예제 #1
0
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;			
	}
}