int altera_jtag_uart_attach(struct altera_jtag_uart_softc *sc) { struct tty *tp; int error; AJU_LOCK_INIT(sc); /* * XXXRW: Currently, we detect the console solely based on it using a * reserved address, and borrow console-level locks and buffer if so. * Is there a better way? */ if (rman_get_start(sc->ajus_mem_res) == BERI_UART_BASE) { sc->ajus_lockp = &aju_cons_lock; sc->ajus_buffer_validp = &aju_cons_buffer_valid; sc->ajus_buffer_datap = &aju_cons_buffer_data; sc->ajus_jtag_presentp = &aju_cons_jtag_present; sc->ajus_jtag_missedp = &aju_cons_jtag_missed; sc->ajus_flags |= ALTERA_JTAG_UART_FLAG_CONSOLE; } else { sc->ajus_lockp = &sc->ajus_lock; sc->ajus_buffer_validp = &sc->ajus_buffer_valid; sc->ajus_buffer_datap = &sc->ajus_buffer_data; sc->ajus_jtag_presentp = &sc->ajus_jtag_present; sc->ajus_jtag_missedp = &sc->ajus_jtag_missed; } /* * Disable interrupts regardless of whether or not we plan to use * them. We will register an interrupt handler now if they will be * used, but not re-enable intil later once the remainder of the tty * layer is properly initialised, as we're not ready for input yet. */ AJU_LOCK(sc); aju_intr_disable(sc); AJU_UNLOCK(sc); if (sc->ajus_irq_res != NULL) { error = bus_setup_intr(sc->ajus_dev, sc->ajus_irq_res, INTR_ENTROPY | INTR_TYPE_TTY | INTR_MPSAFE, NULL, aju_intr, sc, &sc->ajus_irq_cookie); if (error) { device_printf(sc->ajus_dev, "could not activate interrupt\n"); AJU_LOCK_DESTROY(sc); return (error); } } tp = sc->ajus_ttyp = tty_alloc(&aju_ttydevsw, sc); if (sc->ajus_flags & ALTERA_JTAG_UART_FLAG_CONSOLE) { aju_cons_sc = sc; tty_init_console(tp, 0); } tty_makedev(tp, NULL, "%s%d", AJU_TTYNAME, sc->ajus_unit); /* * If we will be using interrupts, enable them now; otherwise, start * polling. From this point onwards, input can arrive. */ if (sc->ajus_irq_res != NULL) { AJU_LOCK(sc); aju_intr_readable_enable(sc); AJU_UNLOCK(sc); } else { callout_init(&sc->ajus_io_callout, 1); callout_reset(&sc->ajus_io_callout, AJU_IO_POLLINTERVAL, aju_io_callout, sc); } callout_init(&sc->ajus_ac_callout, 1); callout_reset(&sc->ajus_ac_callout, AJU_AC_POLLINTERVAL, aju_ac_callout, sc); return (0); }
/* * cz_attach: * * A Cyclades-Z board was found; attach it. */ static void cz_attach(device_t parent, device_t self, void *aux) { extern const struct cdevsw cz_cdevsw; /* XXX */ struct cz_softc *cz = device_private(self); struct pci_attach_args *pa = aux; pci_intr_handle_t ih; const char *intrstr = NULL; struct cztty_softc *sc; struct tty *tp; int i; aprint_naive(": Multi-port serial controller\n"); aprint_normal(": Cyclades-Z multiport serial\n"); cz->cz_dev = self; cz->cz_plx.plx_pc = pa->pa_pc; cz->cz_plx.plx_tag = pa->pa_tag; if (pci_mapreg_map(pa, PLX_PCI_RUNTIME_MEMADDR, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &cz->cz_plx.plx_st, &cz->cz_plx.plx_sh, NULL, NULL) != 0) { aprint_error_dev(cz->cz_dev, "unable to map PLX registers\n"); return; } if (pci_mapreg_map(pa, PLX_PCI_LOCAL_ADDR0, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &cz->cz_win_st, &cz->cz_win_sh, NULL, NULL) != 0) { aprint_error_dev(cz->cz_dev, "unable to map device window\n"); return; } cz->cz_mailbox0 = CZ_PLX_READ(cz, PLX_MAILBOX0); cz->cz_nopenchan = 0; /* * Make sure that the board is completely stopped. */ CZ_WIN_FPGA(cz); CZ_FPGA_WRITE(cz, FPGA_CPU_STOP, 0); /* * Load the board's firmware. */ if (cz_load_firmware(cz) != 0) return; /* * Now that we're ready to roll, map and establish the interrupt * handler. */ if (pci_intr_map(pa, &ih) != 0) { /* * The common case is for Cyclades-Z boards to run * in polling mode, and thus not have an interrupt * mapped for them. Don't bother reporting that * the interrupt is not mappable, since this isn't * really an error. */ cz->cz_ih = NULL; goto polling_mode; } else { intrstr = pci_intr_string(pa->pa_pc, ih); cz->cz_ih = pci_intr_establish(pa->pa_pc, ih, IPL_TTY, cz_intr, cz); } if (cz->cz_ih == NULL) { aprint_error_dev(cz->cz_dev, "unable to establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); /* We will fall-back on polling mode. */ } else aprint_normal_dev(cz->cz_dev, "interrupting at %s\n", intrstr); polling_mode: if (cz->cz_ih == NULL) { callout_init(&cz->cz_callout, 0); if (cz_timeout_ticks == 0) cz_timeout_ticks = max(1, hz * CZ_POLL_MS / 1000); aprint_normal_dev(cz->cz_dev, "polling mode, %d ms interval (%d tick%s)\n", CZ_POLL_MS, cz_timeout_ticks, cz_timeout_ticks == 1 ? "" : "s"); } /* * Allocate sufficient pointers for the children and * attach them. Set all ports to a reasonable initial * configuration while we're at it: * * disabled * 8N1 * default baud rate * hardware flow control. */ CZ_WIN_RAM(cz); if (cz->cz_nchannels == 0) { /* No channels? No more work to do! */ return; } cz->cz_ports = malloc(sizeof(struct cztty_softc) * cz->cz_nchannels, M_DEVBUF, M_WAITOK|M_ZERO); cztty_attached_ttys += cz->cz_nchannels; for (i = 0; i < cz->cz_nchannels; i++) { sc = &cz->cz_ports[i]; sc->sc_channel = i; sc->sc_chan_st = cz->cz_win_st; sc->sc_parent = cz; if (bus_space_subregion(cz->cz_win_st, cz->cz_win_sh, cz->cz_fwctl + ZFIRM_CHNCTL_OFF(i, 0), ZFIRM_CHNCTL_SIZE, &sc->sc_chan_sh)) { aprint_error_dev(cz->cz_dev, "unable to subregion channel %d control\n", i); sc->sc_channel = CZTTY_CHANNEL_DEAD; continue; } if (bus_space_subregion(cz->cz_win_st, cz->cz_win_sh, cz->cz_fwctl + ZFIRM_BUFCTL_OFF(i, 0), ZFIRM_BUFCTL_SIZE, &sc->sc_buf_sh)) { aprint_error_dev(cz->cz_dev, "unable to subregion channel %d buffer\n", i); sc->sc_channel = CZTTY_CHANNEL_DEAD; continue; } callout_init(&sc->sc_diag_ch, 0); tp = tty_alloc(); tp->t_dev = makedev(cdevsw_lookup_major(&cz_cdevsw), (device_unit(cz->cz_dev) * ZFIRM_MAX_CHANNELS) + i); tp->t_oproc = czttystart; tp->t_param = czttyparam; tty_attach(tp); sc->sc_tty = tp; CZTTY_CHAN_WRITE(sc, CHNCTL_OP_MODE, C_CH_DISABLE); CZTTY_CHAN_WRITE(sc, CHNCTL_INTR_ENABLE, CZ_INTERRUPTS); CZTTY_CHAN_WRITE(sc, CHNCTL_SW_FLOW, 0); CZTTY_CHAN_WRITE(sc, CHNCTL_FLOW_XON, 0x11); CZTTY_CHAN_WRITE(sc, CHNCTL_FLOW_XOFF, 0x13); CZTTY_CHAN_WRITE(sc, CHNCTL_COMM_BAUD, TTYDEF_SPEED); CZTTY_CHAN_WRITE(sc, CHNCTL_COMM_PARITY, C_PR_NONE); CZTTY_CHAN_WRITE(sc, CHNCTL_COMM_DATA_L, C_DL_CS8 | C_DL_1STOP); CZTTY_CHAN_WRITE(sc, CHNCTL_COMM_FLAGS, 0); CZTTY_CHAN_WRITE(sc, CHNCTL_HW_FLOW, C_RS_CTS | C_RS_RTS); CZTTY_CHAN_WRITE(sc, CHNCTL_RS_CONTROL, 0); } }
int mfcsopen(dev_t dev, int flag, int mode, struct lwp *l) { struct tty *tp; struct mfcs_softc *sc; int unit, error; error = 0; unit = dev & 0x1f; sc = device_lookup_private(&mfcs_cd, unit); if (sc == NULL || (mfcs_active & (1 << unit)) == 0) return (ENXIO); if (sc->sc_tty) tp = sc->sc_tty; else { tp = sc->sc_tty = tty_alloc(); tty_attach(tp); } tp->t_oproc = (void (*) (struct tty *)) mfcsstart; tp->t_param = mfcsparam; tp->t_dev = dev; tp->t_hwiflow = mfcshwiflow; if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return (EBUSY); mutex_spin_enter(&tty_lock); if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { ttychars(tp); if (tp->t_ispeed == 0) { /* * only when cleared do we reset to defaults. */ 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 = mfcsdefaultrate; } /* * do these all the time */ if (sc->swflags & TIOCFLAG_CLOCAL) tp->t_cflag |= CLOCAL; if (sc->swflags & TIOCFLAG_CRTSCTS) tp->t_cflag |= CRTSCTS; if (sc->swflags & TIOCFLAG_MDMBUF) tp->t_cflag |= MDMBUF; mfcsparam(tp, &tp->t_termios); ttsetwater(tp); (void)mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET); if ((SWFLAGS(dev) & TIOCFLAG_SOFTCAR) || (mfcsmctl(dev, 0, DMGET) & TIOCM_CD)) tp->t_state |= TS_CARR_ON; else tp->t_state &= ~TS_CARR_ON; } /* * if NONBLOCK requested, ignore carrier */ if (flag & O_NONBLOCK) goto done; /* * block waiting for carrier */ while ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) { tp->t_wopen++; error = ttysleep(tp, &tp->t_rawcv, true, 0); tp->t_wopen--; if (error) { mutex_spin_exit(&tty_lock); return(error); } } done: /* This is a way to handle lost XON characters */ if ((flag & O_TRUNC) && (tp->t_state & TS_TTSTOP)) { tp->t_state &= ~TS_TTSTOP; ttstart (tp); } /* * Reset the tty pointer, as there could have been a dialout * use of the tty with a dialin open waiting. */ tp->t_dev = dev; mutex_spin_exit(&tty_lock); return tp->t_linesw->l_open(dev, tp); }
/* * Open a zs serial port. */ int zsopen(dev_t dev, int flags, int mode, struct lwp *l) { struct tty *tp; struct zs_chanstate *cs; struct zs_softc *sc; int unit = ZS_UNIT(dev); int zs = unit >> 1; int error, s; sc = device_lookup_private(&zs_cd, zs); if (sc == NULL) return ENXIO; cs = sc->sc_cs[unit & 1]; /* * When port A (ser02) is selected on the TT, make sure * the port is enabled. */ if ((machineid & ATARI_TT) && !(unit & 1)) ym2149_ser2(1); if (cs->cs_rbuf == NULL) { cs->cs_rbuf = malloc(ZLRB_RING_SIZE * sizeof(int), M_DEVBUF, M_WAITOK); } tp = cs->cs_ttyp; if (tp == NULL) { cs->cs_ttyp = tp = tty_alloc(); tty_attach(tp); tp->t_dev = dev; tp->t_oproc = zsstart; tp->t_param = zsparam; } if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) return EBUSY; s = spltty(); /* * Do the following iff this is a first open. */ if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { if (tp->t_ispeed == 0) { 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; } ttychars(tp); ttsetwater(tp); (void)zsparam(tp, &tp->t_termios); /* * Turn on DTR. We must always do this, even if carrier is not * present, because otherwise we'd have to use TIOCSDTR * immediately after setting CLOCAL, which applications do not * expect. We always assert DTR while the device is open * unless explicitly requested to deassert it. */ zs_modem(cs, ZSWR5_RTS|ZSWR5_DTR, DMSET); /* May never get a status intr. if DCD already on. -gwr */ if (((cs->cs_rr0 = cs->cs_zc->zc_csr) & ZSRR0_DCD) != 0) tp->t_state |= TS_CARR_ON; if (cs->cs_softcar) tp->t_state |= TS_CARR_ON; } splx(s); error = ttyopen(tp, ZS_DIALOUT(dev), (flags & O_NONBLOCK)); if (error) goto bad; error = tp->t_linesw->l_open(dev, tp); if (error) goto bad; return 0; bad: if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { /* * We failed to open the device, and nobody else had it opened. * Clean up the state as appropriate. */ zs_shutdown(cs); } return error; }
void sscom_attach_subr(struct sscom_softc *sc) { int unit = sc->sc_unit; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; struct tty *tp; callout_init(&sc->sc_diag_callout, 0); #if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && defined(SSCOM_MPLOCK) sc->sc_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SERIAL); #endif sc->sc_ucon = UCON_RXINT_ENABLE|UCON_TXINT_ENABLE; /* * set default for modem control hook */ if (sc->sc_set_modem_control == NULL) sc->sc_set_modem_control = sscom_set_modem_control; if (sc->sc_read_modem_status == NULL) sc->sc_read_modem_status = sscom_read_modem_status; /* Disable interrupts before configuring the device. */ KASSERT(sc->sc_change_txrx_interrupts != NULL); KASSERT(sc->sc_clear_interrupts != NULL); sscom_disable_txrxint(sc); #ifdef KGDB /* * Allow kgdb to "take over" this port. If this is * the kgdb device, it has exclusive use. */ if (unit == sscom_kgdb_unit) { SET(sc->sc_hwflags, SSCOM_HW_KGDB); sc->sc_ucon = UCON_DEBUGPORT; } #endif if (unit == sscomconsunit) { uint32_t stat; int timo; sscomconsattached = 1; sscomconstag = iot; sscomconsioh = ioh; /* wait for this transmission to complete */ timo = 1500000; do { stat = bus_space_read_4(iot, ioh, SSCOM_UTRSTAT); } while ((stat & UTRSTAT_TXEMPTY) == 0 && --timo > 0); /* Make sure the console is always "hardwired". */ SET(sc->sc_hwflags, SSCOM_HW_CONSOLE); SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); sc->sc_ucon = UCON_DEBUGPORT; } /* set RX/TX trigger to half values */ bus_space_write_4(iot, ioh, SSCOM_UFCON, __SHIFTIN(4, UFCON_TXTRIGGER) | __SHIFTIN(4, UFCON_RXTRIGGER) | UFCON_FIFO_ENABLE | UFCON_TXFIFO_RESET| UFCON_RXFIFO_RESET); /* tx/rx fifo reset are auto-cleared */ bus_space_write_4(iot, ioh, SSCOM_UCON, sc->sc_ucon); #ifdef KGDB if (ISSET(sc->sc_hwflags, SSCOM_HW_KGDB)) { sscom_kgdb_attached = 1; printf("%s: kgdb\n", device_xname(sc->sc_dev)); sscom_enable_debugport(sc); return; } #endif tp = tty_alloc(); tp->t_oproc = sscomstart; tp->t_param = sscomparam; tp->t_hwiflow = sscomhwiflow; sc->sc_tty = tp; sc->sc_rbuf = malloc(sscom_rbuf_size << 1, M_DEVBUF, M_NOWAIT); sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; sc->sc_rbavail = sscom_rbuf_size; if (sc->sc_rbuf == NULL) { printf("%s: unable to allocate ring buffer\n", device_xname(sc->sc_dev)); return; } sc->sc_ebuf = sc->sc_rbuf + (sscom_rbuf_size << 1); tty_attach(tp); if (ISSET(sc->sc_hwflags, SSCOM_HW_CONSOLE)) { int maj; /* locate the major number */ maj = cdevsw_lookup_major(&sscom_cdevsw); cn_tab->cn_dev = makedev(maj, device_unit(sc->sc_dev)); printf("%s: console (major=%d)\n", device_xname(sc->sc_dev), maj); } sc->sc_si = softint_establish(SOFTINT_SERIAL, sscomsoft, sc); #ifdef RND_COM rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), RND_TYPE_TTY, RND_FLAG_DEFAULT); #endif /* if there are no enable/disable functions, assume the device is always enabled */ if (ISSET(sc->sc_hwflags, SSCOM_HW_CONSOLE)) sscom_enable_debugport(sc); else sscom_disable_txrxint(sc); SET(sc->sc_hwflags, SSCOM_HW_DEV_OK); }
/* ARGSUSED */ STATIC void gtmpscattach(device_t parent, device_t self, void *aux) { struct gtmpsc_softc *sc = device_private(self); struct marvell_attach_args *mva = aux; bus_dma_segment_t segs; struct tty *tp; int rsegs, err, unit; void *kva; aprint_naive("\n"); aprint_normal(": Multi-Protocol Serial Controller\n"); if (mva->mva_unit != MVA_UNIT_DEFAULT) unit = mva->mva_unit; else unit = (mva->mva_offset == GTMPSC_BASE(0)) ? 0 : 1; #ifdef MPSC_CONSOLE if (cn_tab == >mpsc_consdev && cn_tab->cn_dev == makedev(0, unit)) { gtmpsc_cn_softc.sc_dev = self; memcpy(sc, >mpsc_cn_softc, sizeof(struct gtmpsc_softc)); sc->sc_flags = GTMPSC_CONSOLE; } else #endif { if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, mva->mva_offset, mva->mva_size, &sc->sc_mpsch)) { aprint_error_dev(self, "Cannot map MPSC registers\n"); return; } if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, GTSDMA_BASE(unit), GTSDMA_SIZE, &sc->sc_sdmah)) { aprint_error_dev(self, "Cannot map SDMA registers\n"); return; } sc->sc_dev = self; sc->sc_unit = unit; sc->sc_iot = mva->mva_iot; sc->sc_dmat = mva->mva_dmat; err = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 0, &segs, 1, &rsegs, BUS_DMA_NOWAIT); if (err) { aprint_error_dev(sc->sc_dev, "bus_dmamem_alloc error 0x%x\n", err); goto fail0; } err = bus_dmamem_map(sc->sc_dmat, &segs, 1, PAGE_SIZE, &kva, BUS_DMA_NOWAIT); if (err) { aprint_error_dev(sc->sc_dev, "bus_dmamem_map error 0x%x\n", err); goto fail1; } memset(kva, 0, PAGE_SIZE); /* paranoid/superfluous */ sc->sc_poll_sdmapage = kva; err = bus_dmamap_create(sc->sc_dmat, sizeof(gtmpsc_polltx_t), 1, sizeof(gtmpsc_polltx_t), 0, BUS_DMA_NOWAIT, &sc->sc_txdma_map); if (err != 0) { aprint_error_dev(sc->sc_dev, "bus_dmamap_create error 0x%x\n", err); goto fail2; } err = bus_dmamap_load(sc->sc_dmat, sc->sc_txdma_map, sc->sc_poll_sdmapage->tx, sizeof(gtmpsc_polltx_t), NULL, BUS_DMA_NOWAIT | BUS_DMA_READ | BUS_DMA_WRITE); if (err != 0) { aprint_error_dev(sc->sc_dev, "bus_dmamap_load tx error 0x%x\n", err); goto fail3; } err = bus_dmamap_create(sc->sc_dmat, sizeof(gtmpsc_pollrx_t), 1, sizeof(gtmpsc_pollrx_t), 0, BUS_DMA_NOWAIT, &sc->sc_rxdma_map); if (err != 0) { aprint_error_dev(sc->sc_dev, "bus_dmamap_create rx error 0x%x\n", err); goto fail4; } err = bus_dmamap_load(sc->sc_dmat, sc->sc_rxdma_map, sc->sc_poll_sdmapage->rx, sizeof(gtmpsc_pollrx_t), NULL, BUS_DMA_NOWAIT | BUS_DMA_READ | BUS_DMA_WRITE); if (err != 0) { aprint_error_dev(sc->sc_dev, "bus_dmamap_load rx error 0x%x\n", err); goto fail5; } sc->sc_brg = unit; /* XXXXX */ sc->sc_baudrate = GT_MPSC_DEFAULT_BAUD_RATE; } aprint_normal_dev(self, "with SDMA offset 0x%04x-0x%04x\n", GTSDMA_BASE(unit), GTSDMA_BASE(unit) + GTSDMA_SIZE - 1); sc->sc_rx_ready = 0; sc->sc_tx_busy = 0; sc->sc_tx_done = 0; sc->sc_tx_stopped = 0; sc->sc_heldchange = 0; gtmpsc_txdesc_init(sc); gtmpsc_rxdesc_init(sc); sc->sc_tty = tp = tty_alloc(); tp->t_oproc = gtmpscstart; tp->t_param = gtmpscparam; tty_attach(tp); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH); /* * clear any pending SDMA interrupts for this unit */ (void) gt_sdma_icause(device_parent(sc->sc_dev), SDMA_INTR_RXBUF(sc->sc_unit) | SDMA_INTR_RXERR(sc->sc_unit) | SDMA_INTR_TXBUF(sc->sc_unit) | SDMA_INTR_TXEND(sc->sc_unit)); sc->sc_si = softint_establish(SOFTINT_SERIAL, gtmpsc_softintr, sc); if (sc->sc_si == NULL) panic("mpscattach: cannot softint_establish IPL_SOFTSERIAL"); shutdownhook_establish(gtmpsc_shutdownhook, sc); gtmpscinit_stop(sc); gtmpscinit_start(sc); if (sc->sc_flags & GTMPSC_CONSOLE) { int maj; /* locate the major number */ maj = cdevsw_lookup_major(>mpsc_cdevsw); tp->t_dev = cn_tab->cn_dev = makedev(maj, device_unit(sc->sc_dev)); aprint_normal_dev(self, "console\n"); } #ifdef KGDB /* * Allow kgdb to "take over" this port. If this is * the kgdb device, it has exclusive use. */ if (sc->sc_unit == gtmpsckgdbport) { #ifdef MPSC_CONSOLE if (sc->sc_unit == MPSC_CONSOLE) { aprint_error_dev(self, "(kgdb): cannot share with console\n"); return; } #endif sc->sc_flags |= GTMPSC_KGDB; aprint_normal_dev(self, "kgdb\n"); gtmpsc_txflush(sc); kgdb_attach(gtmpsc_kgdb_getc, gtmpsc_kgdb_putc, NULL); kgdb_dev = 123; /* unneeded, only to satisfy some tests */ gtmpsc_kgdb_attached = 1; kgdb_connect(1); } #endif /* KGDB */ return; fail5: bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxdma_map); fail4: bus_dmamap_unload(sc->sc_dmat, sc->sc_txdma_map); fail3: bus_dmamap_destroy(sc->sc_dmat, sc->sc_txdma_map); fail2: bus_dmamem_unmap(sc->sc_dmat, kva, PAGE_SIZE); fail1: bus_dmamem_free(sc->sc_dmat, &segs, 1); fail0: return; }
void sabtty_attach(device_t parent, device_t self, void *aux) { struct sabtty_softc *sc = device_private(self); struct sabtty_attach_args *sa = aux; int r; int maj; int is_kgdb = 0; sc->sc_dev = self; #ifdef KGDB is_kgdb = sab_kgdb_check(sc); #endif if (!is_kgdb) { sc->sc_tty = tty_alloc(); 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 = device_private(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; if (sc->sc_flags & SABTTYF_IS_RSC) t.c_ospeed = 115200; else 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"); aprint_naive(": Serial port\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 = tty_alloc(); 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) { aprint_error_dev(sc->sc_dev, "channel %d: unable to allocate ring buffer\n", 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); aprint_normal_dev(sc->sc_dev, "channel %d: %s\n", chan, "console"); } #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); aprint_normal_dev(sc->sc_dev, "channel %d: %s\n", chan, "kgdb"); } #endif ch->ch_si = softint_establish(SOFTINT_SERIAL, sbscn_soft, ch); #ifdef RND_SBSCN rnd_attach_source(&ch->ch_rnd_source, device_xname(sc->sc_dev), RND_TYPE_TTY, 0); #endif sbscn_config(ch); SET(ch->ch_hwflags, SBSCN_HW_DEV_OK); }
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 = tty_alloc(); 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); #ifdef RND_COM rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), RND_TYPE_TTY, RND_FLAG_DEFAULT); #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); }