Beispiel #1
0
static void
pchb_attach(struct device *parent, struct device *self, void *aux)
{
	struct pci_attach_args *pa = aux;
	char devinfo[256];

	printf("\n");
	pcifound++;

	/*
	 * All we do is print out a description.  Eventually, we
	 * might want to add code that does something that's
	 * possibly chipset-specific.
	 */
	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_GALILEO &&
	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_GALILEO_GT64120) {
		/* Bah, same product ID... */

		/*
		 * XXX:	Is the >= 0x10 test correct?  The '120 doco
		 *	lists rev == 0x02 and the '120A doco lists
		 *	rev == 0x10.
		 */
		snprintf(devinfo, sizeof(devinfo),
		    "Galileo Technology GT-64120%s System Controller",
		    PCI_REVISION(pa->pa_class) >= 0x10 ? "A" : "");
	} else {
		pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
	}
	printf("%s: %s (rev. 0x%02x)\n", self->dv_xname, devinfo,
	    PCI_REVISION(pa->pa_class));
}
Beispiel #2
0
int
pciprint(void *aux, const char *pnp)
{
	struct pci_attach_args *pa = aux;
	char devinfo[256];
	const struct pci_quirkdata *qd;

	if (pnp) {
		pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo));
		aprint_normal("%s at %s", devinfo, pnp);
	}
	aprint_normal(" dev %d function %d", pa->pa_device, pa->pa_function);
	if (pci_config_dump) {
		printf(": ");
		pci_conf_print(pa->pa_pc, pa->pa_tag, NULL);
		if (!pnp)
			pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo));
		printf("%s at %s", devinfo, pnp ? pnp : "?");
		printf(" dev %d function %d (", pa->pa_device, pa->pa_function);
#ifdef __i386__
		printf("tag %#lx, intrtag %#lx, intrswiz %#lx, intrpin %#lx",
		    *(long *)&pa->pa_tag, *(long *)&pa->pa_intrtag,
		    (long)pa->pa_intrswiz, (long)pa->pa_intrpin);
#else
		printf("intrswiz %#lx, intrpin %#lx",
		    (long)pa->pa_intrswiz, (long)pa->pa_intrpin);
#endif
		printf(", i/o %s, mem %s,",
		    pa->pa_flags & PCI_FLAGS_IO_OKAY ? "on" : "off",
		    pa->pa_flags & PCI_FLAGS_MEM_OKAY ? "on" : "off");
		qd = pci_lookup_quirkdata(PCI_VENDOR(pa->pa_id),
		    PCI_PRODUCT(pa->pa_id));
		if (qd == NULL) {
			printf(" no quirks");
		} else {
			snprintb(devinfo, sizeof (devinfo),
			    "\002\001multifn\002singlefn\003skipfunc0"
			    "\004skipfunc1\005skipfunc2\006skipfunc3"
			    "\007skipfunc4\010skipfunc5\011skipfunc6"
			    "\012skipfunc7", qd->quirks);
			printf(" quirks %s", devinfo);
		}
		printf(")");
	}
	return UNCONF;
}
Beispiel #3
0
void
pchbattach(struct device *parent, struct device *self, void *aux)
{
	struct pci_attach_args *pa = aux;
	char devinfo[256];
#if NAGP > 0
	struct agpbus_attach_args apa;
#endif
	volatile unsigned char *python;
	uint32_t v;
	
	aprint_normal("\n");

	/*
	 * All we do is print out a description.  Eventually, we
	 * might want to add code that does something that's
	 * possibly chipset-specific.
	 */

	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
	aprint_normal("%s: %s (rev. 0x%02x)\n", self->dv_xname, devinfo,
	    PCI_REVISION(pa->pa_class));

	switch (PCI_VENDOR(pa->pa_id)) {
	case PCI_VENDOR_IBM:
		switch (PCI_PRODUCT(pa->pa_id)) {
		case PCI_PRODUCT_IBM_82660:
			ibm82660_print(pa, self);
			break;
		case PCI_PRODUCT_IBM_PYTHON:
			python = mapiodev(0xfeff6000, 0x60);
			v = 0x88b78e01; /* taken from linux */
			out32rb(python+0x30, v);
			v = in32rb(python+0x30);
			aprint_debug("Reset python reg 30 to 0x%x\n", v);
			break;
		}
		break;
	case PCI_VENDOR_MOT:
		switch (PCI_PRODUCT(pa->pa_id)) {
		case PCI_PRODUCT_MOT_MPC105:
			mpc105_print(pa, self);
			break;
		case PCI_PRODUCT_MOT_MPC106:
			mpc106_print(pa, self);
			break;
		}
		break;
	}

#if NAGP > 0
	if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP,
			       NULL, NULL) != 0) {
		apa.apa_pci_args = *pa;
		config_found_ia(self, "agpbus", &apa, agpbusprint);
	}
