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 */ tp = tty_alloc_mutex(&ucom_class, sc, sc->sc_mtx); if (tp == NULL) 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 */ snprintf(buf, sizeof(buf), UCOM_TTY_PREFIX "%u.%u", ssc->sc_unit, sc->sc_subunit); } else { /* single modem */ snprintf(buf, sizeof(buf), UCOM_TTY_PREFIX "%u", ssc->sc_unit); } } tty_makedev(tp, NULL, "%s", buf); sc->sc_tty = tp; 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; tty_init_console(tp, 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->sc_tty); ucom_param(ucom_cons_softc->sc_tty, &tp->t_termios_init_in); UCOM_MTX_UNLOCK(ucom_cons_softc); } return (0); }
static int ucom_attach_tty(struct ucom_softc *sc, uint32_t sub_units) { struct tty *tp; int error = 0; char buf[32]; /* temporary TTY device name buffer */ tp = tty_alloc_mutex(&ucom_class, sc, sc->sc_mtx); if (tp == NULL) { error = ENOMEM; goto done; } DPRINTF("tp = %p, unit = %d\n", tp, sc->sc_unit); buf[0] = 0; /* set some default value */ /* Check if the client has a custom TTY name */ if (sc->sc_callback->ucom_tty_name) { sc->sc_callback->ucom_tty_name(sc, buf, sizeof(buf), sc->sc_local_unit); } if (buf[0] == 0) { /* Use default TTY name */ if (sub_units > 1) { /* multiple modems in one */ if (snprintf(buf, sizeof(buf), "U%u.%u", sc->sc_unit - sc->sc_local_unit, sc->sc_local_unit)) { /* ignore */ } } else { /* single modem */ if (snprintf(buf, sizeof(buf), "U%u", sc->sc_unit)) { /* ignore */ } } } tty_makedev(tp, NULL, "%s", buf); sc->sc_tty = tp; DPRINTF("ttycreate: %s\n", buf); cv_init(&sc->sc_cv, "ucom"); done: return (error); }
/* * Attach the device. Initialize the card. */ int siattach(device_t dev) { int unit; struct si_softc *sc; struct si_port *pp; struct tty *tp; volatile struct si_channel *ccbp; volatile struct si_reg *regp; volatile caddr_t maddr; struct si_module *modp; int nmodule, nport, x, y; int uart_type; sc = device_get_softc(dev); unit = device_get_unit(dev); sc->sc_typename = si_type[sc->sc_type]; if (si_numunits < unit + 1) si_numunits = unit + 1; DPRINT((0, DBG_AUTOBOOT, "si%d: siattach\n", unit)); #ifdef POLL if (si_pollrate == 0) { si_pollrate = POLLHZ; /* in addition to irq */ #ifdef REALPOLL si_realpoll = 1; /* scan always */ #endif } #endif DPRINT((0, DBG_AUTOBOOT, "si%d: type: %s paddr: %x maddr: %x\n", unit, sc->sc_typename, sc->sc_paddr, sc->sc_maddr)); sc->sc_ports = NULL; /* mark as uninitialised */ maddr = sc->sc_maddr; /* Stop the CPU first so it won't stomp around while we load */ switch (sc->sc_type) { #ifdef DEV_EISA case SIEISA: outb(sc->sc_iobase + 2, sc->sc_irq << 4); #endif break; case SIPCI: *(maddr+SIPCIRESET) = 0; break; case SIJETPCI: /* fall through to JET ISA */ case SIJETISA: *(maddr+SIJETCONFIG) = 0; break; case SIHOST2: *(maddr+SIPLRESET) = 0; break; case SIHOST: *(maddr+SIRESET) = 0; break; default: /* this should never happen */ printf("si%d: unsupported configuration\n", unit); return EINVAL; break; } /* OK, now lets download the download code */ if (SI_ISJET(sc->sc_type)) { DPRINT((0, DBG_DOWNLOAD, "si%d: jet_download: nbytes %d\n", unit, si3_t225_dsize)); si_bcopy(si3_t225_download, maddr + si3_t225_downloadaddr, si3_t225_dsize); DPRINT((0, DBG_DOWNLOAD, "si%d: jet_bootstrap: nbytes %d -> %x\n", unit, si3_t225_bsize, si3_t225_bootloadaddr)); si_bcopy(si3_t225_bootstrap, maddr + si3_t225_bootloadaddr, si3_t225_bsize); } else { DPRINT((0, DBG_DOWNLOAD, "si%d: si_download: nbytes %d\n", unit, si2_z280_dsize)); si_bcopy(si2_z280_download, maddr + si2_z280_downloadaddr, si2_z280_dsize); } /* Now start the CPU */ switch (sc->sc_type) { #ifdef DEV_EISA case SIEISA: /* modify the download code to tell it that it's on an EISA */ *(maddr + 0x42) = 1; outb(sc->sc_iobase + 2, (sc->sc_irq << 4) | 4); (void)inb(sc->sc_iobase + 3); /* reset interrupt */ break; #endif case SIPCI: /* modify the download code to tell it that it's on a PCI */ *(maddr+0x42) = 1; *(maddr+SIPCIRESET) = 1; *(maddr+SIPCIINTCL) = 0; break; case SIJETPCI: *(maddr+SIJETRESET) = 0; *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN; break; case SIJETISA: *(maddr+SIJETRESET) = 0; switch (sc->sc_irq) { case 9: *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0x90; break; case 10: *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xa0; break; case 11: *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xb0; break; case 12: *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xc0; break; case 15: *(maddr+SIJETCONFIG) = SIJETBUSEN|SIJETIRQEN|0xf0; break; } break; case SIHOST: *(maddr+SIRESET_CL) = 0; *(maddr+SIINTCL_CL) = 0; break; case SIHOST2: *(maddr+SIPLRESET) = 0x10; switch (sc->sc_irq) { case 11: *(maddr+SIPLIRQ11) = 0x10; break; case 12: *(maddr+SIPLIRQ12) = 0x10; break; case 15: *(maddr+SIPLIRQ15) = 0x10; break; } *(maddr+SIPLIRQCLR) = 0x10; break; default: /* this should _REALLY_ never happen */ printf("si%d: Uh, it was supported a second ago...\n", unit); return EINVAL; } DELAY(1000000); /* wait around for a second */ regp = (struct si_reg *)maddr; y = 0; /* wait max of 5 sec for init OK */ while (regp->initstat == 0 && y++ < 10) { DELAY(500000); } switch (regp->initstat) { case 0: printf("si%d: startup timeout - aborting\n", unit); sc->sc_type = SIEMPTY; return EINVAL; case 1: if (SI_ISJET(sc->sc_type)) { /* set throttle to 100 times per second */ regp->int_count = JET_INT_COUNT; /* rx_intr_count is a NOP in Jet */ } else { /* set throttle to 125 times per second */ regp->int_count = INT_COUNT; /* rx intr max of 25 times per second */ regp->rx_int_count = RXINT_COUNT; } regp->int_pending = 0; /* no intr pending */ regp->int_scounter = 0; /* reset counter */ break; case 0xff: /* * No modules found, so give up on this one. */ printf("si%d: %s - no ports found\n", unit, si_type[sc->sc_type]); return 0; default: printf("si%d: download code version error - initstat %x\n", unit, regp->initstat); return EINVAL; } /* * First time around the ports just count them in order * to allocate some memory. */ nport = 0; modp = (struct si_module *)(maddr + 0x80); for (;;) { DPRINT((0, DBG_DOWNLOAD, "si%d: ccb addr 0x%x\n", unit, modp)); switch (modp->sm_type) { case TA4: DPRINT((0, DBG_DOWNLOAD, "si%d: Found old TA4 module, 4 ports\n", unit)); x = 4; break; case TA8: DPRINT((0, DBG_DOWNLOAD, "si%d: Found old TA8 module, 8 ports\n", unit)); x = 8; break; case TA4_ASIC: DPRINT((0, DBG_DOWNLOAD, "si%d: Found ASIC TA4 module, 4 ports\n", unit)); x = 4; break; case TA8_ASIC: DPRINT((0, DBG_DOWNLOAD, "si%d: Found ASIC TA8 module, 8 ports\n", unit)); x = 8; break; case MTA: DPRINT((0, DBG_DOWNLOAD, "si%d: Found CD1400 module, 8 ports\n", unit)); x = 8; break; case SXDC: DPRINT((0, DBG_DOWNLOAD, "si%d: Found SXDC module, 8 ports\n", unit)); x = 8; break; default: printf("si%d: unknown module type %d\n", unit, modp->sm_type); goto try_next; } /* this was limited in firmware and is also a driver issue */ if ((nport + x) > SI_MAXPORTPERCARD) { printf("si%d: extra ports ignored\n", unit); goto try_next; } nport += x; si_Nports += x; si_Nmodules++; try_next: if (modp->sm_next == 0) break; modp = (struct si_module *) (maddr + (unsigned)(modp->sm_next & 0x7fff)); } sc->sc_ports = (struct si_port *)malloc(sizeof(struct si_port) * nport, M_DEVBUF, M_NOWAIT | M_ZERO); if (sc->sc_ports == 0) { printf("si%d: fail to malloc memory for port structs\n", unit); return EINVAL; } sc->sc_nport = nport; /* * Scan round the ports again, this time initialising. */ pp = sc->sc_ports; nmodule = 0; modp = (struct si_module *)(maddr + 0x80); uart_type = 1000; /* arbitary, > uchar_max */ for (;;) { switch (modp->sm_type) { case TA4: nport = 4; break; case TA8: nport = 8; break; case TA4_ASIC: nport = 4; break; case TA8_ASIC: nport = 8; break; case MTA: nport = 8; break; case SXDC: nport = 8; break; default: goto try_next2; } nmodule++; ccbp = (struct si_channel *)((char *)modp + 0x100); if (uart_type == 1000) uart_type = ccbp->type; else if (uart_type != ccbp->type) printf("si%d: Warning: module %d mismatch! (%d%s != %d%s)\n", unit, nmodule, ccbp->type, si_modulename(sc->sc_type, ccbp->type), uart_type, si_modulename(sc->sc_type, uart_type)); for (x = 0; x < nport; x++, pp++, ccbp++) { pp->sp_ccb = ccbp; /* save the address */ pp->sp_pend = IDLE_CLOSE; pp->sp_state = 0; /* internal flag */ #ifdef SI_DEBUG sprintf(pp->sp_name, "si%r%r", unit, (int)(pp - sc->sc_ports)); #endif tp = pp->sp_tty = tty_alloc_mutex(&si_tty_class, pp, &Giant); tty_makedev(tp, NULL, "A%r%r", unit, (int)(pp - sc->sc_ports)); } try_next2: if (modp->sm_next == 0) { printf("si%d: card: %s, ports: %d, modules: %d, type: %d%s\n", unit, sc->sc_typename, sc->sc_nport, nmodule, uart_type, si_modulename(sc->sc_type, uart_type)); break; } modp = (struct si_module *) (maddr + (unsigned)(modp->sm_next & 0x7fff)); } if (unit == 0) make_dev(&si_Scdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "si_control"); return (0); }
static void nmdm_clone(void *arg, struct ucred *cred, char *name, int nameen, struct cdev **dev) { struct nmdmsoftc *ns; struct tty *tp; char *end; int error; char endc; if (*dev != NULL) return; if (strncmp(name, "nmdm", 4) != 0) return; if (strlen(name) <= strlen("nmdmX")) return; /* Device name must be "nmdm%s%c", where %c is 'A' or 'B'. */ end = name + strlen(name) - 1; endc = *end; if (endc != 'A' && endc != 'B') return; ns = malloc(sizeof(*ns), M_NMDM, M_WAITOK | M_ZERO); mtx_init(&ns->ns_mtx, "nmdm", NULL, MTX_DEF); /* Hook the pairs together. */ ns->ns_part1.np_pair = ns; ns->ns_part1.np_other = &ns->ns_part2; TASK_INIT(&ns->ns_part1.np_task, 0, nmdm_task_tty, &ns->ns_part1); callout_init_mtx(&ns->ns_part1.np_callout, &ns->ns_mtx, 0); ns->ns_part2.np_pair = ns; ns->ns_part2.np_other = &ns->ns_part1; TASK_INIT(&ns->ns_part2.np_task, 0, nmdm_task_tty, &ns->ns_part2); callout_init_mtx(&ns->ns_part2.np_callout, &ns->ns_mtx, 0); /* Create device nodes. */ tp = ns->ns_part1.np_tty = tty_alloc_mutex(&nmdm_class, &ns->ns_part1, &ns->ns_mtx); *end = 'A'; error = tty_makedevf(tp, NULL, endc == 'A' ? TTYMK_CLONING : 0, "%s", name); if (error) { *end = endc; mtx_destroy(&ns->ns_mtx); free(ns, M_NMDM); return; } tp = ns->ns_part2.np_tty = tty_alloc_mutex(&nmdm_class, &ns->ns_part2, &ns->ns_mtx); *end = 'B'; error = tty_makedevf(tp, NULL, endc == 'B' ? TTYMK_CLONING : 0, "%s", name); if (error) { *end = endc; mtx_lock(&ns->ns_mtx); /* see nmdm_free() */ ns->ns_part1.np_other = NULL; atomic_add_int(&nmdm_count, 1); tty_rel_gone(ns->ns_part1.np_tty); return; } if (endc == 'A') *dev = ns->ns_part1.np_tty->t_dev; else *dev = ns->ns_part2.np_tty->t_dev; *end = endc; atomic_add_int(&nmdm_count, 1); }
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 */ tp = tty_alloc_mutex(&ucom_class, sc, sc->sc_mtx); if (tp == NULL) 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 */ snprintf(buf, sizeof(buf), UCOM_TTY_PREFIX "%u.%u", ssc->sc_unit, sc->sc_subunit); } else { /* single modem */ snprintf(buf, sizeof(buf), UCOM_TTY_PREFIX "%u", ssc->sc_unit); } } tty_makedev(tp, NULL, "%s", buf); sc->sc_tty = tp; sc->sc_pps.ppscap = PPS_CAPTUREBOTH; sc->sc_pps.driver_abi = PPS_ABI_VERSION; sc->sc_pps.driver_mtx = sc->sc_mtx; pps_init_abi(&sc->sc_pps); 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; tty_init_console(tp, 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->sc_tty); ucom_param(ucom_cons_softc->sc_tty, &tp->t_termios_init_in); UCOM_MTX_UNLOCK(ucom_cons_softc); } if ((ssc->sc_flag & UCOM_FLAG_DEVICE_MODE) != 0 && ucom_device_mode_console > 0 && ucom_cons_softc == NULL) { struct consdev *cp; cp = malloc(sizeof(struct consdev), M_USBDEV, M_WAITOK|M_ZERO); cp->cn_ops = &ucom_cnops; cp->cn_arg = NULL; cp->cn_pri = CN_NORMAL; strlcpy(cp->cn_name, "tty", sizeof(cp->cn_name)); strlcat(cp->cn_name, buf, sizeof(cp->cn_name)); sc->sc_consdev = cp; cnadd(cp); } return (0); }