static int lx_ptm_read(dev_t dev, struct uio *uiop, cred_t *credp) { int pktio = lx_ptm_lh_pktio_get(DEVT_TO_INDEX(dev)); int err, loop; struct uio uio; struct iovec iovp; ASSERT(uiop->uio_iovcnt > 0); /* * If packet mode has been enabled (via TIOCPKT) we need to pad * all read requests with a leading byte that indicates any * relevant control status information. */ if (pktio != 0) { /* * We'd like to write the control information into * the current buffer but we can't yet. We don't * want to modify userspace memory here only to have * the read operation fail later. So instead * what we'll do here is read one character from the * beginning of the memory pointed to by the uio * structure. This will advance the output pointer * by one. Then when the read completes successfully * we can update the byte that we passed over. Before * we do the read make a copy of the current uiop and * iovec structs so we can write to them later. */ uio = *uiop; iovp = *uiop->uio_iov; uio.uio_iov = &iovp; if (uwritec(uiop) == -1) return (EFAULT); } do { /* * Before we actually attempt a read operation we need * to make sure there's some buffer space to actually * read in some data. We do this because if we're in * pktio mode and the caller only requested one byte, * then we've already used up that one byte and we * don't want to pass this read request. Doing a 0 * byte read (unless there is a problem with the stream * head) always returns succcess. Normally when a streams * read returns 0 bytes we interpret that as an EOF on * the stream (ie, the slave side has been opened and * closed) and we ignore it and re-try the read operation. * So if we pass on a 0 byte read here lx_ptm_read_loop() * will tell us to loop around and we'll end up in an * infinite loop. */ if (uiop->uio_resid == 0) break; /* * Serialize all reads. We need to do this so that we can * properly emulate the behavior of master terminals on Linux. * In reality this serializaion should not pose any kind of * performance problem since it would be very strange to have * multiple threads trying to read from the same master * terminal device concurrently. */ if (lx_ptm_read_start(dev) != 0) return (EINTR); err = lx_ptm_read_loop(dev, uiop, credp, &loop); lx_ptm_read_end(dev); if (err != 0) return (err); } while (loop != 0); if (pktio != 0) { uint8_t pktio_data = TIOCPKT_DATA; /* * Note that the control status information we * pass back is faked up in the sense that we * don't actually report any events, we always * report a status of 0. */ if (uiomove(&pktio_data, 1, UIO_READ, &uio) != 0) return (EFAULT); } return (0); }
lowinit() { #if !defined(GPROF) caddr_t cp; #endif extern int dumpmag; extern int rthashsize; extern int arptab_size; extern int dk_ndrive; extern struct domain unixdomain; #ifdef INET extern struct domain inetdomain; #endif #include "imp.h" #if NIMP > 0 extern struct domain impdomain; #endif #ifdef NS extern struct domain nsdomain; #endif /* cpp messes these up for lint so put them here */ unixdomain.dom_next = domains; domains = &unixdomain; #ifdef INET inetdomain.dom_next = domains; domains = &inetdomain; #endif #if NIMP > 0 impdomain.dom_next = domains; domains = &impdomain; #endif #ifdef NS nsdomain.dom_next = domains; domains = &nsdomain; #endif dumpmag = 0; /* used only by savecore */ rthashsize = rthashsize; /* used by netstat, etc. */ arptab_size = arptab_size; /* used by arp command */ dk_ndrive = dk_ndrive; /* used by vmstat, iostat, etc. */ /* * Pseudo-uses of globals. */ lowinit(); intstack[0] = intstack[1]; maxmem = physmem = freemem = 0; u = u; fixctlrmask(); main(0); Xustray(); /* * Routines called from interrupt vectors. */ panic("Machine check"); printf("Write timeout"); consdin(); consdout(); hardclock((caddr_t)0, 0); softclock((caddr_t)0, 0); trap((unsigned)0, (unsigned)0, (unsigned)0, (unsigned)0); memerr(); /* * Miscellaneous routines called from configurable * drivers. */ disksort((struct buf *)0, (struct buf *)0); (void) uwritec((struct uio *)0); (void) todr(); if (vmemall((struct pte *)0, 0, (struct proc *)0, 0)) return; /* use value */ boothowto = 0; dumpflag = 0; dumpflag = dumpflag; #ifdef KADB bootesym = 0; bootesym = bootesym; #endif #if !defined(GPROF) cp = (caddr_t)&etext; cp = cp; #endif }