#endif /* NAGP */
}
static void
nfsmbc_attach(device_t parent, device_t self, void *aux)
{
	struct nfsmbc_softc *sc = device_private(self);
	struct pci_attach_args *pa = aux;
	struct nfsmbc_attach_args nfsmbca;
	pcireg_t reg;
	int baseregs[2];
	char devinfo[256];

	aprint_naive("\n");
	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
	aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
	    PCI_REVISION(pa->pa_class));

	sc->sc_dev = self;
	sc->sc_pc = pa->pa_pc;
	sc->sc_tag = pa->pa_tag;
	sc->sc_pa = pa;
	sc->sc_iot = pa->pa_iot;

	nfsmbca.nfsmb_iot = sc->sc_iot;

	switch (PCI_PRODUCT(pa->pa_id)) {
	case PCI_PRODUCT_NVIDIA_NFORCE2_SMBUS:
	case PCI_PRODUCT_NVIDIA_NFORCE2_400_SMBUS:
	case PCI_PRODUCT_NVIDIA_NFORCE3_SMBUS:
	case PCI_PRODUCT_NVIDIA_NFORCE3_250_SMBUS:
	case PCI_PRODUCT_NVIDIA_NFORCE4_SMBUS:
		baseregs[0] = NFORCE_OLD_SMB1;
		baseregs[1] = NFORCE_OLD_SMB2;
		break;
	default:
		baseregs[0] = NFORCE_SMB1;
		baseregs[1] = NFORCE_SMB2;
		break;
	}

	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, baseregs[0]);
	nfsmbca.nfsmb_num = 1;
	nfsmbca.nfsmb_addr = NFORCE_SMBBASE(reg);
	sc->sc_nfsmb[0] = config_found(sc->sc_dev, &nfsmbca, nfsmbc_print);

	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, baseregs[1]);
	nfsmbca.nfsmb_num = 2;
	nfsmbca.nfsmb_addr = NFORCE_SMBBASE(reg);
	sc->sc_nfsmb[1] = config_found(sc->sc_dev, &nfsmbca, nfsmbc_print);

	/* This driver is similar to an ISA bridge that doesn't
	 * need any special handling. So registering NULL handlers
	 * are sufficent. */
	if (!pmf_device_register(self, NULL, NULL))
		aprint_error_dev(self, "couldn't establish power handler\n");
}
static void
ahci_pci_attach(device_t parent, device_t self, void *aux)
{
	struct pci_attach_args *pa = aux;
	struct ahci_pci_softc *psc = device_private(self);
	struct ahci_softc *sc = &psc->ah_sc;
	bus_size_t size;
	char devinfo[256];
	const char *intrstr;
	pci_intr_handle_t intrhandle;
	void *ih;

	sc->sc_atac.atac_dev = self;

	if (pci_mapreg_map(pa, AHCI_PCI_ABAR,
	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &sc->sc_ahcit, &sc->sc_ahcih, NULL, &size) != 0) {
		aprint_error_dev(self, "can't map ahci registers\n");
		return;
	}
	psc->sc_pc = pa->pa_pc;
	psc->sc_pcitag = pa->pa_tag;

	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
	aprint_naive(": AHCI disk controller\n");
	aprint_normal(": %s\n", devinfo);
	
	if (pci_intr_map(pa, &intrhandle) != 0) {
		aprint_error("%s: couldn't map interrupt\n", AHCINAME(sc));
		return;
	}
	intrstr = pci_intr_string(pa->pa_pc, intrhandle);
	ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO, ahci_intr, sc);
	if (ih == NULL) {
		aprint_error("%s: couldn't establish interrupt", AHCINAME(sc));
		return;
	}
	aprint_normal("%s: interrupting at %s\n", AHCINAME(sc),
	    intrstr ? intrstr : "unknown interrupt");
	sc->sc_dmat = pa->pa_dmat;

	if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_RAID) {
		AHCIDEBUG_PRINT(("%s: RAID mode\n", AHCINAME(sc)), DEBUG_PROBE);
		sc->sc_atac_capflags = ATAC_CAP_RAID;
	} else {
		AHCIDEBUG_PRINT(("%s: SATA mode\n", AHCINAME(sc)), DEBUG_PROBE);
	}

	ahci_attach(sc);

	if (!pmf_device_register(self, NULL, ahci_pci_resume))
		aprint_error_dev(self, "couldn't establish power handler\n");
}
Beispiel #6
0
static void
pcib_attach(device_t parent, device_t self, void *aux)
{
	struct pci_attach_args *pa = aux;
	char devinfo[256];

	aprint_normal("\n");
	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
	aprint_normal_dev(self, "%s, rev %d\n", devinfo,
	    PCI_REVISION(pa->pa_class));

}
void
ral_cardbus_attach(struct device *parent, struct device *self,
    void *aux)
{
	struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)self;
	struct rt2560_softc *sc = &csc->sc_sc;
	struct cardbus_attach_args *ca = aux;
	cardbus_devfunc_t ct = ca->ca_ct;
	char devinfo[256];
	bus_addr_t base;
	int error, revision;

	pci_devinfo(ca->ca_id, ca->ca_class, 0, devinfo, sizeof(devinfo));
	revision = PCI_REVISION(ca->ca_class);
	aprint_normal(": %s (rev. 0x%02x)\n", devinfo, revision);

	csc->sc_opns =
	    (CARDBUS_PRODUCT(ca->ca_id) == PCI_PRODUCT_RALINK_RT2560) ?
	    &ral_rt2560_opns : &ral_rt2661_opns;

	sc->sc_dmat = ca->ca_dmat;
	csc->sc_ct = ct;
	csc->sc_tag = ca->ca_tag;
	csc->sc_intrline = ca->ca_intrline;

	/* power management hooks */
	sc->sc_enable = ral_cardbus_enable;
	sc->sc_disable = ral_cardbus_disable;

	/* map control/status registers */
	error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
	    CARDBUS_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, &base,
	    &csc->sc_mapsize);
	if (error != 0) {
		printf(": could not map memory space\n");
		return;
	}

#if rbus
#else
	(*cf->cardbus_mem_open)(cc, 0, base, base + csc->sc_mapsize);
