예제 #1
0
void
pckbc_hpc_attach(struct device *parent, struct device * self, void *aux)
{
	struct pckbc_hpc_softc *msc = (struct pckbc_hpc_softc *)self;
	struct pckbc_softc *sc = &msc->sc_pckbc;
	struct hpc_attach_args *haa = aux;
	struct pckbc_internal *t = NULL;
	bus_space_handle_t ioh_d, ioh_c;
	int console;

	msc->sc_irq = haa->ha_irq;
	msc->sc_hasintr = 0;

	console = pckbc_is_console(haa->ha_st,
	    XKPHYS_TO_PHYS(haa->ha_sh + haa->ha_devoff + 3));

	if (console) {
		/* pckbc_cnattach() has already been called */
		t = &pckbc_consdata;
		pckbc_console_attached = 1;
	} else {
		if (bus_space_subregion(haa->ha_st, haa->ha_sh,
		    haa->ha_devoff + 3 + KBDATAP, 1, &ioh_d) ||
		    bus_space_subregion(haa->ha_st, haa->ha_sh,
		    haa->ha_devoff + 3 + KBCMDP, 1, &ioh_c)) {
			printf(": couldn't map registers\n");
			return;
		}

		t = malloc(sizeof(*t), M_DEVBUF, M_NOWAIT | M_ZERO);
		t->t_iot = haa->ha_st;
		t->t_ioh_c = ioh_c;
		t->t_ioh_d = ioh_d;
	}

	sc->intr_establish = pckbc_hpc_intr_establish;

	t->t_cmdbyte = KC8_CPU;
	t->t_sc = sc;
	sc->id = t;

	printf("\n");
	pckbc_attach(sc, 0);
}
void
pckbc_elb_attach(device_t parent, device_t self, void *aux)
{
	struct pckbc_elb_softc *msc = device_private(self);
	struct pckbc_softc *sc = &msc->sc_pckbc;
	struct elb_attach_args *eaa = aux;
	struct pckbc_internal *t;

	sc->sc_dv = self;

	/*
	 * Setup interrupt data.
	 */
	msc->sc_irq = eaa->elb_irq;
	sc->intr_establish = pckbc_elb_intr_establish;

	if (pckbc_is_console(eaa->elb_bt, eaa->elb_base)) {
		t = &pckbc_consdata;
		pckbc_console_attached = 1;
	} else {
		t = malloc(sizeof(struct pckbc_internal), M_DEVBUF, M_WAITOK);
		memset(t, 0, sizeof(struct pckbc_internal));
	}

	t->t_iot = eaa->elb_bt;
	bus_space_map(eaa->elb_bt,
	    _BUS_SPACE_UNSTRIDE(eaa->elb_bt, eaa->elb_base), 1, 0, &t->t_ioh_d);
	bus_space_map(eaa->elb_bt,
	    _BUS_SPACE_UNSTRIDE(eaa->elb_bt, eaa->elb_base2), 1, 0, &t->t_ioh_c);
	t->t_addr = eaa->elb_base;
	t->t_sc = sc;
	sc->id = t;

	aprint_normal("\n");

	pckbc_attach(sc);
}
예제 #3
0
파일: pckbc_js.c 프로젝트: ryo/netbsd-src
static void
pckbc_js_attach_common(struct pckbc_js_softc *jsc,
		       bus_space_tag_t iot, bus_addr_t ioaddr, int intr,
		       int isconsole)
{
	struct pckbc_softc *sc = (struct pckbc_softc *)jsc;
	struct pckbc_internal *t;

	jsc->jsc_pckbc.intr_establish = pckbc_js_intr_establish;
	jsc->jsc_intr = intr;
	jsc->jsc_establised = 0;

	if (isconsole) {
		int status;

		status = pckbc_cnattach(iot, ioaddr, KBCMDP, PCKBC_KBD_SLOT, 0);
		if (status == 0)
			aprint_normal(": cnattach ok");
		else
			aprint_error(": cnattach %d", status);
	}

	if (pckbc_is_console(iot, ioaddr)) {
		t = &pckbc_consdata;
		pckbc_console_attached = 1;
	} else {
		bus_space_handle_t ioh_d, ioh_c;

		if (bus_space_map(iot, ioaddr + KBDATAP, 1, 0, &ioh_d) != 0) {
			aprint_error(": unable to map data register\n");
			return;
		}

		if (bus_space_map(iot, ioaddr + KBCMDP,  1, 0, &ioh_c) != 0) {
			bus_space_unmap(iot, ioh_d, 1);
			aprint_error(": unable to map cmd register\n");
			return;
		}

		t = malloc(sizeof(struct pckbc_internal), M_DEVBUF, M_WAITOK);
		memset(t, 0, sizeof(struct pckbc_internal));
		t->t_iot = iot;
		t->t_ioh_d = ioh_d;
		t->t_ioh_c = ioh_c;
		t->t_addr = ioaddr;
		t->t_cmdbyte = KC8_CPU; /* initial command: enable ports */
		callout_init(&t->t_cleanup, 0);

		(void) pckbc_poll_data1(t, PCKBC_KBD_SLOT); /* flush */

		if (pckbc_send_cmd(iot, ioh_c, KBC_SELFTEST) == 0)
			aprint_error(": unable to request self test");
		else {
			int response;

			response = pckbc_poll_data1(t, PCKBC_KBD_SLOT);
			if (response == 0x55)
				aprint_normal(": selftest ok");
			else
				aprint_error(": selftest failed (0x%02x)",
				    response);
		}
	}

	/* crosslink */
	t->t_sc = sc;
	sc->id = t;

	/* finish off the attach */
	aprint_normal("\n");
	pckbc_attach(sc);
}
예제 #4
0
static void
pckbc_acpi_attach(device_t parent, device_t self, void *aux)
{
	struct pckbc_acpi_softc *psc = device_private(self);
	struct pckbc_softc *sc = &psc->sc_pckbc;
	struct pckbc_internal *t;
	struct acpi_attach_args *aa = aux;
	bus_space_handle_t ioh_d, ioh_c;
	pckbc_slot_t peer;
	struct acpi_resources res;
	struct acpi_io *io0, *io1, *ioswap;
	struct acpi_irq *irq;
	ACPI_STATUS rv;

	sc->sc_dv = self;
	psc->sc_ic = aa->aa_ic;

	if (acpi_match_hid(aa->aa_node->ad_devinfo, pckbc_acpi_ids_kbd)) {
		psc->sc_slot = PCKBC_KBD_SLOT;
		peer = PCKBC_AUX_SLOT;
	} else if (acpi_match_hid(aa->aa_node->ad_devinfo, pckbc_acpi_ids_ms)) {
		psc->sc_slot = PCKBC_AUX_SLOT;
		peer = PCKBC_KBD_SLOT;
	} else {
		aprint_error(": unknown port!\n");
		panic("pckbc_acpi_attach: impossible");
	}

	aprint_naive("\n");
	aprint_normal(": %s port\n", pckbc_slot_names[psc->sc_slot]);

	/* parse resources */
	rv = acpi_resource_parse(sc->sc_dv, aa->aa_node->ad_handle, "_CRS",
	    &res, &acpi_resource_parse_ops_default);
	if (ACPI_FAILURE(rv))
		return;

	/* find our IRQ */
	irq = acpi_res_irq(&res, 0);
	if (irq == NULL) {
		aprint_error_dev(self, "unable to find irq resource\n");
		goto out;
	}
	psc->sc_irq = irq->ar_irq;
	psc->sc_ist = (irq->ar_type == ACPI_EDGE_SENSITIVE) ? IST_EDGE : IST_LEVEL;

	if (psc->sc_slot == PCKBC_KBD_SLOT)
		first = psc;

	if ((!first || !first->sc_pckbc.id) &&
	    (psc->sc_slot == PCKBC_KBD_SLOT)) {

		io0 = acpi_res_io(&res, 0);
		io1 = acpi_res_io(&res, 1);
		if (io0 == NULL || io1 == NULL) {
			aprint_error_dev(self,
			    "unable to find i/o resources\n");
			goto out;
		}

		/*
		 * JDM: Some firmware doesn't report resources in the order we
		 * expect; sort IO resources here (lowest first)
		 */
		if (io0->ar_base > io1->ar_base) {
			ioswap = io0;
			io0 = io1;
			io1 = ioswap;
		}

		if (pckbc_is_console(aa->aa_iot, io0->ar_base)) {
			t = &pckbc_consdata;
			ioh_d = t->t_ioh_d;
			ioh_c = t->t_ioh_c;
			pckbc_console_attached = 1;
			/* t->t_cmdbyte was initialized by cnattach */
		} else {
			if (bus_space_map(aa->aa_iot, io0->ar_base,
					  io0->ar_length, 0, &ioh_d) ||
			    bus_space_map(aa->aa_iot, io1->ar_base,
					  io1->ar_length, 0, &ioh_c))
				panic("pckbc_acpi_attach: couldn't map");

			t = malloc(sizeof(struct pckbc_internal),
			    M_DEVBUF, M_WAITOK|M_ZERO);
			t->t_iot = aa->aa_iot;
			t->t_ioh_d = ioh_d;
			t->t_ioh_c = ioh_c;
			t->t_addr = io0->ar_base;
			t->t_cmdbyte = KC8_CPU;	/* Enable ports */
			callout_init(&t->t_cleanup, 0);
		}

		t->t_sc = &first->sc_pckbc;
		first->sc_pckbc.id = t;

		if (!pmf_device_register(self, NULL, pckbc_resume))
			aprint_error_dev(self,
			    "couldn't establish power handler\n");

		first->sc_pckbc.intr_establish = pckbc_acpi_intr_establish;
		config_defer(first->sc_pckbc.sc_dv, pckbc_acpi_finish_attach);
	} else if (!pmf_device_register(self, NULL, NULL))
		aprint_error_dev(self, "couldn't establish power handler\n");
 out:
	acpi_resource_cleanup(&res);
}
예제 #5
0
int
pckbc_isa_match(device_t parent, cfdata_t match, void *aux)
{
	struct isa_attach_args *ia = aux;
	bus_space_tag_t iot = ia->ia_iot;
	bus_space_handle_t ioh_d, ioh_c;
	int res, ok = 1;

	if (ISA_DIRECT_CONFIG(ia))
		return (0);

	/* If values are hardwired to something that they can't be, punt. */
	if (ia->ia_nio < 1 ||
	    (ia->ia_io[0].ir_addr != ISA_UNKNOWN_PORT &&
	     ia->ia_io[0].ir_addr != IO_KBD))
		return (0);

	if (ia->ia_niomem > 0 &&
	    (ia->ia_iomem[0].ir_addr != ISA_UNKNOWN_IOMEM))
		return (0);

	if (ia->ia_nirq < 1 ||
	    (ia->ia_irq[0].ir_irq != ISA_UNKNOWN_IRQ &&
	     ia->ia_irq[0].ir_irq != 1 /*XXX*/))
		return (0);

	if (ia->ia_ndrq > 0 &&
	    (ia->ia_drq[0].ir_drq != ISA_UNKNOWN_DRQ))
		return (0);

	if (pckbc_is_console(iot, IO_KBD) == 0) {
		struct pckbc_internal t;

		if (bus_space_map(iot, IO_KBD + KBDATAP, 1, 0, &ioh_d))
			return (0);
		if (bus_space_map(iot, IO_KBD + KBCMDP, 1, 0, &ioh_c)) {
			bus_space_unmap(iot, ioh_d, 1);
			return (0);
		}

		memset(&t, 0, sizeof(t));
		t.t_iot = iot;
		t.t_ioh_d = ioh_d;
		t.t_ioh_c = ioh_c;

		/* flush KBC */
		(void) pckbc_poll_data1(&t, PCKBC_KBD_SLOT);

		/* KBC selftest */
		if (pckbc_send_cmd(iot, ioh_c, KBC_SELFTEST) == 0) {
			ok = 0;
			goto out;
		}
		res = pckbc_poll_data1(&t, PCKBC_KBD_SLOT);
#ifndef PCKBCNOTEST
		if (res != 0x55) {
#ifdef PCKBCDEBUG
			aprint_verbose("kbc selftest: %x\n", res);
#endif
			ok = 0;
		}
#endif /* PCKBCNOTEST */
 out:
		bus_space_unmap(iot, ioh_d, 1);
		bus_space_unmap(iot, ioh_c, 1);
	}

	if (ok) {
		ia->ia_io[0].ir_addr = IO_KBD;
		ia->ia_io[0].ir_size = 5;
		ia->ia_nio = 1;

		ia->ia_niomem = 0;
		ia->ia_nirq = 0;
		ia->ia_ndrq = 0;
	}
	return (ok);
}
예제 #6
0
void
pckbc_isa_attach(device_t parent, device_t self, void *aux)
{
	struct pckbc_isa_softc *isc = device_private(self);
	struct pckbc_softc *sc = &isc->sc_pckbc;
	struct isa_attach_args *ia = aux;
	struct pckbc_internal *t;
	bus_space_tag_t iot;
	bus_space_handle_t ioh_d, ioh_c;

	sc->sc_dv = self;
	isc->sc_ic = ia->ia_ic;
	iot = ia->ia_iot;

	switch (ia->ia_nirq) {
	case 1:
		/* Both channels use the same IRQ. */
		isc->sc_irq[PCKBC_KBD_SLOT] =
		    isc->sc_irq[PCKBC_AUX_SLOT] = ia->ia_irq[0].ir_irq;
		break;

	case 2:
		/* First IRQ is kbd, second IRQ is aux port. */
		isc->sc_irq[PCKBC_KBD_SLOT] = ia->ia_irq[0].ir_irq;
		isc->sc_irq[PCKBC_AUX_SLOT] = ia->ia_irq[1].ir_irq;
		break;

	default:
		/* Set up IRQs for "normal" ISA. */
		isc->sc_irq[PCKBC_KBD_SLOT] = 1;
		isc->sc_irq[PCKBC_AUX_SLOT] = 12;
		break;
	}

	sc->intr_establish = pckbc_isa_intr_establish;

	if (pckbc_is_console(iot, IO_KBD)) {
		t = &pckbc_consdata;
		ioh_d = t->t_ioh_d;
		ioh_c = t->t_ioh_c;
		pckbc_console_attached = 1;
		/* t->t_cmdbyte was initialized by cnattach */
	} else {
		if (bus_space_map(iot, IO_KBD + KBDATAP, 1, 0, &ioh_d) ||
		    bus_space_map(iot, IO_KBD + KBCMDP, 1, 0, &ioh_c))
			panic("pckbc_attach: couldn't map");

		t = malloc(sizeof(struct pckbc_internal), M_DEVBUF,
		    M_WAITOK|M_ZERO);
		t->t_iot = iot;
		t->t_ioh_d = ioh_d;
		t->t_ioh_c = ioh_c;
		t->t_addr = IO_KBD;
		t->t_cmdbyte = KC8_CPU; /* Enable ports */
		callout_init(&t->t_cleanup, 0);
	}

	t->t_sc = sc;
	sc->id = t;

	aprint_normal("\n");

	if (!pmf_device_register(self, NULL, pckbc_resume))
		aprint_error_dev(self, "couldn't establish power handler\n");

	/* Finish off the attach. */
	pckbc_attach(sc);
}