static void dl_attach (struct device *parent, struct device *self, void *aux) { struct dl_softc *sc = device_private(self); struct uba_attach_args *ua = aux; sc->sc_iot = ua->ua_iot; sc->sc_ioh = ua->ua_ioh; /* Tidy up the device */ DL_WRITE_WORD(DL_UBA_RCSR, DL_RCSR_RXIE); DL_WRITE_WORD(DL_UBA_XCSR, DL_XCSR_TXIE); /* Initialize our softc structure. Should be done in open? */ sc->sc_tty = ttymalloc(); tty_attach(sc->sc_tty); /* Now register the TX & RX interrupt handlers */ uba_intr_establish(ua->ua_icookie, ua->ua_cvec, dlxint, sc, &sc->sc_tintrcnt); uba_intr_establish(ua->ua_icookie, ua->ua_cvec - 4, dlrint, sc, &sc->sc_rintrcnt); evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, device_xname(&sc->sc_dev), "rintr"); evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, device_xname(&sc->sc_dev), "tintr"); printf("\n"); }
int vconsopen(dev_t dev, int flag, int mode, struct proc *p) { struct vcons_softc *sc; struct tty *tp; int unit = minor(dev); if (unit > vcons_cd.cd_ndevs) return (ENXIO); sc = vcons_cd.cd_devs[unit]; if (sc == NULL) return (ENXIO); if (sc->sc_tty) tp = sc->sc_tty; else tp = sc->sc_tty = ttymalloc(0); tp->t_oproc = vconsstart; tp->t_param = vconsparam; tp->t_dev = dev; if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; ttsetwater(tp); } else if ((tp->t_state & TS_XCLUDE) && suser(p, 0)) return (EBUSY); tp->t_state |= TS_CARR_ON; return ((*linesw[tp->t_line].l_open)(dev, tp, p)); }
void kminit(void) { km_tty[0] = ttymalloc(); km_tty[0]->t_dev = makedev(12, 0); initialized = 1; }
void ucom_attach(struct device *parent, struct device *self, void *aux) { struct ucom_softc *sc = (struct ucom_softc *)self; struct ucom_attach_args *uca = aux; struct tty *tp; if (uca->info != NULL) printf(", %s", uca->info); printf("\n"); sc->sc_udev = uca->device; sc->sc_iface = uca->iface; sc->sc_bulkout_no = uca->bulkout; sc->sc_bulkin_no = uca->bulkin; sc->sc_uhidev = uca->uhidev; sc->sc_ibufsize = uca->ibufsize; sc->sc_ibufsizepad = uca->ibufsizepad; sc->sc_obufsize = uca->obufsize; sc->sc_opkthdrlen = uca->opkthdrlen; sc->sc_methods = uca->methods; sc->sc_parent = uca->arg; sc->sc_portno = uca->portno; tp = ttymalloc(); tp->t_oproc = ucomstart; tp->t_param = ucomparam; sc->sc_tty = tp; sc->sc_cua = 0; rw_init(&sc->sc_lock, "ucomlk"); sc->sc_open = 0; }
/*ARGSUSED*/ int ptcopen(dev_t dev, int flag, int devtype, struct proc *p) { struct pt_softc *pti; struct tty *tp; int error; if ((error = check_pty(minor(dev)))) return (error); pti = pt_softc[minor(dev)]; if (!pti->pt_tty) { tp = pti->pt_tty = ttymalloc(); } else tp = pti->pt_tty; if (tp->t_oproc) return (EIO); tp->t_oproc = ptsstart; (void)(*linesw[tp->t_line].l_modem)(tp, 1); tp->t_lflag &= ~EXTPROC; pti->pt_flags = 0; pti->pt_send = 0; pti->pt_ucntl = 0; return (0); }
int dartopen(dev_t dev, int flag, int mode, struct proc *p) { int s, port; struct dart_info *dart; struct dartsoftc *sc; struct tty *tp; port = DART_PORT(dev); if (dart_cd.cd_ndevs == 0 || port >= NDARTPORTS) return (ENODEV); sc = (struct dartsoftc *)dart_cd.cd_devs[0]; /* the only one */ dart = &sc->sc_dart[port]; s = spltty(); if (dart->tty != NULL) tp = dart->tty; else tp = dart->tty = ttymalloc(); tp->t_oproc = dartstart; tp->t_param = dartparam; tp->t_dev = dev; if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = B9600; dartparam(tp, &tp->t_termios); if (port == CONS_PORT) { /* console is 8N1 */ tp->t_cflag = (CREAD | CS8 | HUPCL); } else { tp->t_cflag = TTYDEF_CFLAG; } ttsetwater(tp); (void)dartmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET); tp->t_state |= TS_CARR_ON; } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { splx(s); return (EBUSY); } /* * Reset the tty pointer, as there could have been a dialout * use of the tty with a dialin open waiting. */ tp->t_dev = dev; splx(s); return ((*linesw[tp->t_line].l_open)(dev, tp)); }
/* * Check if the minor is correct and ensure necessary structures * are properly allocated. */ int check_pty(int minor) { struct pt_softc *pti; rw_enter_write(&pt_softc_lock); if (minor >= npty) { struct pt_softc **newpt; int newnpty; /* check if the requested pty can be granted */ if (minor >= maxptys) goto limit_reached; /* grow pty array by powers of two, up to maxptys */ for (newnpty = npty; newnpty <= minor; newnpty *= 2) ; if (newnpty > maxptys) newnpty = maxptys; newpt = ptyarralloc(newnpty); if (maxptys == npty) { goto limit_reached; } memcpy(newpt, pt_softc, npty * sizeof(struct pt_softc *)); free(pt_softc, M_DEVBUF); pt_softc = newpt; npty = newnpty; } /* * If the entry is not yet allocated, allocate one. */ if (!pt_softc[minor]) { pti = malloc(sizeof(struct pt_softc), M_DEVBUF, M_WAITOK|M_ZERO); pti->pt_tty = ttymalloc(); ptydevname(minor, pti); pt_softc[minor] = pti; } rw_exit_write(&pt_softc_lock); return (0); limit_reached: rw_exit_write(&pt_softc_lock); tablefull("pty"); return (ENXIO); }
static int ofw_dev_open(dev_t dev, int flag, int mode, struct thread *td) { struct tty *tp; int unit; int error, setuptimeout; error = 0; setuptimeout = 0; unit = minor(dev); tp = ofw_tp = dev->si_tty = ttymalloc(ofw_tp); tp->t_oproc = ofw_tty_start; tp->t_param = ofw_tty_param; tp->t_stop = ofw_tty_stop; tp->t_dev = dev; if ((tp->t_state & TS_ISOPEN) == 0) { tp->t_state |= TS_CARR_ON; ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG|CLOCAL; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; ttsetwater(tp); setuptimeout = 1; } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { return (EBUSY); } error = (*linesw[tp->t_line].l_open)(dev, tp); if (error == 0 && setuptimeout) { polltime = hz / OFW_POLL_HZ; if (polltime < 1) { polltime = 1; } ofw_timeouthandle = timeout(ofw_timeout, tp, polltime); } return (error); }
void mtty_attach(struct device *parent, struct device *dev, void *args) { struct magma_softc *sc = (struct magma_softc *)parent; struct mtty_softc *ms = (struct mtty_softc *)dev; int port, chip, chan; sc->ms_mtty = ms; dprintf((" addr 0x%x", ms)); for (port = 0, chip = 0, chan = 0; port < sc->ms_board->mb_nser; port++) { struct mtty_port *mp = &ms->ms_port[port]; struct tty *tp; mp->mp_cd1400 = &sc->ms_cd1400[chip]; if (mp->mp_cd1400->cd_parmode && chan == 0) { /* skip channel 0 if parmode */ chan = 1; } mp->mp_channel = chan; tp = ttymalloc(0); tp->t_oproc = mtty_start; tp->t_param = mtty_param; mp->mp_tty = tp; mp->mp_rbuf = malloc(MTTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT); if (mp->mp_rbuf == NULL) break; mp->mp_rend = mp->mp_rbuf + MTTY_RBUF_SIZE; chan = (chan + 1) % CD1400_NO_OF_CHANNELS; if (chan == 0) chip++; } ms->ms_nports = port; printf(": %d tty%s\n", port, port == 1 ? "" : "s"); }
/*ARGSUSED*/ int ptsopen(dev_t dev, int flag, int devtype, struct proc *p) { struct pt_softc *pti; struct tty *tp; int error; if ((error = check_pty(minor(dev)))) return (error); pti = pt_softc[minor(dev)]; if (!pti->pt_tty) { tp = pti->pt_tty = ttymalloc(); } else tp = pti->pt_tty; if ((tp->t_state & TS_ISOPEN) == 0) { tp->t_state |= TS_WOPEN; ttychars(tp); /* Set up default chars */ tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; ttsetwater(tp); /* would be done in xxparam() */ } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) return (EBUSY); if (tp->t_oproc) /* Ctrlr still around. */ tp->t_state |= TS_CARR_ON; while ((tp->t_state & TS_CARR_ON) == 0) { tp->t_state |= TS_WOPEN; if (flag&FNONBLOCK) break; error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); if (error) return (error); } error = (*linesw[tp->t_line].l_open)(dev, tp); ptcwakeup(tp, FREAD|FWRITE); return (error); }
static int dcons_attach_port(int port, char *name, int flags) { struct dcons_softc *dc; struct tty *tp; dc = &sc[port]; dc->flags = flags; dc->dev = make_dev(&dcons_cdevsw, port, UID_ROOT, GID_WHEEL, 0600, name); tp = ttymalloc(NULL); dc->dev->si_drv1 = (void *)dc; dc->dev->si_tty = tp; tp->t_oproc = dcons_tty_start; tp->t_param = dcons_tty_param; tp->t_stop = nottystop; tp->t_dev = dc->dev; return(0); }
static int dcons_open(dev_t dev, int flag, int mode, struct THREAD *td) { struct tty *tp; int unit, error, s; unit = minor(dev); if (unit != 0) return (ENXIO); tp = dev->si_tty = ttymalloc(dev->si_tty); tp->t_oproc = dcons_tty_start; tp->t_param = dcons_tty_param; tp->t_stop = nottystop; tp->t_dev = dev; error = 0; s = spltty(); if ((tp->t_state & TS_ISOPEN) == 0) { tp->t_state |= TS_CARR_ON; ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG|CLOCAL; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; ttsetwater(tp); } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { splx(s); return (EBUSY); } splx(s); error = (*linesw[tp->t_line].l_open)(dev, tp); return (error); }
int ucom_attach(struct ucom_softc *sc) { struct tty *tp; int unit; unit = device_get_unit(sc->sc_dev); sc->sc_tty = tp = ttymalloc(sc->sc_tty); tp->t_oproc = ucomstart; tp->t_param = ucomparam; tp->t_stop = ucomstop; DPRINTF(("ucom_attach: tty_attach tp = %p\n", tp)); DPRINTF(("ucom_attach: make_dev: ucom%d\n", unit)); sc->dev = make_dev(&ucom_cdevsw, unit | UCOM_CALLOUT_MASK, UID_UUCP, GID_DIALER, 0660, "ucom%d", unit); sc->dev->si_tty = tp; return (0); }
int zstty_attach(device_t dev) { struct zstty_softc *sc; struct tty *tp; char mode[32]; int reset; int baud; int clen; char parity; int stop; char c; sc = device_get_softc(dev); mtx_init(&sc->sc_mtx, "zstty", NULL, MTX_SPIN); sc->sc_dev = dev; sc->sc_iput = sc->sc_iget = sc->sc_ibuf; sc->sc_oget = sc->sc_obuf; tp = ttymalloc(NULL); sc->sc_si = make_dev(&zstty_cdevsw, device_get_unit(dev), UID_ROOT, GID_WHEEL, 0600, "%s", device_get_desc(dev)); sc->sc_si->si_drv1 = sc; sc->sc_si->si_tty = tp; tp->t_dev = sc->sc_si; sc->sc_tty = tp; tp->t_oproc = zsttystart; tp->t_param = zsttyparam; tp->t_stop = zsttystop; tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_cflag = CREAD | CLOCAL | CS8; tp->t_ospeed = TTYDEF_SPEED; tp->t_ispeed = TTYDEF_SPEED; if (zstty_console(dev, mode, sizeof(mode))) { ttychars(tp); /* format: 9600,8,n,1,- */ if (sscanf(mode, "%d,%d,%c,%d,%c", &baud, &clen, &parity, &stop, &c) == 5) { tp->t_ospeed = baud; tp->t_ispeed = baud; tp->t_cflag = CREAD | CLOCAL; switch (clen) { case 5: tp->t_cflag |= CS5; break; case 6: tp->t_cflag |= CS6; break; case 7: tp->t_cflag |= CS7; break; case 8: default: tp->t_cflag |= CS8; break; } if (parity == 'e') tp->t_cflag |= PARENB; else if (parity == 'o') tp->t_cflag |= PARENB | PARODD; if (stop == 2) tp->t_cflag |= CSTOPB; } device_printf(dev, "console %s\n", mode); sc->sc_console = 1; zstty_cons = sc; } else { if ((device_get_unit(dev) & 1) == 0) reset = ZSWR9_A_RESET; else reset = ZSWR9_B_RESET; ZS_WRITE_REG(sc, 9, reset); } return (0); }
void sacom_attach_subr(struct sacom_softc *sc) { bus_addr_t iobase = sc->sc_baseaddr; bus_space_tag_t iot = sc->sc_iot; struct tty *tp; /* XXX Do we need to disable interrupts here? */ if (iot == sacomconstag && iobase == sacomconsaddr) { sacomconsattached = 1; sc->sc_speed = SACOMSPEED(sacomconsrate); /* Make sure the console is always "hardwired". */ delay(10000); /* wait for output to finish */ SET(sc->sc_hwflags, COM_HW_CONSOLE); SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); } tp = ttymalloc(); tp->t_oproc = sacomstart; tp->t_param = sacomparam; tp->t_hwiflow = sacomhwiflow; sc->sc_tty = tp; sc->sc_rbuf = malloc(SACOM_RING_SIZE << 1, M_DEVBUF, M_NOWAIT); sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; sc->sc_rbavail = SACOM_RING_SIZE; if (sc->sc_rbuf == NULL) { printf("%s: unable to allocate ring buffer\n", sc->sc_dev.dv_xname); return; } sc->sc_ebuf = sc->sc_rbuf + (SACOM_RING_SIZE << 1); sc->sc_tbc = 0; tty_attach(tp); if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { int maj; /* locate the major number */ maj = cdevsw_lookup_major(&sacom_cdevsw); cn_tab->cn_dev = makedev(maj, device_unit(&sc->sc_dev)); delay(10000); /* XXX */ printf("%s: console\n", sc->sc_dev.dv_xname); delay(10000); /* XXX */ } sc->sc_si = softint_establish(SOFTINT_SERIAL, sacomsoft, sc); #if NRND > 0 && defined(RND_COM) rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, RND_TYPE_TTY, 0); #endif /* if there are no enable/disable functions, assume the device is always enabled */ if (!sc->enable) sc->enabled = 1; sacom_config(sc); SET(sc->sc_hwflags, COM_HW_DEV_OK); }
int dartopen(dev_t dev, int flag, int mode, struct proc *p) { int s; u_int port, chip; struct dart_info *dart; struct dartsoftc *sc; struct tty *tp; chip = DART_CHIP(dev); port = DART_PORT(dev); if (dart_cd.cd_ndevs <= chip || port >= NDARTPORTS) return (ENODEV); sc = (struct dartsoftc *)dart_cd.cd_devs[chip]; if (sc == NULL) return (ENODEV); dart = &sc->sc_dart[port]; s = spltty(); if (dart->tty != NULL) tp = dart->tty; else tp = dart->tty = ttymalloc(0); tp->t_oproc = dartstart; tp->t_param = dartparam; tp->t_dev = dev; if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); if (tp->t_ispeed == 0) { tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = B9600; if (sc->sc_console && port == CONS_PORT) { /* console is 8N1 */ tp->t_cflag = (CREAD | CS8 | HUPCL); } else { tp->t_cflag = TTYDEF_CFLAG; } } if (dart->dart_swflags & TIOCFLAG_CLOCAL) tp->t_cflag |= CLOCAL; if (dart->dart_swflags & TIOCFLAG_CRTSCTS) tp->t_cflag |= CRTSCTS; if (dart->dart_swflags & TIOCFLAG_MDMBUF) tp->t_cflag |= MDMBUF; dartparam(tp, &tp->t_termios); ttsetwater(tp); (void)dartmctl(sc, port, TIOCM_DTR | TIOCM_RTS, DMSET); tp->t_state |= TS_CARR_ON; } else if (tp->t_state & TS_XCLUDE && suser(p, 0) != 0) { splx(s); return (EBUSY); } /* * Reset the tty pointer, as there could have been a dialout * use of the tty with a dialin open waiting. */ tp->t_dev = dev; splx(s); return ((*linesw[tp->t_line].l_open)(dev, tp, p)); }
int com_activate(struct device *self, int act) { struct com_softc *sc = (struct com_softc *)self; int s, rv = 0; switch (act) { case DVACT_SUSPEND: if (timeout_del(&sc->sc_dtr_tmo)) { /* Make sure DTR gets raised upon resume. */ SET(sc->sc_mcr, MCR_DTR | MCR_RTS); } timeout_del(&sc->sc_diag_tmo); break; case DVACT_RESUME: com_resume(sc); break; case DVACT_DEACTIVATE: #ifdef KGDB if (sc->sc_hwflags & (COM_HW_CONSOLE|COM_HW_KGDB)) { #else if (sc->sc_hwflags & COM_HW_CONSOLE) { #endif /* KGDB */ rv = EBUSY; break; } s = spltty(); if (sc->disable != NULL && sc->enabled != 0) { (*sc->disable)(sc); sc->enabled = 0; } splx(s); break; } return (rv); } int comopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = DEVUNIT(dev); struct com_softc *sc; bus_space_tag_t iot; bus_space_handle_t ioh; struct tty *tp; int s; int error = 0; if (unit >= com_cd.cd_ndevs) return ENXIO; sc = com_cd.cd_devs[unit]; if (!sc) return ENXIO; #ifdef KGDB /* * If this is the kgdb port, no other use is permitted. */ if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) return (EBUSY); #endif /* KGDB */ s = spltty(); if (!sc->sc_tty) { tp = sc->sc_tty = ttymalloc(1000000); } else tp = sc->sc_tty; splx(s); tp->t_oproc = comstart; tp->t_param = comparam; tp->t_dev = dev; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_WOPEN); ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; #ifdef COM_CONSOLE if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { tp->t_cflag = comconscflag; tp->t_ispeed = tp->t_ospeed = comconsrate; } else #endif { tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = comdefaultrate; } if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) SET(tp->t_cflag, CLOCAL); if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) SET(tp->t_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) SET(tp->t_cflag, MDMBUF); tp->t_lflag = TTYDEF_LFLAG; s = spltty(); sc->sc_initialize = 1; comparam(tp, &tp->t_termios); ttsetwater(tp); sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; iot = sc->sc_iot; ioh = sc->sc_ioh; /* * Wake up the sleepy heads. */ if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); bus_space_write_1(iot, ioh, com_efr, EFR_ECB); bus_space_write_1(iot, ioh, com_ier, 0); bus_space_write_1(iot, ioh, com_efr, 0); bus_space_write_1(iot, ioh, com_lcr, 0); break; case COM_UART_TI16750: bus_space_write_1(iot, ioh, com_ier, 0); break; case COM_UART_PXA2X0: bus_space_write_1(iot, ioh, com_ier, IER_EUART); break; } } if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST; u_int8_t lcr; if (tp->t_ispeed <= 1200) fifo |= FIFO_TRIGGER_1; else if (tp->t_ispeed <= 38400) fifo |= FIFO_TRIGGER_4; else fifo |= FIFO_TRIGGER_8; if (sc->sc_uarttype == COM_UART_TI16750) { fifo |= FIFO_ENABLE_64BYTE; lcr = bus_space_read_1(iot, ioh, com_lcr); bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); } /* * (Re)enable and drain FIFOs. * * Certain SMC chips cause problems if the FIFOs are * enabled while input is ready. Turn off the FIFO * if necessary to clear the input. Test the input * ready bit after enabling the FIFOs to handle races * between enabling and fresh input. * * Set the FIFO threshold based on the receive speed. */ for (;;) { bus_space_write_1(iot, ioh, com_fifo, 0); delay(100); (void) bus_space_read_1(iot, ioh, com_data); bus_space_write_1(iot, ioh, com_fifo, fifo | FIFO_RCV_RST | FIFO_XMT_RST); delay(100); if(!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) break; } if (sc->sc_uarttype == COM_UART_TI16750) bus_space_write_1(iot, ioh, com_lcr, lcr); } /* Flush any pending I/O. */ while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) (void) bus_space_read_1(iot, ioh, com_data); /* You turn me on, baby! */ sc->sc_mcr = MCR_DTR | MCR_RTS; if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN)) SET(sc->sc_mcr, MCR_IENABLE); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC; #ifdef COM_PXA2X0 if (sc->sc_uarttype == COM_UART_PXA2X0) sc->sc_ier |= IER_EUART | IER_ERXTOUT; #endif bus_space_write_1(iot, ioh, com_ier, sc->sc_ier); sc->sc_msr = bus_space_read_1(iot, ioh, com_msr); if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) || ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF)) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); #ifdef COM_PXA2X0 if (sc->sc_uarttype == COM_UART_PXA2X0 && ISSET(sc->sc_hwflags, COM_HW_SIR)) { bus_space_write_1(iot, ioh, com_isr, ISR_RECV); #ifdef __zaurus__ scoop_set_irled(1); #endif } #endif } else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p, 0) != 0) return EBUSY; else s = spltty(); if (DEVCUA(dev)) { if (ISSET(tp->t_state, TS_ISOPEN)) { /* Ah, but someone already is dialed in... */ splx(s); return EBUSY; } sc->sc_cua = 1; /* We go into CUA mode. */ } else { /* tty (not cua) device; wait for carrier if necessary. */ if (ISSET(flag, O_NONBLOCK)) { if (sc->sc_cua) { /* Opening TTY non-blocking... but the CUA is busy. */ splx(s); return EBUSY; } } else { while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON))) { SET(tp->t_state, TS_WOPEN); error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); /* * If TS_WOPEN has been reset, that means the cua device * has been closed. We don't want to fail in that case, * so just go around again. */ if (error && ISSET(tp->t_state, TS_WOPEN)) { CLR(tp->t_state, TS_WOPEN); if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN)) compwroff(sc); splx(s); return error; } } } } splx(s); return (*linesw[tp->t_line].l_open)(dev, tp, p); }
void at91usart_attach_subr(struct at91usart_softc *sc, struct at91bus_attach_args *sa) { struct tty *tp; int err; printf("\n"); if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0, &sc->sc_ioh)) panic("%s: Cannot map registers", device_xname(sc->sc_dev)); sc->sc_iot = sa->sa_iot; sc->sc_hwbase = sa->sa_addr; sc->sc_dmat = sa->sa_dmat; sc->sc_pid = sa->sa_pid; /* allocate fifos */ err = at91pdc_alloc_fifo(sc->sc_dmat, &sc->sc_rx_fifo, AT91USART_RING_SIZE, BUS_DMA_READ | BUS_DMA_STREAMING); if (err) panic("%s: cannot allocate rx fifo", device_xname(sc->sc_dev)); err = at91pdc_alloc_fifo(sc->sc_dmat, &sc->sc_tx_fifo, AT91USART_RING_SIZE, BUS_DMA_WRITE | BUS_DMA_STREAMING); if (err) panic("%s: cannot allocate tx fifo", device_xname(sc->sc_dev)); /* initialize uart */ at91_peripheral_clock(sc->sc_pid, 1); at91usart_writereg(sc, US_IDR, -1); at91usart_writereg(sc, US_RTOR, 12); // 12-bit timeout at91usart_writereg(sc, US_PDC + PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); at91_intr_establish(sa->sa_pid, IPL_TTY, INTR_HIGH_LEVEL, at91usart_intr, sc); USART_INIT(sc, 115200U); #ifdef NOTYET if (sc->sc_iot == usart_cn_sc.sc_iot && sc->sc_hwbase == usart_cn_sc.sc_hwbase) { usart_cn_sc.sc_attached = 1; /* Make sure the console is always "hardwired". */ delay(10000); /* wait for output to finish */ SET(sc->sc_hwflags, COM_HW_CONSOLE); SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); SET(sc->sc_ier, USART_INT_RXRDY); USARTREG(USART_IER) = USART_INT_RXRDY; // @@@@@ } #endif // NOTYET tp = ttymalloc(); tp->t_oproc = at91usart_start; tp->t_param = at91usart_param; tp->t_hwiflow = at91usart_hwiflow; sc->sc_tty = tp; tty_attach(tp); #if NOTYET if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { int maj; /* locate the major number */ maj = cdevsw_lookup_major(&at91usart_cdevsw); cn_tab->cn_dev = makedev(maj, device_unit(sc->sc_dev)); aprint_normal("%s: console (maj %u min %u cn_dev %u)\n", device_xname(sc->sc_dev), maj, device_unit(sc->sc_dev), cn_tab->cn_dev); } #endif /* NOTYET */ sc->sc_si = softint_establish(SOFTINT_SERIAL, at91usart_soft, sc); #if NRND > 0 && defined(RND_COM) rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), RND_TYPE_TTY, 0); #endif /* if there are no enable/disable functions, assume the device is always enabled */ if (!sc->enable) sc->enabled = 1; /* XXX configure register */ /* xxx_config(sc) */ SET(sc->sc_hwflags, COM_HW_DEV_OK); }
static int ucom_attach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) { struct tty *tp; char buf[32]; /* temporary TTY device name buffer */ cdev_t dev; kprintf("attach tty\n"); lwkt_gettoken(&tty_token); kprintf("malloc: "); sc->sc_tty = tp = ttymalloc(sc->sc_tty); tp->t_oproc = ucom_start; tp->t_param = ucom_param; tp->t_stop = ucom_stop; if (tp == NULL) { lwkt_reltoken(&tty_token); return (ENOMEM); } /* Check if the client has a custom TTY name */ buf[0] = '\0'; if (sc->sc_callback->ucom_tty_name) { sc->sc_callback->ucom_tty_name(sc, buf, sizeof(buf), ssc->sc_unit, sc->sc_subunit); } if (buf[0] == 0) { /* Use default TTY name */ if (ssc->sc_subunits > 1) { /* multiple modems in one */ ksnprintf(buf, sizeof(buf), UCOM_TTY_PREFIX "%u.%u", ssc->sc_unit, sc->sc_subunit); } else { /* single modem */ ksnprintf(buf, sizeof(buf), UCOM_TTY_PREFIX "%u", ssc->sc_unit); } } dev = make_dev(&ucom_ops, ssc->sc_unit | 0x80, // XXX UCOM_CALLOUT_MASK, UID_UUCP, GID_DIALER, 0660, buf, ssc->sc_unit); dev->si_tty = tp; sc->sc_tty = tp; dev->si_drv1 = sc; DPRINTF("ttycreate: %s\n", buf); /* Check if this device should be a console */ if ((ucom_cons_softc == NULL) && (ssc->sc_unit == ucom_cons_unit) && (sc->sc_subunit == ucom_cons_subunit)) { DPRINTF("unit %d subunit %d is console", ssc->sc_unit, sc->sc_subunit); ucom_cons_softc = sc; /* XXXDF tty_init_console(tp, ucom_cons_baud); */ tp->t_termios.c_ispeed = ucom_cons_baud; tp->t_termios.c_ospeed = ucom_cons_baud; UCOM_MTX_LOCK(ucom_cons_softc); ucom_cons_rx_low = 0; ucom_cons_rx_high = 0; ucom_cons_tx_low = 0; ucom_cons_tx_high = 0; sc->sc_flag |= UCOM_FLAG_CONSOLE; ucom_open(ucom_cons_softc); ucom_param(tp, &tp->t_termios); UCOM_MTX_UNLOCK(ucom_cons_softc); } lwkt_reltoken(&tty_token); return (0); }
int comopen(dev_t dev, int flag, int mode, struct lwp *l) { struct com_softc *sc; int iobase; struct tty *tp; int s; int error = 0; sc = device_lookup_private(&xcom_cd, COMUNIT(dev)); if (!sc) return ENXIO; if (!sc->sc_tty) { tp = sc->sc_tty = ttymalloc(); tty_attach(tp); } else tp = sc->sc_tty; tp->t_oproc = comstart; tp->t_param = comparam; tp->t_dev = dev; if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); s = spltty(); if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) SET(tp->t_cflag, CLOCAL); if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) SET(tp->t_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) SET(tp->t_cflag, MDMBUF); tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = comdefaultrate; comparam(tp, &tp->t_termios); ttsetwater(tp); if (comsopen++ == 0) callout_reset(&com_poll_ch, 1, compollin, NULL); sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; iobase = sc->sc_iobase; #ifdef COM_HAYESP /* Setup the ESP board */ if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) { int hayespbase = sc->sc_hayespbase; outb(iobase + com_fifo, FIFO_DMA_MODE|FIFO_ENABLE| FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8); /* Set 16550 compatibility mode */ outb(hayespbase + HAYESP_CMD1, HAYESP_SETMODE); outb(hayespbase + HAYESP_CMD2, HAYESP_MODE_FIFO|HAYESP_MODE_RTS| HAYESP_MODE_SCALE); /* Set RTS/CTS flow control */ outb(hayespbase + HAYESP_CMD1, HAYESP_SETFLOWTYPE); outb(hayespbase + HAYESP_CMD2, HAYESP_FLOW_RTS); outb(hayespbase + HAYESP_CMD2, HAYESP_FLOW_CTS); /* Set flow control levels */ outb(hayespbase + HAYESP_CMD1, HAYESP_SETRXFLOW); outb(hayespbase + HAYESP_CMD2, HAYESP_HIBYTE(HAYESP_RXHIWMARK)); outb(hayespbase + HAYESP_CMD2, HAYESP_LOBYTE(HAYESP_RXHIWMARK)); outb(hayespbase + HAYESP_CMD2, HAYESP_HIBYTE(HAYESP_RXLOWMARK)); outb(hayespbase + HAYESP_CMD2, HAYESP_LOBYTE(HAYESP_RXLOWMARK)); } else #endif if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) /* Set the FIFO threshold based on the receive speed. */ outb(pio(iobase , com_fifo), FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); /* flush any pending I/O */ while (ISSET(inb(pio(iobase , com_lsr)), LSR_RXRDY)) (void) inb(pio(iobase , com_data)); /* you turn me on, baby */ sc->sc_mcr = MCR_DTR | MCR_RTS; if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN)) SET(sc->sc_mcr, MCR_IENABLE | MCR_DRS); /* */ outb(pio(iobase , com_mcr), sc->sc_mcr); sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC; outb(pio(iobase , com_ier), sc->sc_ier); sc->sc_msr = inb(pio(iobase , com_msr)); if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF)) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); } splx(s); error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); if (!error) error = (*tp->t_linesw->l_open)(dev, tp); /* XXX cleanup on error */ return error; }
void zstty_attach(struct device *parent, struct device *self, void *aux) { struct zsc_softc *zsc = (struct zsc_softc *)parent; struct zstty_softc *zst = (struct zstty_softc *)self; struct cfdata *cf = self->dv_cfdata; struct zsc_attach_args *args = aux; struct zs_chanstate *cs; struct tty *tp; int channel, s, tty_unit; dev_t dev; const char *i, *o; int dtr_on; int resetbit; timeout_set(&zst->zst_diag_ch, zstty_diag, zst); tty_unit = zst->zst_dev.dv_unit; channel = args->channel; cs = zsc->zsc_cs[channel]; cs->cs_private = zst; cs->cs_ops = &zsops_tty; zst->zst_cs = cs; zst->zst_swflags = cf->cf_flags; /* softcar, etc. */ zst->zst_hwflags = args->hwflags; dev = makedev(zs_major, tty_unit); if (zst->zst_swflags) printf(" flags 0x%x", zst->zst_swflags); if (ISSET(zst->zst_hwflags, ZS_HWFLAG_NO_DCD)) SET(zst->zst_swflags, TIOCFLAG_SOFTCAR); /* * Check whether we serve as a console device. * XXX - split console input/output channels aren't * supported yet on /dev/console */ i = o = NULL; if ((zst->zst_hwflags & ZS_HWFLAG_CONSOLE_INPUT) != 0) { i = " input"; if ((args->hwflags & ZS_HWFLAG_USE_CONSDEV) != 0) { args->consdev->cn_dev = dev; cn_tab->cn_pollc = args->consdev->cn_pollc; cn_tab->cn_getc = args->consdev->cn_getc; } cn_tab->cn_dev = dev; } if ((zst->zst_hwflags & ZS_HWFLAG_CONSOLE_OUTPUT) != 0) { o = " output"; if ((args->hwflags & ZS_HWFLAG_USE_CONSDEV) != 0) { cn_tab->cn_putc = args->consdev->cn_putc; } cn_tab->cn_dev = dev; } if (i != NULL || o != NULL) { printf(": console%s", i ? (o ? "" : i) : o); } #ifdef KGDB if (zs_check_kgdb(cs, dev)) { /* * Allow kgdb to "take over" this port. Returns true * if this serial port is in-use by kgdb. */ printf(": kgdb\n"); /* * This is the kgdb port (exclusive use) * so skip the normal attach code. */ return; } #endif #if defined(__sparc__) || defined(__sparc64__) if (strcmp(args->type, "keyboard") == 0 || strcmp(args->type, "mouse") == 0) printf(": %s", args->type); #endif printf("\n"); tp = ttymalloc(0); tp->t_dev = dev; tp->t_oproc = zsstart; tp->t_param = zsparam; tp->t_hwiflow = zshwiflow; zst->zst_tty = tp; zst->zst_rbuf = mallocarray(zstty_rbuf_size, 2, M_DEVBUF, M_WAITOK); zst->zst_ebuf = zst->zst_rbuf + (zstty_rbuf_size * 2); /* Disable the high water mark. */ zst->zst_r_hiwat = 0; zst->zst_r_lowat = 0; zst->zst_rbget = zst->zst_rbput = zst->zst_rbuf; zst->zst_rbavail = zstty_rbuf_size; /* if there are no enable/disable functions, assume the device is always enabled */ if (!cs->enable) cs->enabled = 1; /* * Hardware init */ dtr_on = 0; resetbit = 0; if (ISSET(zst->zst_hwflags, ZS_HWFLAG_CONSOLE)) { /* Call zsparam similar to open. */ struct termios t; /* Wait a while for previous console output to complete */ DELAY(10000); /* Setup the "new" parameters in t. */ t.c_ispeed = 0; t.c_ospeed = cs->cs_defspeed; t.c_cflag = cs->cs_defcflag; s = splzs(); /* * Turn on receiver and status interrupts. * We defer the actual write of the register to zsparam(), * but we must make sure status interrupts are turned on by * the time zsparam() reads the initial rr0 state. */ SET(cs->cs_preg[1], ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE); splx(s); /* Make sure zsparam will see changes. */ tp->t_ospeed = 0; (void)zsparam(tp, &t); /* Make sure DTR is on now. */ dtr_on = 1; } else if (!ISSET(zst->zst_hwflags, ZS_HWFLAG_NORESET)) { /* Not the console; may need reset. */ resetbit = (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET; } s = splzs(); if (resetbit) zs_write_reg(cs, 9, resetbit); zs_modem(zst, dtr_on); splx(s); }
int iteopen(dev_t dev, int mode, int devtype, struct lwp *l) { struct ite_softc *ip; struct tty *tp; int error, first, unit; unit = ITEUNIT(dev); first = 0; if (unit >= ite_cd.cd_ndevs) return ENXIO; ip = getitesp(dev); if (ip == NULL) return ENXIO; if ((ip->flags & ITE_ATTACHED) == 0) return ENXIO; if (ip->tp == NULL) { tp = ip->tp = ttymalloc(); tty_attach(tp); } else tp = ip->tp; if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); if ((ip->flags & ITE_ACTIVE) == 0) { ite_on(dev, 0); first = 1; } tp->t_oproc = itestart; tp->t_param = ite_param; tp->t_dev = dev; if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; tp->t_state = TS_CARR_ON; ttsetwater(tp); } error = ttyopen(tp, 0, mode & O_NONBLOCK); if (error) goto bad; error = tp->t_linesw->l_open(dev, tp); if (error) goto bad; tp->t_winsize.ws_row = ip->rows; tp->t_winsize.ws_col = ip->cols; kbdenable(); return (0); bad: if (first) ite_off(dev, 0); return (error); }
int imxuartopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = DEVUNIT(dev); struct imxuart_softc *sc; bus_space_tag_t iot; bus_space_handle_t ioh; struct tty *tp; int s; int error = 0; if (unit >= imxuart_cd.cd_ndevs) return ENXIO; sc = imxuart_cd.cd_devs[unit]; if (sc == NULL) return ENXIO; s = spltty(); if (sc->sc_tty == NULL) tp = sc->sc_tty = ttymalloc(0); else tp = sc->sc_tty; splx(s); tp->t_oproc = imxuart_start; tp->t_param = imxuart_param; tp->t_dev = dev; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_WOPEN); ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) tp->t_cflag = imxuartconscflag; else tp->t_cflag = TTYDEF_CFLAG; if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) SET(tp->t_cflag, CLOCAL); if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) SET(tp->t_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) SET(tp->t_cflag, MDMBUF); tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = imxuartdefaultrate; s = spltty(); sc->sc_initialize = 1; imxuart_param(tp, &tp->t_termios); ttsetwater(tp); sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; sc->sc_ibufhigh = sc->sc_ibuf + IMXUART_IHIGHWATER; sc->sc_ibufend = sc->sc_ibuf + IMXUART_IBUFSIZE; iot = sc->sc_iot; ioh = sc->sc_ioh; sc->sc_ucr1 = bus_space_read_2(iot, ioh, IMXUART_UCR1); sc->sc_ucr2 = bus_space_read_2(iot, ioh, IMXUART_UCR2); sc->sc_ucr3 = bus_space_read_2(iot, ioh, IMXUART_UCR3); sc->sc_ucr4 = bus_space_read_2(iot, ioh, IMXUART_UCR4); /* interrupt after one char on tx/rx */ /* reference frequency divider: 1 */ bus_space_write_2(iot, ioh, IMXUART_UFCR, 1 << IMXUART_FCR_TXTL_SH | 5 << IMXUART_FCR_RFDIV_SH | 1 << IMXUART_FCR_RXTL_SH); bus_space_write_2(iot, ioh, IMXUART_UBIR, (imxuartdefaultrate / 100) - 1); /* formula: clk / (rfdiv * 1600) */ bus_space_write_2(iot, ioh, IMXUART_UBMR, (imxccm_get_uartclk() * 1000) / 1600); SET(sc->sc_ucr1, IMXUART_CR1_EN|IMXUART_CR1_RRDYEN); SET(sc->sc_ucr2, IMXUART_CR2_TXEN|IMXUART_CR2_RXEN); bus_space_write_2(iot, ioh, IMXUART_UCR1, sc->sc_ucr1); bus_space_write_2(iot, ioh, IMXUART_UCR2, sc->sc_ucr2); /* sc->sc_mcr = MCR_DTR | MCR_RTS; XXX */ SET(sc->sc_ucr3, IMXUART_CR3_DSR); /* XXX */ bus_space_write_2(iot, ioh, IMXUART_UCR3, sc->sc_ucr3); SET(tp->t_state, TS_CARR_ON); /* XXX */ } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) return EBUSY; else s = spltty(); if (DEVCUA(dev)) { if (ISSET(tp->t_state, TS_ISOPEN)) { splx(s); return EBUSY; } sc->sc_cua = 1; } else { /* tty (not cua) device; wait for carrier if necessary */ if (ISSET(flag, O_NONBLOCK)) { if (sc->sc_cua) { /* Opening TTY non-blocking... but the CUA is busy */ splx(s); return EBUSY; } } else { while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON))) { SET(tp->t_state, TS_WOPEN); error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); /* * If TS_WOPEN has been reset, that means the * cua device has been closed. We don't want * to fail in that case, * so just go around again. */ if (error && ISSET(tp->t_state, TS_WOPEN)) { CLR(tp->t_state, TS_WOPEN); if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN)) imxuart_pwroff(sc); splx(s); return error; } } } } splx(s); return (*linesw[tp->t_line].l_open)(dev,tp,p); }
int viocon_port_create(struct viocon_softc *sc, int portidx) { struct virtio_softc *vsc = sc->sc_virtio; int rxidx, txidx, allocsize, nsegs; char name[6]; struct viocon_port *vp; caddr_t kva; struct tty *tp; vp = malloc(sizeof(*vp), M_DEVBUF, M_WAITOK|M_CANFAIL|M_ZERO); if (vp == NULL) return ENOMEM; sc->sc_ports[portidx] = vp; vp->vp_sc = sc; DBGPRINT("vp: %p\n", vp); if (portidx == 0) rxidx = 0; else rxidx = 2 * (portidx + 1); txidx = rxidx + 1; snprintf(name, sizeof(name), "p%drx", portidx); if (virtio_alloc_vq(vsc, &vsc->sc_vqs[rxidx], rxidx, BUFSIZE, 1, name) != 0) { printf("\nCan't alloc %s virtqueue\n", name); goto err; } vp->vp_rx = &vsc->sc_vqs[rxidx]; vp->vp_rx->vq_done = viocon_rx_intr; vp->vp_si = softintr_establish(IPL_TTY, viocon_rx_soft, vp); DBGPRINT("rx: %p\n", vp->vp_rx); snprintf(name, sizeof(name), "p%dtx", portidx); if (virtio_alloc_vq(vsc, &vsc->sc_vqs[txidx], txidx, BUFSIZE, 1, name) != 0) { printf("\nCan't alloc %s virtqueue\n", name); goto err; } vp->vp_tx = &vsc->sc_vqs[txidx]; vp->vp_tx->vq_done = viocon_tx_intr; DBGPRINT("tx: %p\n", vp->vp_tx); vsc->sc_nvqs += 2; allocsize = (vp->vp_rx->vq_num + vp->vp_tx->vq_num) * BUFSIZE; if (bus_dmamap_create(vsc->sc_dmat, allocsize, 1, allocsize, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &vp->vp_dmamap) != 0) goto err; if (bus_dmamem_alloc(vsc->sc_dmat, allocsize, 8, 0, &vp->vp_dmaseg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0) goto err; if (bus_dmamem_map(vsc->sc_dmat, &vp->vp_dmaseg, nsegs, allocsize, &kva, BUS_DMA_NOWAIT) != 0) goto err; if (bus_dmamap_load(vsc->sc_dmat, vp->vp_dmamap, kva, allocsize, NULL, BUS_DMA_NOWAIT) != 0) goto err; vp->vp_rx_buf = (unsigned char *)kva; /* * XXX use only a small circular tx buffer instead of many BUFSIZE buffers? */ vp->vp_tx_buf = vp->vp_rx_buf + vp->vp_rx->vq_num * BUFSIZE; if (vsc->sc_features & VIRTIO_CONSOLE_F_SIZE) { vp->vp_cols = virtio_read_device_config_2(vsc, VIRTIO_CONSOLE_COLS); vp->vp_rows = virtio_read_device_config_2(vsc, VIRTIO_CONSOLE_ROWS); } tp = ttymalloc(1000000); tp->t_oproc = vioconstart; tp->t_param = vioconparam; tp->t_hwiflow = vioconhwiflow; tp->t_dev = (sc->sc_dev.dv_unit << 4) | portidx; vp->vp_tty = tp; DBGPRINT("tty: %p\n", tp); virtio_start_vq_intr(vsc, vp->vp_rx); virtio_start_vq_intr(vsc, vp->vp_tx); return 0; err: panic("%s failed", __func__); return -1; }
void sabtty_attach(struct device *parent, struct device *self, void *aux) { struct sabtty_softc *sc = (struct sabtty_softc *)self; struct sabtty_attach_args *sa = aux; int r; int maj; int is_kgdb = 0; #ifdef KGDB is_kgdb = sab_kgdb_check(sc); #endif if (!is_kgdb) { sc->sc_tty = ttymalloc(); if (sc->sc_tty == NULL) { aprint_normal(": failed to allocate tty\n"); return; } tty_attach(sc->sc_tty); sc->sc_tty->t_oproc = sabtty_start; sc->sc_tty->t_param = sabtty_param; } sc->sc_parent = (struct sab_softc *)parent; sc->sc_bt = sc->sc_parent->sc_bt; sc->sc_portno = sa->sbt_portno; sc->sc_rend = sc->sc_rbuf + SABTTY_RBUF_SIZE; switch (sa->sbt_portno) { case 0: /* port A */ sc->sc_pvr_dtr = SAB_PVR_DTR_A; sc->sc_pvr_dsr = SAB_PVR_DSR_A; r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh, SAB_CHAN_A, SAB_CHANLEN, &sc->sc_bh); break; case 1: /* port B */ sc->sc_pvr_dtr = SAB_PVR_DTR_B; sc->sc_pvr_dsr = SAB_PVR_DSR_B; r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh, SAB_CHAN_B, SAB_CHANLEN, &sc->sc_bh); break; default: aprint_normal(": invalid channel: %u\n", sa->sbt_portno); return; } if (r != 0) { aprint_normal(": failed to allocate register subregion\n"); return; } sabtty_console_flags(sc); if (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) { struct termios t; const char *acc; /* Let residual prom output drain */ DELAY(100000); switch (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) { case SABTTYF_CONS_IN: acc = "input"; break; case SABTTYF_CONS_OUT: acc = "output"; break; case SABTTYF_CONS_IN|SABTTYF_CONS_OUT: default: acc = "i/o"; break; } t.c_ispeed= 0; t.c_ospeed = 9600; t.c_cflag = CREAD | CS8 | HUPCL; sc->sc_tty->t_ospeed = 0; sabttyparam(sc, sc->sc_tty, &t); if (sc->sc_flags & SABTTYF_CONS_IN) { sabtty_cons_input = sc; cn_tab->cn_pollc = sab_cnpollc; cn_tab->cn_getc = sab_cngetc; maj = cdevsw_lookup_major(&sabtty_cdevsw); cn_tab->cn_dev = makedev(maj, device_unit(self)); shutdownhook_establish(sabtty_shutdown, sc); cn_init_magic(&sabtty_cnm_state); cn_set_magic("\047\001"); /* default magic is BREAK */ } if (sc->sc_flags & SABTTYF_CONS_OUT) { sabtty_tec_wait(sc); sabtty_cons_output = sc; cn_tab->cn_putc = sab_cnputc; maj = cdevsw_lookup_major(&sabtty_cdevsw); cn_tab->cn_dev = makedev(maj, device_unit(self)); } aprint_normal(": console %s", acc); } else { /* Not a console... */ sabtty_reset(sc); #ifdef KGDB if (is_kgdb) { sab_kgdb_init(sc); aprint_normal(": kgdb"); } #endif } aprint_normal("\n"); }
void sbscn_attach_channel(struct sbscn_softc *sc, int chan, int intr) { struct sbscn_channel *ch = &sc->sc_channels[chan]; u_long chan_addr; struct tty *tp; ch->ch_sc = sc; ch->ch_num = chan; chan_addr = sc->sc_addr + (0x100 * chan); ch->ch_base = (void *)MIPS_PHYS_TO_KSEG1(chan_addr); ch->ch_isr_base = (void *)MIPS_PHYS_TO_KSEG1(sc->sc_addr + 0x220 + (0x20 * chan)); ch->ch_imr_base = (void *)MIPS_PHYS_TO_KSEG1(sc->sc_addr + 0x230 + (0x20 * chan)); #ifdef XXXCGDnotyet ch->ch_inchg_base = (void *)MIPS_PHYS_TO_KSEG1(sc->sc_addr + 0x2d0 + (0x10 * chan)); #endif ch->ch_i_dcd = ch->ch_i_dcd_pin = 0 /* XXXCGD */; ch->ch_i_cts = ch->ch_i_cts_pin = 0 /* XXXCGD */; ch->ch_i_dsr = ch->ch_i_dsr_pin = 0 /* XXXCGD */; ch->ch_i_ri = ch->ch_i_ri_pin = 0 /* XXXCGD */; ch->ch_i_mask = ch->ch_i_dcd | ch->ch_i_cts | ch->ch_i_dsr | ch->ch_i_ri; ch->ch_o_dtr = ch->ch_o_dtr_pin = 0 /* XXXCGD */; ch->ch_o_rts = ch->ch_o_rts_pin = 0 /* XXXCGD */; ch->ch_o_mask = ch->ch_o_dtr | ch->ch_o_rts; ch->ch_intrhand = cpu_intr_establish(intr, IPL_SERIAL, sbscn_intr, ch); callout_init(&ch->ch_diag_callout, 0); /* Disable interrupts before configuring the device. */ ch->ch_imr = 0; WRITE_REG(ch->ch_imr_base, ch->ch_imr); if (sbscn_cons_present && sbscn_cons_addr == chan_addr && sbscn_cons_chan == chan) { sbscn_cons_attached = 1; /* Make sure the console is always "hardwired". */ delay(1000); /* wait for output to finish */ SET(ch->ch_hwflags, SBSCN_HW_CONSOLE); SET(ch->ch_swflags, TIOCFLAG_SOFTCAR); } tp = ttymalloc(); tp->t_oproc = sbscn_start; tp->t_param = sbscn_param; tp->t_hwiflow = sbscn_hwiflow; ch->ch_tty = tp; ch->ch_rbuf = malloc(sbscn_rbuf_size << 1, M_DEVBUF, M_NOWAIT); if (ch->ch_rbuf == NULL) { printf("%s: channel %d: unable to allocate ring buffer\n", sc->sc_dev.dv_xname, chan); return; } ch->ch_ebuf = ch->ch_rbuf + (sbscn_rbuf_size << 1); tty_attach(tp); if (ISSET(ch->ch_hwflags, SBSCN_HW_CONSOLE)) { int maj; /* locate the major number */ maj = cdevsw_lookup_major(&sbscn_cdevsw); cn_tab->cn_dev = makedev(maj, (device_unit(&sc->sc_dev) << 1) + chan); printf("%s: channel %d: console\n", sc->sc_dev.dv_xname, chan); } #ifdef KGDB /* * Allow kgdb to "take over" this port. If this is * the kgdb device, it has exclusive use. */ if (sbscn_kgdb_present && sbscn_kgdb_addr == chan_addr && sbscn_kgdb_chan == chan) { sbscn_kgdb_attached = 1; SET(sc->sc_hwflags, SBSCN_HW_KGDB); printf("%s: channel %d: kgdb\n", sc->sc_dev.dv_xname, chan); } #endif ch->ch_si = softint_establish(SOFTINT_SERIAL, sbscn_soft, ch); #if NRND > 0 && defined(RND_SBSCN) rnd_attach_source(&ch->ch_rnd_source, sc->sc_dev.dv_xname, RND_TYPE_TTY, 0); #endif sbscn_config(ch); SET(ch->ch_hwflags, SBSCN_HW_DEV_OK); }