#endif

	csc->sc_bar_val = base | CARDBUS_MAPREG_TYPE_MEM;

	/* set up the PCI configuration registers */
	ral_cardbus_setup(csc);

	(*csc->sc_opns->attach)(sc, CARDBUS_PRODUCT(ca->ca_id));

	Cardbus_function_disable(ct);
}
Beispiel #8
0
int
jmb_print(void *aux, const char *pnp)
{
	struct pci_attach_args		*pa = aux;
	char				devinfo[256];

	if (pnp != NULL) {
		pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo,
		    sizeof(devinfo));
		printf("%s at %s", devinfo, pnp);
	}

	return (UNCONF);
}
Beispiel #9
0
void
ral_cardbus_attach(device_t parent, device_t self, void *aux)
{
	struct ral_cardbus_softc *csc = device_private(self);
	struct rt2560_softc *sc = &csc->sc_sc;
	struct cardbus_attach_args *ca = aux;
	cardbus_devfunc_t ct = ca->ca_ct;
	char devinfo[256];
	bus_addr_t base;
	int error, revision;

	pci_devinfo(ca->ca_id, ca->ca_class, 0, devinfo, sizeof(devinfo));
	revision = PCI_REVISION(ca->ca_class);
	aprint_normal(": %s (rev. 0x%02x)\n", devinfo, revision);

	csc->sc_opns =
	    (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_RALINK_RT2560) ?
	    &ral_rt2560_opns : &ral_rt2661_opns;

	sc->sc_dev = self;
	sc->sc_dmat = ca->ca_dmat;
	csc->sc_ct = ct;
	csc->sc_tag = ca->ca_tag;

	/* power management hooks */
	sc->sc_enable = ral_cardbus_enable;
	sc->sc_disable = ral_cardbus_disable;

	/* map control/status registers */
	error = Cardbus_mapreg_map(ct, PCI_BAR0,
	    PCI_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, &base,
	    &csc->sc_mapsize);
	if (error != 0) {
		aprint_error(": could not map memory space\n");
		return;
	}

	csc->sc_bar_val = base | PCI_MAPREG_TYPE_MEM;

	/* set up the PCI configuration registers */
	ral_cardbus_setup(csc);

	(*csc->sc_opns->attach)(sc, PCI_PRODUCT(ca->ca_id));

	Cardbus_function_disable(ct);
}
void
pcmbattach(device_t parent, device_t self, void *aux)
{
	struct pci_attach_args *pa = aux;
	char devinfo[256];

	aprint_naive("\n");
	aprint_normal("\n");

	/*
	 * Just print out a description and defer configuration
	 * until all PCI devices have been attached.
	 */
	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
	aprint_normal_dev(self, "%s (rev. 0x%02x)\n", devinfo,
	    PCI_REVISION(pa->pa_class));

	config_defer(self, pcmb_callback);
}
static void
joy_pci_attach(device_t parent, device_t self, void *aux)
{
	struct joy_softc *sc = device_private(self);
	struct pci_attach_args *pa = aux;
	char devinfo[256];
	bus_size_t mapsize;
	int reg;

	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
	aprint_normal(": %s (rev 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class));
	
	for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END;
	     reg += sizeof(pcireg_t))
		if (bar_is_io(pa->pa_pc, pa->pa_tag, reg))
			break;
	if (reg >= PCI_MAPREG_END) {
		aprint_error_dev(self,
		    "violates PCI spec, no IO region found\n");
		return;
	}

	if (pci_mapreg_map(pa, reg, PCI_MAPREG_TYPE_IO, 0,
	    &sc->sc_iot, &sc->sc_ioh, NULL, &mapsize)) {
		aprint_error_dev(self, "could not map IO space\n");
		return;
	}

	if (mapsize != 2) {
		if (!bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1, 1, &sc->sc_ioh) < 0) {
			aprint_error_dev(self, "error mapping subregion\n");
			return;
		}
	}

	sc->sc_dev = self;

	joyattach(sc);
}
void
ohci_cardbus_attach(device_t parent, device_t self, void *aux)
{
	struct ohci_cardbus_softc *sc = device_private(self);
	struct cardbus_attach_args *ca = aux;
	cardbus_devfunc_t ct = ca->ca_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;
	pcireg_t csr;
	char devinfo[256];
	usbd_status r;
	const char *vendor;
	const char *devname = device_xname(self);

	sc->sc.sc_dev = self;
	sc->sc.sc_bus.hci_private = sc;

	pci_devinfo(ca->ca_id, ca->ca_class, 0, devinfo, sizeof(devinfo));
	printf(": %s (rev. 0x%02x)\n", devinfo,
	       PCI_REVISION(ca->ca_class));

	/* Map I/O registers */
	if (Cardbus_mapreg_map(ct, PCI_CBMEM, PCI_MAPREG_TYPE_MEM, 0,
			   &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size)) {
		printf("%s: can't map mem space\n", devname);
		return;
	}

	sc->sc_cc = cc;
	sc->sc_cf = cf;
	sc->sc_ct = ct;
	sc->sc.sc_bus.dmatag = ca->ca_dmat;

	/* Enable the device. */
	csr = Cardbus_conf_read(ct, ca->ca_tag,
				PCI_COMMAND_STATUS_REG);
	Cardbus_conf_write(ct, ca->ca_tag, PCI_COMMAND_STATUS_REG,
		       csr | PCI_COMMAND_MASTER_ENABLE
			   | PCI_COMMAND_MEM_ENABLE);

	/* Disable interrupts, so we don't can any spurious ones. */
	bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE,
			  OHCI_ALL_INTRS);

	sc->sc_ih = Cardbus_intr_establish(ct, IPL_USB, ohci_intr, sc);
	if (sc->sc_ih == NULL) {
		printf("%s: couldn't establish interrupt\n", devname);
		return;
	}

	/* Figure out vendor for root hub descriptor. */
	vendor = pci_findvendor(ca->ca_id);
	sc->sc.sc_id_vendor = PCI_VENDOR(ca->ca_id);
	if (vendor)
		strlcpy(sc->sc.sc_vendor, vendor, sizeof(sc->sc.sc_vendor));
	else
		snprintf(sc->sc.sc_vendor, sizeof(sc->sc.sc_vendor),
		    "vendor 0x%04x", PCI_VENDOR(ca->ca_id));

	r = ohci_init(&sc->sc);
	if (r != USBD_NORMAL_COMPLETION) {
		printf("%s: init failed, error=%d\n", devname, r);

		/* Avoid spurious interrupts. */
		Cardbus_intr_disestablish(ct, sc->sc_ih);
		sc->sc_ih = 0;

		return;
	}

#if NEHCI_CARDBUS > 0
	usb_cardbus_add(&sc->sc_cardbus, ca, self);
#endif

	if (!pmf_device_register1(self, ohci_suspend, ohci_resume,
	                          ohci_shutdown))
		aprint_error_dev(self, "couldn't establish power handler\n");

	/* Attach usb device. */
	sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint);
}
static void
uhci_cardbus_attach(device_t parent, device_t self,
    void *aux)
{
	struct uhci_cardbus_softc *sc = device_private(self);
	struct cardbus_attach_args *ca = (struct cardbus_attach_args *)aux;
	cardbus_devfunc_t ct = ca->ca_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;
	pcitag_t tag = ca->ca_tag;
	pcireg_t csr;
	const char *vendor;
	const char *devname = device_xname(self);
	char devinfo[256];
	usbd_status r;

	sc->sc.sc_dev = self;
	sc->sc.sc_bus.hci_private = sc;

	pci_devinfo(ca->ca_id, ca->ca_class, 0, devinfo, sizeof(devinfo));
	printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(ca->ca_class));

	/* Map I/O registers */
	if (Cardbus_mapreg_map(ct, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
			   &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size)) {
		printf("%s: can't map i/o space\n", devname);
		return;
	}

	sc->sc_cc = cc;
	sc->sc_cf = cf;
	sc->sc_ct = ct;
	sc->sc_tag = tag;
	sc->sc.sc_bus.dmatag = ca->ca_dmat;

	/* Enable the device. */
	csr = Cardbus_conf_read(ct, tag, PCI_COMMAND_STATUS_REG);
	Cardbus_conf_write(ct, tag, PCI_COMMAND_STATUS_REG,
		       csr | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE);

	/* Disable interrupts, so we don't get any spurious ones. */
	bus_space_write_2(sc->sc.iot, sc->sc.ioh, UHCI_INTR, 0);

	/* Map and establish the interrupt. */
	sc->sc_ih = Cardbus_intr_establish(ct, IPL_USB, uhci_intr, sc);
	if (sc->sc_ih == NULL) {
		printf("%s: couldn't establish interrupt\n", devname);
		return;
	}

	/* Set LEGSUP register to its default value. */
	Cardbus_conf_write(ct, tag, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN);

	switch(Cardbus_conf_read(ct, tag, PCI_USBREV) & PCI_USBREV_MASK) {
	case PCI_USBREV_PRE_1_0:
		sc->sc.sc_bus.usbrev = USBREV_PRE_1_0;
		break;
	case PCI_USBREV_1_0:
		sc->sc.sc_bus.usbrev = USBREV_1_0;
		break;
	case PCI_USBREV_1_1:
		sc->sc.sc_bus.usbrev = USBREV_1_1;
		break;
	default:
		sc->sc.sc_bus.usbrev = USBREV_UNKNOWN;
		break;
	}

	/* Figure out vendor for root hub descriptor. */
	vendor = pci_findvendor(ca->ca_id);
	sc->sc.sc_id_vendor = PCI_VENDOR(ca->ca_id);
	if (vendor)
		strlcpy(sc->sc.sc_vendor, vendor, sizeof(sc->sc.sc_vendor));
	else
		snprintf(sc->sc.sc_vendor, sizeof(sc->sc.sc_vendor),
		    "vendor 0x%04x", PCI_VENDOR(ca->ca_id));

	r = uhci_init(&sc->sc);
	if (r != USBD_NORMAL_COMPLETION) {
		printf("%s: init failed, error=%d\n", devname, r);

		/* Avoid spurious interrupts. */
		Cardbus_intr_disestablish(ct, sc->sc_ih);
		sc->sc_ih = NULL;

		return;
	}

