static int pckbc_attach_slot(struct pckbc_softc *sc, pckbc_slot_t slot) { struct pckbc_internal *t = sc->id; void *sdata; device_t child; int alloced = 0; if (t->t_slotdata[slot] == NULL) { sdata = malloc(sizeof(struct pckbc_slotdata), M_DEVBUF, M_NOWAIT); if (sdata == NULL) { aprint_error_dev(sc->sc_dv, "no memory\n"); return (0); } t->t_slotdata[slot] = sdata; pckbc_init_slotdata(t->t_slotdata[slot]); alloced++; } child = pckbport_attach_slot(sc->sc_dv, t->t_pt, slot); if (child == NULL && alloced) { free(t->t_slotdata[slot], M_DEVBUF); t->t_slotdata[slot] = NULL; } if (child != NULL && t->t_slotdata[slot] != NULL) rnd_attach_source(&t->t_slotdata[slot]->rnd_source, device_xname(child), RND_TYPE_TTY, 0); return child != NULL; }
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; } }