static void sackbc_attach(device_t parent, device_t self, void *aux) { struct sackbc_softc *sc = device_private(self); struct sacc_softc *psc = device_private(parent); struct sa1111_attach_args *aa = (struct sa1111_attach_args *)aux; device_t child; uint32_t tmp, clock_bit; int intr, slot; switch (aa->sa_addr) { case SACC_KBD0: clock_bit = (1<<6); intr = 21; break; case SACC_KBD1: clock_bit = (1<<5); intr = 18; break; default: return; } if (aa->sa_size <= 0) aa->sa_size = SACCKBD_SIZE; if (aa->sa_intr == SACCCF_INTR_DEFAULT) aa->sa_intr = intr; sc->dev = self; sc->iot = psc->sc_iot; if (bus_space_subregion(psc->sc_iot, psc->sc_ioh, aa->sa_addr, aa->sa_size, &sc->ioh)) { aprint_normal(": can't map subregion\n"); return; } /* enable clock for PS/2 kbd or mouse */ tmp = bus_space_read_4(psc->sc_iot, psc->sc_ioh, SACCSC_SKPCR); bus_space_write_4(psc->sc_iot, psc->sc_ioh, SACCSC_SKPCR, tmp | clock_bit); sc->ih_rx = NULL; sc->intr = aa->sa_intr; sc->polling = 0; tmp = bus_space_read_4(sc->iot, sc->ioh, SACCKBD_CR); bus_space_write_4(sc->iot, sc->ioh, SACCKBD_CR, tmp | KBDCR_ENA); /* XXX: this is necessary to get keyboard working. but I don't know why */ bus_space_write_4(sc->iot, sc->ioh, SACCKBD_CLKDIV, 2); tmp = bus_space_read_4(sc->iot, sc->ioh, SACCKBD_STAT); if ((tmp & KBDSTAT_ENA) == 0) { printf("??? can't enable KBD controller\n"); return; } printf("\n"); sc->pt = pckbport_attach(sc, &sackbc_ops); /* * Although there is no such thing as SLOT for SA-1111 kbd * controller, pckbd and pms drivers require it. */ for (slot = PCKBPORT_KBD_SLOT; slot <= PCKBPORT_AUX_SLOT; ++slot) { child = pckbport_attach_slot(self, sc->pt, slot); if (child == NULL) continue; sc->slot = slot; rnd_attach_source(&sc->rnd_source, device_xname(child), RND_TYPE_TTY, RND_FLAG_DEFAULT|RND_FLAG_ESTIMATE_VALUE); /* only one of KBD_SLOT or AUX_SLOT is used. */ break; } }
void pckbc_attach(struct pckbc_softc *sc) { struct pckbc_internal *t; bus_space_tag_t iot; bus_space_handle_t ioh_d, ioh_c; int res; u_char cmdbits = 0; t = sc->id; iot = t->t_iot; ioh_d = t->t_ioh_d; ioh_c = t->t_ioh_c; t->t_pt = pckbport_attach(t, &pckbc_ops); if (t->t_pt == NULL) { aprint_error(": attach failed\n"); return; } /* flush */ (void) pckbc_poll_data1(t, PCKBC_KBD_SLOT); /* set initial cmd byte */ if (!pckbc_put8042cmd(t)) { printf("pckbc: cmd word write error\n"); return; } /* * XXX Don't check the keyboard port. There are broken keyboard controllers * which don't pass the test but work normally otherwise. */ #if 0 /* * check kbd port ok */ if (!pckbc_send_cmd(iot, ioh_c, KBC_KBDTEST)) return; res = pckbc_poll_data1(t, PCKBC_KBD_SLOT, 0); /* * Normally, we should get a "0" here. * But there are keyboard controllers behaving differently. */ if (res == 0 || res == 0xfa || res == 0x01 || res == 0xab) { #ifdef PCKBCDEBUG if (res != 0) printf("pckbc: returned %x on kbd slot test\n", res); #endif if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT)) cmdbits |= KC8_KENABLE; } else { printf("pckbc: kbd port test: %x\n", res); return; } #else if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT)) cmdbits |= KC8_KENABLE; #endif /* 0 */ /* * Check aux port ok. * Avoid KBC_AUXTEST because it hangs some older controllers * (eg UMC880?). */ if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXECHO)) { printf("pckbc: aux echo error 1\n"); goto nomouse; } if (!pckbc_wait_output(iot, ioh_c)) { printf("pckbc: aux echo error 2\n"); goto nomouse; } t->t_haveaux = 1; bus_space_write_1(iot, ioh_d, 0, 0x5a); /* a random value */ res = pckbc_poll_data1(t, PCKBC_AUX_SLOT); /* * The following is needed to find the aux port on the Tadpole * SPARCle. */ if (res == -1 && ISSET(t->t_flags, PCKBC_NEED_AUXWRITE)) { /* Read of aux echo timed out, try again */ if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXWRITE)) goto nomouse; if (!pckbc_wait_output(iot, ioh_c)) goto nomouse; bus_space_write_1(iot, ioh_d, 0, 0x5a); res = pckbc_poll_data1(t, PCKBC_AUX_SLOT); } if (res != -1) { /* * In most cases, the 0x5a gets echoed. * Some older controllers (Gateway 2000 circa 1993) * return 0xfe here. * We are satisfied if there is anything in the * aux output buffer. */ if (pckbc_attach_slot(sc, PCKBC_AUX_SLOT)) cmdbits |= KC8_MENABLE; } else { #ifdef PCKBCDEBUG printf("pckbc: aux echo test failed\n"); #endif t->t_haveaux = 0; } nomouse: /* enable needed interrupts */ t->t_cmdbyte |= cmdbits; if (!pckbc_put8042cmd(t)) printf("pckbc: cmd word write error\n"); }