#if NEHCI_CARDBUS > 0
	usb_cardbus_add(&sc->sc_cardbus, ca, self);
#endif

	/* Attach usb device. */
	sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint);
}
static void
wi_pci_attach(struct device *parent, struct device *self, void *aux)
{
	struct wi_pci_softc *psc = (struct wi_pci_softc *)self;
	struct wi_softc *sc = &psc->psc_wi;
	struct pci_attach_args *pa = aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	const char *intrstr;
	const struct wi_pci_product *wpp;
	pci_intr_handle_t ih;
	bus_space_tag_t memt, iot, plxt, tmdt;
	bus_space_handle_t memh, ioh, plxh, tmdh;

	psc->psc_pc = pc;
	psc->psc_pcitag = pa->pa_tag;

	wpp = wi_pci_lookup(pa);
#ifdef DIAGNOSTIC
	if (wpp == NULL) {
		printf("\n");
		panic("wi_pci_attach: impossible");
	}
#endif

	switch (wpp->wpp_chip) {
	case CHIP_PLX_OTHER:
	case CHIP_PLX_9052:
		/* Map memory and I/O registers. */
		if (pci_mapreg_map(pa, WI_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
		    &memt, &memh, NULL, NULL) != 0) {
			printf(": can't map mem space\n");
			return;
		}
		if (pci_mapreg_map(pa, WI_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
		    &iot, &ioh, NULL, NULL) != 0) {
			printf(": can't map I/O space\n");
			return;
		}

		if (wpp->wpp_chip == CHIP_PLX_OTHER) {
			/* The PLX 9052 doesn't have IO at 0x14.  Perhaps
			   other chips have, so we'll make this conditional. */
			if (pci_mapreg_map(pa, WI_PCI_PLX_LOIO,
				PCI_MAPREG_TYPE_IO, 0, &plxt,
				&plxh, NULL, NULL) != 0) {
					printf(": can't map PLX\n");
					return;
				}
		}
		break;
	case CHIP_TMD_7160:
		/* Used instead of PLX on at least one revision of
		 * the National Datacomm Corporation NCP130. Values
		 * for registers acquired from OpenBSD, which in
		 * turn got them from a Linux driver.
		 */
		/* Map COR and I/O registers. */
		if (pci_mapreg_map(pa, WI_TMD_COR, PCI_MAPREG_TYPE_IO, 0,
		    &tmdt, &tmdh, NULL, NULL) != 0) {
			printf(": can't map TMD\n");
			return;
		}
		if (pci_mapreg_map(pa, WI_TMD_IO, PCI_MAPREG_TYPE_IO, 0,
		    &iot, &ioh, NULL, NULL) != 0) {
			printf(": can't map I/O space\n");
			return;
		}
		break;
	default:
		if (pci_mapreg_map(pa, WI_PCI_CBMA,
		    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
		    0, &iot, &ioh, NULL, NULL) != 0) {
			printf(": can't map mem space\n");
			return;
		}

		memt = iot;
		memh = ioh;
		sc->sc_pci = 1;
		break;
	}

	{
		char devinfo[256];

		pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
		printf(": %s (rev. 0x%02x)\n", devinfo,
		       PCI_REVISION(pa->pa_class));
	}

	sc->sc_enabled = 1;
	sc->sc_enable = wi_pci_enable;
	sc->sc_disable = wi_pci_disable;

	sc->sc_iot = iot;
	sc->sc_ioh = ioh;
	/* Make sure interrupts are disabled. */
	CSR_WRITE_2(sc, WI_INT_EN, 0);
	CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);

	if (wpp->wpp_chip == CHIP_PLX_OTHER) {
		uint32_t command;
#define	WI_LOCAL_INTCSR		0x4c
#define	WI_LOCAL_INTEN		0x40	/* poke this into INTCSR */

		command = bus_space_read_4(plxt, plxh, WI_LOCAL_INTCSR);
		command |= WI_LOCAL_INTEN;
		bus_space_write_4(plxt, plxh, WI_LOCAL_INTCSR, command);
	}

	/* Map and establish the interrupt. */
	if (pci_intr_map(pa, &ih)) {
		aprint_error_dev(self, "couldn't map interrupt\n");
		return;
	}
	intrstr = pci_intr_string(pc, ih);

	psc->psc_ih = ih;
	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, wi_intr, sc);
	if (sc->sc_ih == NULL) {
		aprint_error_dev(self, "couldn't establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		return;
	}

	printf("%s: interrupting at %s\n", device_xname(self), intrstr);

	switch (wpp->wpp_chip) {
	case CHIP_PLX_OTHER:
	case CHIP_PLX_9052:
		/*
		 * Setup the PLX chip for level interrupts and config index 1
		 * XXX - should really reset the PLX chip too.
		 */
		bus_space_write_1(memt, memh,
		    WI_PLX_COR_OFFSET, WI_PLX_COR_VALUE);
		break;
	case CHIP_TMD_7160:
		/* Enable I/O mode and level interrupts on the embedded
		 * card. The card's COR is the first byte of BAR 0.
		 */
		bus_space_write_1(tmdt, tmdh, 0, WI_COR_IOMODE);
		break;
	default:
		/* reset HFA3842 MAC core */
		wi_pci_reset(sc);
		break;
	}

	printf("%s:", device_xname(self));

	if (wi_attach(sc, 0) != 0) {
		aprint_error_dev(self, "failed to attach controller\n");
		pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
		return;
	}

	if (!wpp->wpp_chip)
		sc->sc_reset = wi_pci_reset;

	if (!pmf_device_register(self, NULL, NULL))
		aprint_error_dev(self, "couldn't establish power handler\n");
	else
		pmf_class_network_register(self, &sc->sc_if);
}
Beispiel #15
0
/*static*/ 
void ndis_attach_pci(device_t parent, device_t self, void *aux)
{
	struct ndis_softc *sc = device_private(self);
	struct pci_attach_args *pa = aux;
#ifdef NDIS_DBG       
	char devinfo[256];
#endif
	pci_intr_handle_t ih;
	pcireg_t type;
	bus_addr_t	base;
	bus_size_t	size;
	int		flags;
	ndis_resource_list 		*rl  = NULL;
	struct cm_partial_resource_desc	*prd = NULL;
#ifdef NDIS_DBG
	struct pci_conf_state conf_state;
	int revision, i;
#endif
	int bar;
	size_t rllen;
	
	printf("in ndis_attach_pci()\n");

	/* initalize the softc */
	//sc->ndis_hardware_type  = NDIS_PCI;
	sc->ndis_dev		= self;
	sc->ndis_iftype 	= PCIBus;
	sc->ndis_res_pc		= pa->pa_pc;
	sc->ndis_res_pctag	= pa->pa_tag;
	/* TODO: is this correct? All are just pa->pa_dmat? */	
	sc->ndis_mtag		= pa->pa_dmat;
	sc->ndis_ttag		= pa->pa_dmat;
	sc->ndis_parent_tag 	= pa->pa_dmat;
	sc->ndis_res_io		= NULL;
	sc->ndis_res_mem	= NULL;
	sc->ndis_res_altmem	= NULL;
	sc->ndis_block 		= NULL;
	sc->ndis_shlist		= NULL;
	
	ndis_in_isr		= FALSE;
	
	printf("sc->ndis_mtag = %x\n", (unsigned int)sc->ndis_mtag);

	rllen = sizeof(ndis_resource_list) +
	    sizeof(cm_partial_resource_desc) * (MAX_RESOURCES - 1);
	rl = malloc(rllen, M_DEVBUF, M_NOWAIT|M_ZERO);

	if(rl == NULL) {
		sc->error = ENOMEM;
		//printf("error: out of memory\n");
		return;
	}
	
	rl->cprl_version = 5;
	rl->cprl_version = 1;    
	rl->cprl_count = 0;
	prd = rl->cprl_partial_descs;
	
#ifdef NDIS_DBG
        pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof devinfo);
        revision = PCI_REVISION(pa->pa_class);
        printf(": %s (rev. 0x%02x)\n", devinfo, revision);
	
	pci_conf_print(sc->ndis_res_pc, sc->ndis_res_pctag, NULL);

	pci_conf_capture(sc->ndis_res_pc, sc->ndis_res_pctag, &conf_state);
	for(i=0; i<16; i++) {
		printf("conf_state.reg[%d] = %x\n", i, conf_state.reg[i]);
	}
