static void zs_sbdio_cninit(struct consdev *cn) { struct zs_chanstate *cs; struct zschan *zc; zc = zs_consaddr; cs = zs_conscs; /* Setup temporary chanstate. */ cs->cs_reg_csr = &zc->zc_csr; cs->cs_reg_data = &zc->zc_data; /* Initialize the pending registers. */ memcpy(cs->cs_preg, zs_init_reg, 16); cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS; cs->cs_brg_clk = PCLK / 16; cs->cs_defspeed = ZS_DEFSPEED; zs_set_speed(cs, ZS_DEFSPEED); /* Clear the master interrupt enable. */ zs_write_reg(cs, 9, 0); /* Reset the whole SCC chip. */ zs_write_reg(cs, 9, ZSWR9_HARD_RESET); /* Copy "pending" to "current" and H/W */ zs_loadchannelregs(cs); }
static int ewskbd_zsc_init(struct zs_chanstate *cs) { int s; s = splzs(); zs_write_reg(cs, 9, ZSWR9_B_RESET); DELAY(100); zs_write_reg(cs, 9, ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR); cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_TIE; cs->cs_preg[2] = 0; cs->cs_preg[3] = ZSWR3_RX_8 | ZSWR3_RX_ENABLE; cs->cs_preg[4] = ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_PARENB; cs->cs_preg[5] = ZSWR5_TX_8 | ZSWR5_RTS | ZSWR5_TX_ENABLE; cs->cs_preg[6] = 0; cs->cs_preg[7] = 0; cs->cs_preg[8] = 0; cs->cs_preg[9] = ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR; cs->cs_preg[10] = 0; cs->cs_preg[11] = ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD | ZSWR11_TRXC_OUT_ENA | ZSWR11_TRXC_BAUD; /* reg[11] and reg[12] are set by zs_set_speed() with cs_brg_clk */ zs_set_speed(cs, EWSKBD_BAUD); cs->cs_preg[14] = ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA; cs->cs_preg[15] = 0; zs_loadchannelregs(cs); splx(s); return 0; }
void zscninit(struct consdev *cn) { volatile struct zschan *cnchan = (volatile void *)IIOV(ZSCN_PHYSADDR); int s; memset(&zscn_cs, 0, sizeof(struct zs_chanstate)); zscn_cs.cs_reg_csr = &cnchan->zc_csr; zscn_cs.cs_reg_data = &cnchan->zc_data; zscn_cs.cs_channel = 0; zscn_cs.cs_brg_clk = PCLK / 16; memcpy(zscn_cs.cs_preg, zs_init_reg, 16); zscn_cs.cs_preg[4] = ZSWR4_CLK_X16 | ZSWR4_ONESB; /* XXX */ zscn_cs.cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS; zs_set_speed(&zscn_cs, ZSCN_SPEED); s = splzs(); zs_write_reg(&zscn_cs, 9, 0); zs_write_reg(&zscn_cs, 9, ZSWR9_HARD_RESET); zs_loadchannelregs(&zscn_cs); splx(s); conschan = cnchan; }
void zskbd_attach(struct device *parent, struct device *self, void *aux) { struct zskbd_softc *sc = (struct zskbd_softc *)self; struct zsc_softc *zsc = (struct zsc_softc *)parent; struct zsc_attach_args *args = aux; struct zs_chanstate *cs; struct wskbddev_attach_args wskaa; int s, channel, rc; uint8_t key; printf(": "); /* Establish ourself with the MD z8530 driver */ channel = args->channel; cs = zsc->zsc_cs[channel]; cs->cs_ops = &zskbd_zsops; cs->cs_private = sc; sc->sc_dc = malloc(sizeof(struct zskbd_devconfig), M_DEVBUF, M_WAITOK | M_ZERO); s = splzs(); zs_write_reg(cs, 9, (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET); cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_TIE; cs->cs_preg[4] = (cs->cs_preg[4] & ZSWR4_CLK_MASK) | (ZSWR4_ONESB | ZSWR4_PARENB); /* 1 stop, odd parity */ cs->cs_preg[15] &= ~ZSWR15_ENABLE_ENHANCED; zs_set_speed(cs, ZSKBD_BAUD); zs_loadchannelregs(cs); /* * Empty the keyboard input buffer (if the keyboard is the console * input device and the user invoked UKC, the `enter key up' event * will still be pending in the buffer). */ while ((zs_read_csr(cs) & ZSRR0_RX_READY) != 0) (void)zs_read_data(cs); /* * Ask the keyboard for its DIP switch settings. This will also let * us know whether the keyboard is connected. */ sc->sc_dc->expected = 2; zskbd_ctrl(cs, ZSKBD_CTRL_A_RCB, 0, 0, 0); while (sc->sc_dc->expected != 0) { rc = zskbd_poll(cs, &key); if (rc != 0) { if (rc == ENXIO && sc->sc_dc->expected == 2) { printf("no keyboard"); /* * Attach wskbd nevertheless, in case the * keyboard is plugged late. */ sc->sc_dc->expected = 0; goto dip; } else { printf("i/o error\n"); return; } } zskbd_process(cs, key); } printf("dip switches %02x", sc->sc_dc->dip); dip: /* * Disable key click by default. Note that if the keyboard is not * currently connected, the bit will nevertheless stick and will * disable the click as soon as a keyboard led needs to be lit. */ zskbd_ctrl(cs, ZSKBD_CTRL_A_NOCLICK, 0, 0, 0); splx(s); printf("\n"); if (zskbd_is_console) sc->sc_dc->enabled = 1; /* attach wskbd */ wskaa.console = zskbd_is_console; wskaa.keymap = &sgikbd_wskbd_keymapdata; wskaa.accessops = &zskbd_wskbd_accessops; wskaa.accesscookie = cs; sc->sc_dc->wskbddev = config_found(self, &wskaa, wskbddevprint); }
/* * Set ZS tty parameters from termios. * XXX - Should just copy the whole termios after * making sure all the changes could be done. */ int zsparam(struct tty *tp, struct termios *t) { struct zstty_softc *zst = zs_device_lookup(&zstty_cd, ZSUNIT(tp->t_dev)); struct zs_chanstate *cs = zst->zst_cs; int ospeed; tcflag_t cflag; uint8_t tmp3, tmp4, tmp5; int s, error; ospeed = t->c_ospeed; cflag = t->c_cflag; /* Check requested parameters. */ if (ospeed < 0) return (EINVAL); if (t->c_ispeed && t->c_ispeed != ospeed) return (EINVAL); /* * For the console, always force CLOCAL and !HUPCL, so that the port * is always active. */ if (ISSET(zst->zst_swflags, TIOCFLAG_SOFTCAR) || ISSET(zst->zst_hwflags, ZS_HWFLAG_CONSOLE)) { SET(cflag, CLOCAL); CLR(cflag, HUPCL); } /* * Only whack the UART when params change. * Some callers need to clear tp->t_ospeed * to make sure initialization gets done. */ if (tp->t_ospeed == ospeed && tp->t_cflag == cflag) return (0); /* * Call MD functions to deal with changed * clock modes or H/W flow control modes. * The BRG divisor is set now. (reg 12,13) */ error = zs_set_speed(cs, ospeed); if (error) return (error); error = zs_set_modes(cs, cflag); if (error) return (error); /* * Block interrupts so that state will not * be altered until we are done setting it up. * * Initial values in cs_preg are set before * our attach routine is called. The master * interrupt enable is handled by zsc.c * */ s = splzs(); /* * Recalculate which status ints to enable. */ zs_maskintr(zst); /* Recompute character size bits. */ tmp3 = cs->cs_preg[3]; tmp5 = cs->cs_preg[5]; CLR(tmp3, ZSWR3_RXSIZE); CLR(tmp5, ZSWR5_TXSIZE); switch (ISSET(cflag, CSIZE)) { case CS5: SET(tmp3, ZSWR3_RX_5); SET(tmp5, ZSWR5_TX_5); break; case CS6: SET(tmp3, ZSWR3_RX_6); SET(tmp5, ZSWR5_TX_6); break; case CS7: SET(tmp3, ZSWR3_RX_7); SET(tmp5, ZSWR5_TX_7); break; case CS8: SET(tmp3, ZSWR3_RX_8); SET(tmp5, ZSWR5_TX_8); break; } cs->cs_preg[3] = tmp3; cs->cs_preg[5] = tmp5; /* * Recompute the stop bits and parity bits. Note that * zs_set_speed() may have set clock selection bits etc. * in wr4, so those must preserved. */ tmp4 = cs->cs_preg[4]; CLR(tmp4, ZSWR4_SBMASK | ZSWR4_PARMASK); if (ISSET(cflag, CSTOPB)) SET(tmp4, ZSWR4_TWOSB); else SET(tmp4, ZSWR4_ONESB); if (!ISSET(cflag, PARODD)) SET(tmp4, ZSWR4_EVENP); if (ISSET(cflag, PARENB)) SET(tmp4, ZSWR4_PARENB); cs->cs_preg[4] = tmp4; /* And copy to tty. */ tp->t_ispeed = 0; tp->t_ospeed = ospeed; tp->t_cflag = cflag; /* * If nothing is being transmitted, set up new current values, * else mark them as pending. */ if (!cs->cs_heldchange) { if (zst->zst_tx_busy) { zst->zst_heldtbc = zst->zst_tbc; zst->zst_tbc = 0; cs->cs_heldchange = 1; } else zs_loadchannelregs(cs); } /* * If hardware flow control is disabled, turn off the buffer water * marks and unblock any soft flow control state. Otherwise, enable * the water marks. */ if (!ISSET(cflag, CHWFLOW)) { zst->zst_r_hiwat = 0; zst->zst_r_lowat = 0; if (ISSET(zst->zst_rx_flags, RX_TTY_OVERFLOWED)) { CLR(zst->zst_rx_flags, RX_TTY_OVERFLOWED); zst->zst_rx_ready = 1; cs->cs_softreq = 1; } if (ISSET(zst->zst_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) { CLR(zst->zst_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED); zs_hwiflow(zst); } } else { zst->zst_r_hiwat = zstty_rbuf_hiwat; zst->zst_r_lowat = zstty_rbuf_lowat; } /* * Force a recheck of the hardware carrier and flow control status, * since we may have changed which bits we're looking at. */ zstty_stint(cs, 1); splx(s); /* * If hardware flow control is disabled, unblock any hard flow control * state. */ if (!ISSET(cflag, CHWFLOW)) { if (zst->zst_tx_stopped) { zst->zst_tx_stopped = 0; zsstart(tp); } } zstty_softint(cs); return (0); }