#endif
	
	/* just do the conversion work in attach instead of calling ndis_convert_res() */
	for(bar = 0x10; bar <= 0x24; bar += 0x04) {
		type = pci_mapreg_type(sc->ndis_res_pc, sc->ndis_res_pctag, bar);
		if(pci_mapreg_info(sc->ndis_res_pc, sc->ndis_res_pctag, bar, type, &base,
			&size, &flags)) {
			printf("pci_mapreg_info() failed on BAR 0x%x!\n", bar);
		} else {			
			switch(type) {
			case PCI_MAPREG_TYPE_IO:
				prd->cprd_type 				= CmResourceTypePort;
				prd->cprd_flags 			= CM_RESOURCE_PORT_IO;
				prd->u.cprd_port.cprd_start.np_quad 	= (uint64_t)base;
				prd->u.cprd_port.cprd_len  	  	= (uint32_t)size;
				if((sc->ndis_res_io = 
					malloc(sizeof(struct ndis_resource), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
					//printf("error: out of memory\n");
					sc->error = ENOMEM;
					goto out;
				}
				sc->ndis_res_io->res_base = base;
				sc->ndis_res_io->res_size = size;
				sc->ndis_res_io->res_tag  = x86_bus_space_io;
				bus_space_map(sc->ndis_res_io->res_tag,
					 sc->ndis_res_io->res_base,
					 sc->ndis_res_io->res_size,
					 flags,
					&sc->ndis_res_io->res_handle);
				break;
			case PCI_MAPREG_TYPE_MEM:
				prd->cprd_type 				= CmResourceTypeMemory;
				prd->cprd_flags 			= CM_RESOURCE_MEMORY_READ_WRITE;
				prd->u.cprd_mem.cprd_start.np_quad 	= (uint64_t)base;
				prd->u.cprd_mem.cprd_len		= (uint32_t)size;
				
				if(sc->ndis_res_mem != NULL && 
					sc->ndis_res_altmem != NULL) {
					printf("too many resources\n");
					sc->error = ENXIO;
					goto out;
				}
				if(sc->ndis_res_mem) {
					if((sc->ndis_res_altmem = 
						malloc(sizeof(struct ndis_resource), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
						sc->error = ENOMEM;
						return;
					}
					sc->ndis_res_altmem->res_base = base;
					sc->ndis_res_altmem->res_size = size;
					sc->ndis_res_altmem->res_tag  = x86_bus_space_mem;
					
					
					if(bus_space_map(sc->ndis_res_altmem->res_tag,
						sc->ndis_res_altmem->res_base,
						sc->ndis_res_altmem->res_size,
						flags|BUS_SPACE_MAP_LINEAR,
						&sc->ndis_res_altmem->res_handle)) {
							printf("bus_space_map failed\n");
					}
				} else {
					if((sc->ndis_res_mem = 
						malloc(sizeof(struct ndis_resource), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
						sc->error = ENOMEM;
						goto out;
					}
					sc->ndis_res_mem->res_base = base;
					sc->ndis_res_mem->res_size = size;
					sc->ndis_res_mem->res_tag  = x86_bus_space_mem;
					
					if(bus_space_map(sc->ndis_res_mem->res_tag,
						sc->ndis_res_mem->res_base,
						sc->ndis_res_mem->res_size,
						flags|BUS_SPACE_MAP_LINEAR,
						&sc->ndis_res_mem->res_handle)) {
							printf("bus_space_map failed\n");
					}
				}
				break;
											   
			default:
				printf("unknown type\n");
			}
			prd->cprd_sharedisp = CmResourceShareDeviceExclusive;

			rl->cprl_count++;								
			prd++;
		}
	}
	
	/* add the interrupt to the list */
	prd->cprd_type 	= CmResourceTypeInterrupt;
	prd->cprd_flags = 0;
	/* TODO: is this all we need to save for the interrupt? */
	prd->u.cprd_intr.cprd_level = pa->pa_intrline;
	prd->u.cprd_intr.cprd_vector = pa->pa_intrline;
	prd->u.cprd_intr.cprd_affinity = 0;
	rl->cprl_count++;
	
	pci_intr_map(pa, &ih);
	sc->ndis_intrhand = pci_intr_establish(pa->pa_pc, ih, IPL_NET /*| PCATCH*/, ndis_intr, sc);
	sc->ndis_irq = (void *)sc->ndis_intrhand;
	
	printf("pci interrupt: %s\n", pci_intr_string(pa->pa_pc, ih));
	
	/* save resource list in the softc */
	sc->ndis_rl = rl;
	sc->ndis_rescnt = rl->cprl_count;
	
	kthread_create(PRI_NONE, 0, NULL, ndis_attach, (void *)sc,
	    NULL, "ndis_attach");
	return;
out:
	free(rl, M_DEVBUF); 
	return;
}
static void
ohci_pci_attach(device_t parent, device_t self, void *aux)
{
	struct ohci_pci_softc *sc = device_private(self);
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	pcitag_t tag = pa->pa_tag;
	char const *intrstr;
	pci_intr_handle_t ih;
	pcireg_t csr;
	char devinfo[256];
	usbd_status r;
	const char *vendor;
	const char *devname = device_xname(self);

	sc->sc.sc_dev = self;
	sc->sc.sc_bus.hci_private = sc;

	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
	printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class));

	/* Map I/O registers */
	if (pci_mapreg_map(pa, PCI_CBMEM, PCI_MAPREG_TYPE_MEM, 0,
			   &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size)) {
		printf("%s: can't map mem space\n", devname);
		return;
	}

	/* Disable interrupts, so we don't get any spurious ones. */
	bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE,
			  OHCI_ALL_INTRS);

	sc->sc_pc = pc;
	sc->sc_tag = tag;
	sc->sc.sc_bus.dmatag = pa->pa_dmat;

	/* Enable the device. */
	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
	pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
		       csr | PCI_COMMAND_MASTER_ENABLE);

	/* Map and establish the interrupt. */
	if (pci_intr_map(pa, &ih)) {
		printf("%s: couldn't map interrupt\n", devname);
		return;
	}
	intrstr = pci_intr_string(pc, ih);
	sc->sc_ih = pci_intr_establish(pc, ih, IPL_USB, ohci_intr, sc);
	if (sc->sc_ih == NULL) {
		printf("%s: couldn't establish interrupt", devname);
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		return;
	}
	printf("%s: interrupting at %s\n", devname, intrstr);

	/* Figure out vendor for root hub descriptor. */
	vendor = pci_findvendor(pa->pa_id);
	sc->sc.sc_id_vendor = PCI_VENDOR(pa->pa_id);
	if (vendor)
		strlcpy(sc->sc.sc_vendor, vendor, sizeof(sc->sc.sc_vendor));
	else
		snprintf(sc->sc.sc_vendor, sizeof(sc->sc.sc_vendor),
		    "vendor 0x%04x", PCI_VENDOR(pa->pa_id));

	r = ohci_init(&sc->sc);
	if (r != USBD_NORMAL_COMPLETION) {
		printf("%s: init failed, error=%d\n", devname, r);
		return;
	}

#if NEHCI > 0
	usb_pci_add(&sc->sc_pci, pa, self);
#endif

	if (!pmf_device_register1(self, ohci_suspend, ohci_resume,
	                          ohci_shutdown))
		aprint_error_dev(self, "couldn't establish power handler\n");

	/* Attach usb device. */
	sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint);
}
static void
ofbattach(device_t parent, device_t self, void *aux)
{
	struct ofb_softc *sc = device_private(self);
	struct pci_attach_args *pa = aux;
	struct wsemuldisplaydev_attach_args a;
	struct rasops_info *ri = &rascons_console_screen.scr_ri;
	long defattr;
	int console, node, sub;
	char devinfo[256];

	sc->sc_dev = self;

	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
	printf(": %s\n", devinfo);

	if (console_node == 0)
		return;

	node = pcidev_to_ofdev(pa->pa_pc, pa->pa_tag);
	console = (node == console_node);
	if (!console) {
		/* check if any of the childs matches */
		sub = OF_child(node);
		while ((sub != 0) && (sub != console_node)) {
			sub = OF_peer(sub);
		}
		if (sub == console_node) {
			console = true;
		}
	}
	
	sc->sc_memt = pa->pa_memt;
	sc->sc_iot = pa->pa_iot;	
	sc->sc_pc = pa->pa_pc;
	sc->sc_pcitag = pa->pa_tag;
	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;

	if (!console)
		return;
	
	vcons_init(&sc->vd, sc, &rascons_stdscreen, &ofb_accessops);
	sc->vd.init_screen = ofb_init_screen;

	sc->sc_node = console_node;

	sc->sc_ih = console_instance;
	vcons_init_screen(&sc->vd, &rascons_console_screen, 1, &defattr);
	rascons_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
	
	printf("%s: %d x %d, %dbpp\n", device_xname(self),
	       ri->ri_width, ri->ri_height, ri->ri_depth);
	
	sc->sc_fbaddr = 0;
	if (OF_getprop(sc->sc_node, "address", &sc->sc_fbaddr, 4) != 4)
		OF_interpret("frame-buffer-adr", 0, 1, &sc->sc_fbaddr);
	if (sc->sc_fbaddr == 0) {
		printf("%s: Unable to find the framebuffer address.\n",
		    device_xname(sc->sc_dev));
		return;
	}
	sc->sc_fbsize = round_page(ri->ri_stride * ri->ri_height);

	/* XXX */
	if (OF_getprop(sc->sc_node, "assigned-addresses", sc->sc_addrs,
	    sizeof(sc->sc_addrs)) == -1) {
		sc->sc_node = OF_parent(sc->sc_node);
		OF_getprop(sc->sc_node, "assigned-addresses", sc->sc_addrs,
		    sizeof(sc->sc_addrs));
	}

	ofb_init_cmap(sc);

	a.console = console;
	a.scrdata = &ofb_screenlist;
	a.accessops = &ofb_accessops;
	a.accesscookie = &sc->vd;

	config_found(self, &a, wsemuldisplaydevprint);

	config_found_ia(self, "drm", aux, ofb_drm_print);
}
Beispiel #18
0
void
uhci_pci_attach(struct device *parent, struct device *self, void *aux)
{
	struct uhci_pci_softc *sc = (struct uhci_pci_softc *)self;
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	pcitag_t tag = pa->pa_tag;
	char const *intrstr;
	pci_intr_handle_t ih;
	const char *vendor;
	char *devname = sc->sc.sc_bus.bdev.dv_xname;
	int s;

#if defined(__NetBSD__)
	char devinfo[256];

	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
	printf(": %s (rev. 0x%02x)", devinfo, PCI_REVISION(pa->pa_class));
#endif

	/* Map I/O registers */
	if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
		    &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size, 0)) {
		printf(": can't map i/o space\n");
		return;
	}


	/* Disable interrupts, so we don't get any spurious ones. */
	s = splhardusb();
	bus_space_write_2(sc->sc.iot, sc->sc.ioh, UHCI_INTR, 0);

	sc->sc_pc = pc;
	sc->sc_tag = tag;
	sc->sc.sc_bus.dmatag = pa->pa_dmat;

	/* Map and establish the interrupt. */
	if (pci_intr_map(pa, &ih)) {
		printf(": couldn't map interrupt\n");
		goto unmap_ret;
	}
	intrstr = pci_intr_string(pc, ih);
	sc->sc_ih = pci_intr_establish(pc, ih, IPL_USB, uhci_intr, sc,
				       devname);
	if (sc->sc_ih == NULL) {
		printf(": couldn't establish interrupt");
		if (intrstr != NULL)
			printf(" at %s", intrstr);
		printf("\n");
		goto unmap_ret;
	}
	printf(": %s\n", intrstr);

	/* Set LEGSUP register to its default value. */
	pci_conf_write(pc, tag, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN);

	switch(pci_conf_read(pc, tag, PCI_USBREV) & PCI_USBREV_MASK) {
	case PCI_USBREV_PRE_1_0:
		sc->sc.sc_bus.usbrev = USBREV_PRE_1_0;
		break;
	case PCI_USBREV_1_0:
		sc->sc.sc_bus.usbrev = USBREV_1_0;
		break;
	case PCI_USBREV_1_1:
		sc->sc.sc_bus.usbrev = USBREV_1_1;
		break;
	default:
		sc->sc.sc_bus.usbrev = USBREV_UNKNOWN;
		break;
	}

	uhci_run(&sc->sc, 0);			/* stop the controller */
						/* disable interrupts */
	bus_space_barrier(sc->sc.iot, sc->sc.ioh, 0, sc->sc.sc_size,
	    BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
	bus_space_write_2(sc->sc.iot, sc->sc.ioh, UHCI_INTR, 0);

	/* Figure out vendor for root hub descriptor. */
	vendor = pci_findvendor(pa->pa_id);
	sc->sc.sc_id_vendor = PCI_VENDOR(pa->pa_id);
	if (vendor)
		strlcpy(sc->sc.sc_vendor, vendor, sizeof (sc->sc.sc_vendor));
	else
		snprintf(sc->sc.sc_vendor, sizeof (sc->sc.sc_vendor),
			"vendor 0x%04x", PCI_VENDOR(pa->pa_id));

	config_defer(self, uhci_pci_attach_deferred);
	
	/* Ignore interrupts for now */
	sc->sc.sc_dying = 1;

	splx(s);

	return;

unmap_ret:
	bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
	splx(s);
}
Beispiel #19
0
static void
siisata_pci_attach(device_t parent, device_t self, void *aux)
{
    struct pci_attach_args *pa = aux;
    struct siisata_pci_softc *psc = device_private(self);
    struct siisata_softc *sc = &psc->si_sc;
    char devinfo[256];
    const char *intrstr;
    pci_intr_handle_t intrhandle;
    pcireg_t csr, memtype;
    const struct siisata_pci_product *spp;
    void *ih;
    bus_space_tag_t memt;
    bus_space_handle_t memh;
    uint32_t gcreg;
    int memh_valid;
    bus_size_t grsize, prsize;

    sc->sc_atac.atac_dev = self;

    psc->sc_pc = pa->pa_pc;
    psc->sc_pcitag = pa->pa_tag;

    pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo));
    aprint_naive(": SATA-II HBA\n");
    aprint_normal(": %s\n", devinfo);

    /* map bar0 */
#if 1
    memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SIISATA_PCI_BAR0);
#else
    memtype = PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
#endif
    switch (memtype) {
    case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
    case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
        memh_valid = (pci_mapreg_map(pa, SIISATA_PCI_BAR0,
                                     memtype, 0, &memt, &memh, NULL, &grsize) == 0);
        break;
    default:
        memh_valid = 0;
    }
    if (memh_valid) {
        sc->sc_grt = memt;
        sc->sc_grh = memh;
    } else {
        aprint_error("%s: unable to map device global registers\n",
                     SIISATANAME(sc));
        return;
    }

    /* map bar1 */
#if 1
    memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SIISATA_PCI_BAR1);
#else
    memtype = PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
#endif
    switch (memtype) {
    case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
    case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
        memh_valid = (pci_mapreg_map(pa, SIISATA_PCI_BAR1,
                                     memtype, 0, &memt, &memh, NULL, &prsize) == 0);
        break;
    default:
        memh_valid = 0;
    }
    if (memh_valid) {
        sc->sc_prt = memt;
        sc->sc_prh = memh;
    } else {
        bus_space_unmap(sc->sc_grt, sc->sc_grh, grsize);
        aprint_error("%s: unable to map device port registers\n",
                     SIISATANAME(sc));
        return;
    }

    if (pci_dma64_available(pa)) {
        sc->sc_dmat = pa->pa_dmat64;
        sc->sc_have_dma64 = 1;
        aprint_debug("64-bit PCI DMA available\n");
    } else {
        sc->sc_dmat = pa->pa_dmat;
        sc->sc_have_dma64 = 0;
    }

    /* map interrupt */
    if (pci_intr_map(pa, &intrhandle) != 0) {
        bus_space_unmap(sc->sc_grt, sc->sc_grh, grsize);
        bus_space_unmap(sc->sc_prt, sc->sc_prh, prsize);
        aprint_error("%s: couldn't map interrupt\n", SIISATANAME(sc));
        return;
    }
    intrstr = pci_intr_string(pa->pa_pc, intrhandle);
    ih = pci_intr_establish(pa->pa_pc, intrhandle,
                            IPL_BIO, siisata_intr, sc);
    if (ih == NULL) {
        bus_space_unmap(sc->sc_grt, sc->sc_grh, grsize);
        bus_space_unmap(sc->sc_prt, sc->sc_prh, prsize);
        aprint_error("%s: couldn't establish interrupt"
                     "at %s\n", SIISATANAME(sc), intrstr);
        return;
    }
    aprint_normal("%s: interrupting at %s\n", SIISATANAME(sc),
                  intrstr ? intrstr : "unknown interrupt");

    /* fill in number of ports on this device */
    spp = siisata_pci_lookup(pa);
    if (spp != NULL) {
        sc->sc_atac.atac_nchannels = spp->spp_ports;
        sc->sc_chip = spp->spp_chip;
    } else
        /* _match() should prevent us from getting here */
        panic("siisata: the universe might be falling apart!\n");

    gcreg = GRREAD(sc, GR_GC);

    aprint_normal("%s: SiI%d on ", SIISATANAME(sc), sc->sc_chip);
    if (sc->sc_chip == 3124) {
        aprint_normal("%d-bit, ", (gcreg & GR_GC_REQ64) ? 64 : 32);
        switch (gcreg & (GR_GC_DEVSEL | GR_GC_STOP | GR_GC_TRDY)) {
        case 0:
            aprint_normal("%d", (gcreg & GR_GC_M66EN) ? 66 : 33);
            break;
        case GR_GC_TRDY:
            aprint_normal("%d", 66);
            break;
        case GR_GC_STOP:
            aprint_normal("%d", 100);
            break;
        case GR_GC_STOP | GR_GC_TRDY:
            aprint_normal("%d", 133);
            break;
        default:
            break;
        }
        aprint_normal("MHz PCI%s bus.", (gcreg & (GR_GC_DEVSEL | GR_GC_STOP | GR_GC_TRDY)) ? "-X" : "");
    } else {
        /* XXX - but only x1 devices so far */
        aprint_normal("PCI-Express x1 port.");
    }
    if (gcreg & GR_GC_3GBPS)
        aprint_normal(" 3.0Gb/s capable.\n");
    else
        aprint_normal("\n");

    /* enable bus mastering in case the firmware didn't */
    csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
    csr |= PCI_COMMAND_MASTER_ENABLE;
    csr |= PCI_COMMAND_MEM_ENABLE;
    pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, csr);

    siisata_attach(sc);

    if (!pmf_device_register(self, NULL, siisata_pci_resume))
        aprint_error_dev(self, "couldn't establish power handler\n");
}
static void
piixpm_attach(device_t parent, device_t self, void *aux)
{
	struct piixpm_softc *sc = device_private(self);
	struct pci_attach_args *pa = aux;
	struct i2cbus_attach_args iba;
	pcireg_t base, conf;
	pcireg_t pmmisc;
	pci_intr_handle_t ih;
	char devinfo[256];
	const char *intrstr = NULL;

	sc->sc_dev = self;
	sc->sc_pc = pa->pa_pc;
	sc->sc_pcitag = pa->pa_tag;

	aprint_naive("\n");
	aprint_normal("\n");

	pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
	aprint_normal_dev(self, "%s (rev. 0x%02x)\n", devinfo,
	    PCI_REVISION(pa->pa_class));

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

	/* Read configuration */
	conf = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_HOSTC);
	DPRINTF(("%s: conf 0x%x\n", device_xname(self), conf));

	if ((PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) ||
	    (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_82371AB_PMC))
		goto nopowermanagement;

	/* check whether I/O access to PM regs is enabled */
	pmmisc = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_PMREGMISC);
	if (!(pmmisc & 1))
		goto nopowermanagement;

	sc->sc_pm_iot = pa->pa_iot;
	/* Map I/O space */
	base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_PM_BASE);
	if (bus_space_map(sc->sc_pm_iot, PCI_MAPREG_IO_ADDR(base),
	    PIIX_PM_SIZE, 0, &sc->sc_pm_ioh)) {
		aprint_error_dev(self, "can't map power management I/O space\n");
		goto nopowermanagement;
	}

	/*
	 * Revision 0 and 1 are PIIX4, 2 is PIIX4E, 3 is PIIX4M.
	 * PIIX4 and PIIX4E have a bug in the timer latch, see Errata #20
	 * in the "Specification update" (document #297738).
	 */
	acpipmtimer_attach(self, sc->sc_pm_iot, sc->sc_pm_ioh,
			   PIIX_PM_PMTMR,
		(PCI_REVISION(pa->pa_class) < 3) ? ACPIPMT_BADLATCH : 0 );

nopowermanagement:
	if ((conf & PIIX_SMB_HOSTC_HSTEN) == 0) {
		aprint_normal_dev(self, "SMBus disabled\n");
		return;
	}

	/* Map I/O space */
	sc->sc_smb_iot = pa->pa_iot;
	base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_BASE) & 0xffff;
	if (bus_space_map(sc->sc_smb_iot, PCI_MAPREG_IO_ADDR(base),
	    PIIX_SMB_SIZE, 0, &sc->sc_smb_ioh)) {
		aprint_error_dev(self, "can't map smbus I/O space\n");
		return;
	}

	sc->sc_poll = 1;
	if ((conf & PIIX_SMB_HOSTC_INTMASK) == PIIX_SMB_HOSTC_SMI) {
		/* No PCI IRQ */
		aprint_normal_dev(self, "interrupting at SMI");
	} else if ((conf & PIIX_SMB_HOSTC_INTMASK) == PIIX_SMB_HOSTC_IRQ) {
		/* Install interrupt handler */
		if (pci_intr_map(pa, &ih) == 0) {
			intrstr = pci_intr_string(pa->pa_pc, ih);
			sc->sc_smb_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
			    piixpm_intr, sc);
			if (sc->sc_smb_ih != NULL) {
				aprint_normal_dev(self, "interrupting at %s",
				    intrstr);
				sc->sc_poll = 0;
			}
		}
	}
	if (sc->sc_poll)
		aprint_normal_dev(self, "polling");

	aprint_normal("\n");

	/* Attach I2C bus */
	rw_init(&sc->sc_i2c_rwlock);
	sc->sc_i2c_tag.ic_cookie = sc;
	sc->sc_i2c_tag.ic_acquire_bus = piixpm_i2c_acquire_bus;
	sc->sc_i2c_tag.ic_release_bus = piixpm_i2c_release_bus;
	sc->sc_i2c_tag.ic_exec = piixpm_i2c_exec;

	bzero(&iba, sizeof(iba));
	iba.iba_tag = &sc->sc_i2c_tag;
	config_found_ia(self, "i2cbus", &iba, iicbus_print);

	return;
}