code:
/*	$OpenBSD: if_dc_cardbus.c,v 1.38 2015/05/04 03:59:42 jsg Exp $	*/

/*
 * Copyright (c) 1997, 1998, 1999
 *	Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by Bill Paul.
 * 4. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: src/sys/pci/if_dc.c,v 1.5 2000/01/12 22:24:05 wpaul Exp $
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/device.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_media.h>

#include <netinet/in.h>
#include <netinet/if_ether.h>

#include <dev/mii/miivar.h>

#include <machine/bus.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

#include <dev/cardbus/cardbusvar.h>

#include <dev/ic/dcreg.h>

/* PCI configuration regs */
#define	PCI_CBIO	0x10
#define	PCI_CBMEM	0x14
#define	PCI_CFDA	0x40

#define	DC_CFDA_SUSPEND	0x80000000
#define	DC_CFDA_STANDBY	0x40000000

struct dc_cardbus_softc {
	struct dc_softc		sc_dc;
	int			sc_intrline;

	cardbus_devfunc_t	sc_ct;
	pci_chipset_tag_t	sc_pc;
	pcitag_t		sc_tag;
	bus_size_t		sc_mapsize;
	int			sc_actype;
};

int dc_cardbus_match(struct device *, void *, void *);
void dc_cardbus_attach(struct device *, struct device *,void *);
int dc_cardbus_detach(struct device *, int);

void dc_cardbus_setup(struct dc_cardbus_softc *csc);

struct cfattach dc_cardbus_ca = {
	sizeof(struct dc_cardbus_softc), dc_cardbus_match, dc_cardbus_attach,
	dc_cardbus_detach, dc_activate
};

const struct pci_matchid dc_cardbus_devices[] = {
	{ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142 },
	{ PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_X3201_3_21143 },
	{ PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AN985 },
	{ PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN2242 },
	{ PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2500 },
	{ PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2500MX },
	{ PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_PCM200 },
	{ PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DRP32TXD },
	{ PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_PCMPC200 },
	{ PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_PCM200 },
	{ PCI_VENDOR_HAWKING, PCI_PRODUCT_HAWKING_PN672TX },
	{ PCI_VENDOR_MICROSOFT, PCI_PRODUCT_MICROSOFT_MN120 },
};

int
dc_cardbus_match(struct device *parent, void *match, void *aux)
{
	return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
	    dc_cardbus_devices, nitems(dc_cardbus_devices)));
}

void
dc_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct dc_cardbus_softc *csc = (struct dc_cardbus_softc *)self;
	struct dc_softc *sc = &csc->sc_dc;
	struct cardbus_attach_args *ca = aux;
	struct cardbus_devfunc *ct = ca->ca_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	pci_chipset_tag_t pc = ca->ca_pc;
	cardbus_function_tag_t cf = ct->ct_cf;
	pcireg_t reg;
	bus_addr_t addr;

	sc->sc_dmat = ca->ca_dmat;
	csc->sc_ct = ct;
	csc->sc_tag = ca->ca_tag;
	csc->sc_pc = ca->ca_pc;

	Cardbus_function_enable(ct);

	if (Cardbus_mapreg_map(ct, PCI_CBIO,
	    PCI_MAPREG_TYPE_IO, 0, &sc->dc_btag, &sc->dc_bhandle, &addr,
	    &csc->sc_mapsize) == 0) {

		csc->sc_actype = CARDBUS_IO_ENABLE;
	} else if (Cardbus_mapreg_map(ct, PCI_CBMEM,
	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &sc->dc_btag, &sc->dc_bhandle, &addr, &csc->sc_mapsize) == 0) {
		csc->sc_actype = CARDBUS_MEM_ENABLE;
	} else {
		printf(": can't map device registers\n");
		return;
	}

	csc->sc_intrline = ca->ca_intrline;

	sc->dc_cachesize = pci_conf_read(csc->sc_pc, ca->ca_tag, DC_PCI_CFLT)
	    & 0xFF;

	dc_cardbus_setup(csc);

	/* Get the eeprom width */
	if ((PCI_VENDOR(ca->ca_id) == PCI_VENDOR_XIRCOM &&
	      PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_XIRCOM_X3201_3_21143))
		;	/* XIRCOM has non-standard eeprom */
	else
		dc_eeprom_width(sc);

	switch (PCI_VENDOR(ca->ca_id)) {
	case PCI_VENDOR_DEC:
		if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_DEC_21142) {
			sc->dc_type = DC_TYPE_21143;
			sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
			sc->dc_flags |= DC_REDUCED_MII_POLL;
			dc_read_srom(sc, sc->dc_romwidth);
			dc_parse_21143_srom(sc);
		}
		break;
	case PCI_VENDOR_XIRCOM:
		if (PCI_PRODUCT(ca->ca_id) ==
		    PCI_PRODUCT_XIRCOM_X3201_3_21143) {
			sc->dc_type = DC_TYPE_XIRCOM;
			sc->dc_flags |= DC_TX_INTR_ALWAYS|DC_TX_COALESCE |
					DC_TX_ALIGN;
			sc->dc_pmode = DC_PMODE_MII;
		}
		break;
	case PCI_VENDOR_ADMTEK:
	case PCI_VENDOR_ACCTON:
	case PCI_VENDOR_ABOCOM:
	case PCI_VENDOR_DLINK:
	case PCI_VENDOR_LINKSYS:
	case PCI_VENDOR_HAWKING:
	case PCI_VENDOR_MICROSOFT:
		if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ADMTEK_AN985 ||
		    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ACCTON_EN2242 ||
		    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ABOCOM_FE2500 ||
		    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ABOCOM_FE2500MX ||
		    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ABOCOM_PCM200 ||
		    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_DLINK_DRP32TXD ||
		    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_LINKSYS_PCMPC200 ||
		    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_LINKSYS_PCM200 ||
		    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_HAWKING_PN672TX ||
		    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_MICROSOFT_MN120) {
			sc->dc_type = DC_TYPE_AN983;
			sc->dc_flags |= DC_TX_USE_TX_INTR|DC_TX_ADMTEK_WAR |
					DC_64BIT_HASH;
			sc->dc_pmode = DC_PMODE_MII;
			/* Don't read SROM for - auto-loaded on reset */
		}
		break;
	default:
		printf(": unknown device\n");
		return;
	}

 	/*
	 * set latency timer, do we really need this?
	 */
	reg = pci_conf_read(pc, ca->ca_tag, PCI_BHLC_REG);
	if (PCI_LATTIMER(reg) < 0x20) {
		reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
		reg |= (0x20 << PCI_LATTIMER_SHIFT);
		pci_conf_write(pc, ca->ca_tag, PCI_BHLC_REG, reg);
	}

	sc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline, IPL_NET,
	    dc_intr, csc, sc->sc_dev.dv_xname);
	if (sc->sc_ih == NULL) {
		printf(": can't establish interrupt at %d\n",
		    ca->ca_intrline);
		return;
	}
	printf(": irq %d", ca->ca_intrline);

	dc_reset(sc);

	sc->dc_revision = PCI_REVISION(ca->ca_class);
	dc_attach(sc);
}

int
dc_cardbus_detach(struct device *self, int flags)
{
	struct dc_cardbus_softc *csc = (struct dc_cardbus_softc *)self;
	struct dc_softc *sc = &csc->sc_dc;
	struct cardbus_devfunc *ct = csc->sc_ct;

	cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, sc->sc_ih);
	dc_detach(sc);

	/* unmap cardbus resources */
	Cardbus_mapreg_unmap(ct,
	    csc->sc_actype == CARDBUS_IO_ENABLE ? PCI_CBIO : PCI_CBMEM,
	    sc->dc_btag, sc->dc_bhandle, csc->sc_mapsize);

	return (0);
}

void
dc_cardbus_setup(struct dc_cardbus_softc *csc)
{
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	pci_chipset_tag_t pc = csc->sc_pc;
	pcireg_t reg;
	int r;

	/* wakeup the card if needed */
	reg = pci_conf_read(pc, csc->sc_tag, PCI_CFDA);
	if (reg & (DC_CFDA_SUSPEND|DC_CFDA_STANDBY)) {
		pci_conf_write(pc, csc->sc_tag, PCI_CFDA,
		    reg & ~(DC_CFDA_SUSPEND|DC_CFDA_STANDBY));
	}

	if (pci_get_capability(csc->sc_pc, csc->sc_tag, PCI_CAP_PWRMGMT, &r,
	    0)) {
		r = pci_conf_read(csc->sc_pc, csc->sc_tag, r + 4) & 3;
		if (r) {
			printf("%s: awakening from state D%d\n",
			    csc->sc_dc.sc_dev.dv_xname, r);
			pci_conf_write(csc->sc_pc, csc->sc_tag, r + 4, 0);
		}
	}

	(*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_actype);
	(*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);

	reg = pci_conf_read(csc->sc_pc, csc->sc_tag, PCI_COMMAND_STATUS_REG);
	reg |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
	    PCI_COMMAND_MASTER_ENABLE;
	pci_conf_write(csc->sc_pc, csc->sc_tag, PCI_COMMAND_STATUS_REG, reg);
	reg = pci_conf_read(csc->sc_pc, csc->sc_tag, PCI_COMMAND_STATUS_REG);
}


code:
/*	$OpenBSD: if_fxp_cardbus.c,v 1.34 2014/12/19 22:44:58 guenther Exp $ */
/*	$NetBSD: if_fxp_cardbus.c,v 1.12 2000/05/08 18:23:36 thorpej Exp $	*/

/*
 * Copyright (c) 1999 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Johan Danielsson.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * CardBus front-end for the Intel i8255x family of Ethernet chips.
 */

#include "bpfilter.h"

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/timeout.h>
#include <sys/device.h>
#include <sys/endian.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_media.h>

#if NBPFILTER > 0
#include <net/bpf.h>
#endif

#include <netinet/in.h>
#include <netinet/if_ether.h>

#include <machine/bus.h>
#include <machine/intr.h>

#include <dev/mii/miivar.h>

#include <dev/ic/fxpreg.h>
#include <dev/ic/fxpvar.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

#include <dev/cardbus/cardbusvar.h>

int fxp_cardbus_match(struct device *, void *, void *);
void fxp_cardbus_attach(struct device *, struct device *, void *);
int fxp_cardbus_detach(struct device *, int);
void fxp_cardbus_setup(struct fxp_softc *);

struct fxp_cardbus_softc {
	struct fxp_softc sc;
	cardbus_devfunc_t ct;
	pcitag_t ct_tag;
	pcireg_t base0_reg;
	pcireg_t base1_reg;
	bus_size_t size;
	pci_chipset_tag_t pc;
};

struct cfattach fxp_cardbus_ca = {
	sizeof(struct fxp_cardbus_softc), fxp_cardbus_match, fxp_cardbus_attach,
	    fxp_cardbus_detach
};

const struct pci_matchid fxp_cardbus_devices[] = {
	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_8255x },
};

#ifdef CBB_DEBUG
#define DPRINTF(X) printf X
#else
#define DPRINTF(X)
#endif

int
fxp_cardbus_match(struct device *parent, void *match, void *aux)
{
	return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
	    fxp_cardbus_devices, nitems(fxp_cardbus_devices)));
}

void
fxp_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
	char intrstr[16];
	struct fxp_softc *sc = (struct fxp_softc *) self;
	struct fxp_cardbus_softc *csc = (struct fxp_cardbus_softc *) self;
	struct cardbus_attach_args *ca = aux;
	struct cardbus_softc *psc =
	    (struct cardbus_softc *)sc->sc_dev.dv_parent;
	cardbus_chipset_tag_t cc = psc->sc_cc;
	cardbus_function_tag_t cf = psc->sc_cf;
	bus_space_tag_t iot, memt;
	bus_space_handle_t ioh, memh;

	bus_addr_t adr;
	bus_size_t size;

	csc->ct = ca->ca_ct;
	csc->pc = ca->ca_pc;

	/*
	 * Map control/status registers.
	 */
	if (Cardbus_mapreg_map(csc->ct, CARDBUS_BASE1_REG,
	    PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, &adr, &size) == 0) {
		csc->base1_reg = adr | 1;
		sc->sc_st = iot;
		sc->sc_sh = ioh;
		csc->size = size;
	} else if (Cardbus_mapreg_map(csc->ct, CARDBUS_BASE0_REG,
	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
	    0, &memt, &memh, &adr, &size) == 0) {
		csc->base0_reg = adr;
		sc->sc_st = memt;
		sc->sc_sh = memh;
		csc->size = size;
	} else
		panic("%s: failed to allocate mem and io space", __func__);

	sc->sc_dmat = ca->ca_dmat;
#if 0
	sc->sc_enable = fxp_cardbus_enable;
	sc->sc_disable = fxp_cardbus_disable;
	sc->sc_enabled = 0;
#endif

	Cardbus_function_enable(csc->ct);

	fxp_cardbus_setup(sc);

	/* Map and establish the interrupt. */
	sc->sc_ih = cardbus_intr_establish(cc, cf, psc->sc_intrline, IPL_NET,
	    fxp_intr, sc, sc->sc_dev.dv_xname);
	if (NULL == sc->sc_ih) {
		printf(": couldn't establish interrupt");
		printf("at %d\n", ca->ca_intrline);
		return;
	}
	snprintf(intrstr, sizeof(intrstr), "irq %d", ca->ca_intrline);

	sc->sc_revision = PCI_REVISION(ca->ca_class);

	fxp_attach(sc, intrstr);
}

void
fxp_cardbus_setup(struct fxp_softc *sc)
{
	struct fxp_cardbus_softc *csc = (struct fxp_cardbus_softc *) sc;
	struct cardbus_softc *psc =
	    (struct cardbus_softc *) sc->sc_dev.dv_parent;
	cardbus_chipset_tag_t cc = psc->sc_cc;
	pci_chipset_tag_t pc = csc->pc;
	cardbus_function_tag_t cf = psc->sc_cf;
	pcireg_t command;

	csc->ct_tag = pci_make_tag(pc, csc->ct->ct_bus,
	    csc->ct->ct_dev, csc->ct->ct_func);

	command = pci_conf_read(pc, csc->ct_tag, PCI_COMMAND_STATUS_REG);
	if (csc->base0_reg) {
		pci_conf_write(pc, csc->ct_tag, CARDBUS_BASE0_REG, csc->base0_reg);
		(cf->cardbus_ctrl) (cc, CARDBUS_MEM_ENABLE);
		command |= PCI_COMMAND_MEM_ENABLE |
		    PCI_COMMAND_MASTER_ENABLE;
	} else if (csc->base1_reg) {
		pci_conf_write(pc, csc->ct_tag, CARDBUS_BASE1_REG, csc->base1_reg);
		(cf->cardbus_ctrl) (cc, CARDBUS_IO_ENABLE);
		command |= (PCI_COMMAND_IO_ENABLE |
		    PCI_COMMAND_MASTER_ENABLE);
	}

	(cf->cardbus_ctrl) (cc, CARDBUS_BM_ENABLE);

	/* enable the card */
	pci_conf_write(pc, csc->ct_tag, PCI_COMMAND_STATUS_REG, command);
}

int
fxp_cardbus_detach(struct device *self, int flags)
{
	struct fxp_softc *sc = (struct fxp_softc *) self;
	struct fxp_cardbus_softc *csc = (struct fxp_cardbus_softc *) self;
	struct cardbus_devfunc *ct = csc->ct;
	int reg;

	cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, sc->sc_ih);
	fxp_detach(sc);

	if (csc->base0_reg)
		reg = CARDBUS_BASE0_REG;
	else
		reg = CARDBUS_BASE1_REG;
	Cardbus_mapreg_unmap(ct, reg, sc->sc_st, sc->sc_sh, csc->size);
	return (0);
}

license: unknown


code:
/*	$OpenBSD: if_malo_cardbus.c,v 1.12 2013/12/06 21:03:02 deraadt Exp $ */

/*
 * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "bpfilter.h"

#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/timeout.h>

#include <net/if.h>
#include <net/if_media.h>

#include <netinet/in.h>
#include <netinet/if_ether.h>

#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>

#include <dev/cardbus/cardbusvar.h>

#include <dev/ic/malo.h>

struct malo_cardbus_softc {
	struct malo_softc	sc_malo;

	/* cardbus specific goo */
	cardbus_devfunc_t	sc_ct;
	pcitag_t		sc_tag;
	void			*sc_ih;

	bus_size_t		sc_mapsize1;
	bus_size_t		sc_mapsize2;
	pcireg_t		sc_bar1_val;
	pcireg_t		sc_bar2_val;
	int			sc_intrline;
	pci_chipset_tag_t	sc_pc;
};

int	malo_cardbus_match(struct device *parent, void *match, void *aux);
void	malo_cardbus_attach(struct device *parent, struct device *self,
	    void *aux);
int	malo_cardbus_detach(struct device *self, int flags);
void	malo_cardbus_setup(struct malo_cardbus_softc *csc);
int	malo_cardbus_enable(struct malo_softc *sc);
void	malo_cardbus_disable(struct malo_softc *sc);

struct cfattach malo_cardbus_ca = {
	sizeof (struct malo_cardbus_softc), malo_cardbus_match,
	malo_cardbus_attach, malo_cardbus_detach
};

static const struct pci_matchid malo_cardbus_devices[] = {
	{ PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_88W8310 },
	{ PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_88W8335_1 },
	{ PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_88W8335_2 }
};

int
malo_cardbus_match(struct device *parent, void *match, void *aux)
{
	return (cardbus_matchbyid(aux, malo_cardbus_devices,
	    sizeof (malo_cardbus_devices) / sizeof (malo_cardbus_devices[0])));
}

void
malo_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)self;
	struct cardbus_attach_args *ca = aux;
	struct malo_softc *sc = &csc->sc_malo;
	cardbus_devfunc_t ct = ca->ca_ct;
	bus_addr_t base;
	int error;

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

	/* power management hooks */
	sc->sc_enable = malo_cardbus_enable;
	sc->sc_disable = malo_cardbus_disable;
#if 0
	sc->sc_power = malo_cardbus_power;
#endif

	/* map control/status registers */
	error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
	    PCI_MAPREG_TYPE_MEM, 0, &sc->sc_mem1_bt,
	    &sc->sc_mem1_bh, &base, &csc->sc_mapsize1);
	if (error != 0) {
		printf(": can't map mem1 space\n");
		return;
	}
	csc->sc_bar1_val = base | PCI_MAPREG_TYPE_MEM;

	/* map control/status registers */
	error = Cardbus_mapreg_map(ct, CARDBUS_BASE1_REG,
	    PCI_MAPREG_TYPE_MEM, 0, &sc->sc_mem2_bt,
	    &sc->sc_mem2_bh, &base, &csc->sc_mapsize2);
	if (error != 0) {
		printf(": can't map mem2 space\n");
		Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_mem1_bt,
		    sc->sc_mem1_bh, csc->sc_mapsize1);
		return;
	}
	csc->sc_bar2_val = base | PCI_MAPREG_TYPE_MEM;

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

	printf(": irq %d", csc->sc_intrline);

	error = malo_attach(sc);
	if (error != 0)
		malo_cardbus_detach(&sc->sc_dev, 0);

	Cardbus_function_disable(ct);
}

int
malo_cardbus_detach(struct device *self, int flags)
{
	struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)self;
	struct malo_softc *sc = &csc->sc_malo;
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;
	int error;

	error = malo_detach(sc);
	if (error != 0)
		return (error);

	/* unhook the interrupt handler */
	if (csc->sc_ih != NULL) {
		cardbus_intr_disestablish(cc, cf, csc->sc_ih);
		csc->sc_ih = NULL;
	}

	/* release bus space and close window */
	Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_mem1_bt,
	    sc->sc_mem1_bh, csc->sc_mapsize1);
	Cardbus_mapreg_unmap(ct, CARDBUS_BASE1_REG, sc->sc_mem2_bt,
	    sc->sc_mem2_bh, csc->sc_mapsize2);

	return (0);
}

void
malo_cardbus_setup(struct malo_cardbus_softc *csc)
{
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	pci_chipset_tag_t pc = csc->sc_pc;
	cardbus_function_tag_t cf = ct->ct_cf;
	pcireg_t reg;

	/* program the BAR */
	pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE0_REG,
	    csc->sc_bar1_val);
	pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE1_REG,
	    csc->sc_bar2_val);

	/* make sure the right access type is on the cardbus bridge */
	(*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
	(*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);

	/* enable the appropriate bits in the PCI CSR */
	reg = pci_conf_read(pc, csc->sc_tag,
	    PCI_COMMAND_STATUS_REG);
	reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE;
	pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
	    reg);
}

int
malo_cardbus_enable(struct malo_softc *sc)
{
	struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)sc;
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;

	/* power on the socket */
	Cardbus_function_enable(ct);

	/* setup the PCI configuration registers */
	malo_cardbus_setup(csc);

	/* map and establish the interrupt handler */
	csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
	    malo_intr, sc, sc->sc_dev.dv_xname);
	if (csc->sc_ih == NULL) {
		printf("%s: could not establish interrupt at %d\n",
		    sc->sc_dev.dv_xname, csc->sc_intrline);
		Cardbus_function_disable(ct);
		return (1);
	}

	return (0);
}

void
malo_cardbus_disable(struct malo_softc *sc)
{
	struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)sc;
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;

	/* unhook the interrupt handler */
	cardbus_intr_disestablish(cc, cf, csc->sc_ih);
	csc->sc_ih = NULL;

	/* power down the socket */
	Cardbus_function_disable(ct);
}


code:
/*	$OpenBSD: if_pgt_cardbus.c,v 1.16 2015/03/14 03:38:47 jsg Exp $ */

/*
 * Copyright (c) 2006 Marcus Glocker <mglocker@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * CardBus front-end for the PrismGT
 */

#include "bpfilter.h"

#include <sys/param.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/timeout.h>
#include <sys/device.h>

#include <machine/bus.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>

#include <netinet/in.h>
#include <netinet/if_ether.h>

#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>

#include <dev/ic/pgtreg.h>
#include <dev/ic/pgtvar.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>

#include <dev/cardbus/cardbusvar.h>

struct pgt_cardbus_softc {
	struct pgt_softc	 sc_pgt;
	cardbus_devfunc_t	 sc_ct;
	pcitag_t		 sc_tag;
	int			 sc_intrline;

	void			*sc_ih;
	bus_size_t		 sc_mapsize;
	pcireg_t		 sc_bar0_val;
	pci_chipset_tag_t	 sc_pc;
};

int	pgt_cardbus_match(struct device *, void *, void *);
void	pgt_cardbus_attach(struct device *, struct device *, void *);
int	pgt_cardbus_detach(struct device *, int);
int	pgt_cardbus_enable(struct pgt_softc *);
void	pgt_cardbus_disable(struct pgt_softc *);
void	pgt_cardbus_power(struct pgt_softc *, int);
void	pgt_cardbus_setup(struct pgt_cardbus_softc *);

struct cfattach pgt_cardbus_ca = {
	sizeof(struct pgt_cardbus_softc), pgt_cardbus_match, pgt_cardbus_attach,
	pgt_cardbus_detach
};

const struct pci_matchid pgt_cardbus_devices[] = {
	{ PCI_VENDOR_INTERSIL, PCI_PRODUCT_INTERSIL_ISL3877 },
	{ PCI_VENDOR_INTERSIL, PCI_PRODUCT_INTERSIL_ISL3890 },
	{ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRWE154G72 }
};

int
pgt_cardbus_match(struct device *parent, void *match, void *aux)
{
	return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
	    pgt_cardbus_devices,
	    sizeof(pgt_cardbus_devices) / sizeof(pgt_cardbus_devices[0])));
}

void
pgt_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)self;
	struct pgt_softc *sc = &csc->sc_pgt;
	struct cardbus_attach_args *ca = aux;
	cardbus_devfunc_t ct = ca->ca_ct;
	bus_addr_t base;
	int error;

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

	/* power management hooks */
	sc->sc_enable = pgt_cardbus_enable;
	sc->sc_disable = pgt_cardbus_disable;
	sc->sc_power = pgt_cardbus_power;

	/* remember chipset */
	if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_INTERSIL_ISL3877)
		sc->sc_flags |= SC_ISL3877;

	/* map control / status registers */
	error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
	    &sc->sc_iotag, &sc->sc_iohandle, &base, &csc->sc_mapsize);
	if (error != 0) {
		printf(": can't map mem space\n");
		return;
	}
	csc->sc_bar0_val = base | PCI_MAPREG_TYPE_MEM;

	/* disable all interrupts */
	bus_space_write_4(sc->sc_iotag, sc->sc_iohandle, PGT_REG_INT_EN, 0);
	(void)bus_space_read_4(sc->sc_iotag, sc->sc_iohandle, PGT_REG_INT_EN);
	DELAY(PGT_WRITEIO_DELAY);

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

	printf(": irq %d\n", csc->sc_intrline);

	if (rootvp == NULL)
		mountroothook_establish(pgt_attach, sc);
	else
		pgt_attach(sc);
}

int
pgt_cardbus_detach(struct device *self, int flags)
{
	struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)self;
	struct pgt_softc *sc = &csc->sc_pgt;
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;
	int error;

	error = pgt_detach(sc);
	if (error != 0)
		return (error);

	/* unhook the interrupt handler */
	if (csc->sc_ih != NULL) {
		cardbus_intr_disestablish(cc, cf, csc->sc_ih);
		csc->sc_ih = NULL;
	}

	/* release bus space and close window */
	Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG,
	    sc->sc_iotag, sc->sc_iohandle, csc->sc_mapsize);

	return (0);
}

int
pgt_cardbus_enable(struct pgt_softc *sc)
{
        struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)sc;
        cardbus_devfunc_t ct = csc->sc_ct;
        cardbus_chipset_tag_t cc = ct->ct_cc;
        cardbus_function_tag_t cf = ct->ct_cf;

        /* power on the socket */
        Cardbus_function_enable(ct);

        /* setup the PCI configuration registers */
        pgt_cardbus_setup(csc);

        /* map and establish the interrupt handler */
        csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
            pgt_intr, sc, sc->sc_dev.dv_xname);
        if (csc->sc_ih == NULL) {
                printf("%s: could not establish interrupt at %d\n",
                    sc->sc_dev.dv_xname, csc->sc_intrline);
                Cardbus_function_disable(ct);
                return (1);
        }

        return (0);
}

void
pgt_cardbus_disable(struct pgt_softc *sc)
{
	struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)sc;
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;

	/* unhook the interrupt handler */
	cardbus_intr_disestablish(cc, cf, csc->sc_ih);
	csc->sc_ih = NULL;

	/* power down the socket */
	Cardbus_function_disable(ct);
}

void
pgt_cardbus_power(struct pgt_softc *sc, int why)
{
	if (why == DVACT_RESUME)
		if (sc->sc_enable != NULL)
			(*sc->sc_enable)(sc);
	if (why == DVACT_SUSPEND)
		if (sc->sc_disable != NULL)
			(*sc->sc_disable)(sc);
}

void
pgt_cardbus_setup(struct pgt_cardbus_softc *csc)
{
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	pci_chipset_tag_t pc = csc->sc_pc;
	cardbus_function_tag_t cf = ct->ct_cf;
	pcireg_t reg;

	/* program the BAR */
	pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE0_REG,
	    csc->sc_bar0_val);

	/* make sure the right access type is on the cardbus bridge */
 	(*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
	(*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);

	/* enable the appropriate bits in the PCI CSR */
	reg = pci_conf_read(pc, csc->sc_tag,
	    PCI_COMMAND_STATUS_REG);
	reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE;
	pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
	    reg);
}


code:
/*	$OpenBSD: if_ral_cardbus.c,v 1.21 2013/12/06 21:03:02 deraadt Exp $  */

/*-
 * Copyright (c) 2005-2010 Damien Bergamini <damien.bergamini@free.fr>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * CardBus front-end for the Ralink RT2560/RT2561/RT2860/RT3090 driver.
 */

#include "bpfilter.h"

#include <sys/param.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/timeout.h>
#include <sys/device.h>

#include <machine/bus.h>
#include <machine/intr.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>

#include <netinet/in.h>
#include <netinet/if_ether.h>

#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_amrr.h>
#include <net80211/ieee80211_radiotap.h>

#include <dev/ic/rt2560var.h>
#include <dev/ic/rt2661var.h>
#include <dev/ic/rt2860var.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>

#include <dev/cardbus/cardbusvar.h>

static struct ral_opns {
	int	(*attach)(void *, int);
	int	(*detach)(void *);
	void	(*suspend)(void *);
	void	(*resume)(void *);
	int	(*intr)(void *);

}  ral_rt2560_opns = {
	rt2560_attach,
	rt2560_detach,
	rt2560_suspend,
	rt2560_wakeup,
	rt2560_intr

}, ral_rt2661_opns = {
	rt2661_attach,
	rt2661_detach,
	rt2661_suspend,
	rt2661_wakeup,
	rt2661_intr

}, ral_rt2860_opns = {
	rt2860_attach,
	rt2860_detach,
	rt2860_suspend,
	rt2860_wakeup,
	rt2860_intr
};

struct ral_cardbus_softc {
	union {
		struct rt2560_softc	sc_rt2560;
		struct rt2661_softc	sc_rt2661;
		struct rt2860_softc	sc_rt2860;
	} u;
#define sc_sc	u.sc_rt2560

	/* cardbus specific goo */
	struct ral_opns		*sc_opns;
	cardbus_devfunc_t	sc_ct;
	pcitag_t		sc_tag;
	void			*sc_ih;
	bus_size_t		sc_mapsize;
	pcireg_t		sc_bar_val;
	int			sc_intrline;
	pci_chipset_tag_t	sc_pc;
};

int	ral_cardbus_match(struct device *, void *, void *);
void	ral_cardbus_attach(struct device *, struct device *, void *);
int	ral_cardbus_detach(struct device *, int);
int	ral_cardbus_activate(struct device *, int);

struct cfattach ral_cardbus_ca = {
	sizeof (struct ral_cardbus_softc), ral_cardbus_match,
	ral_cardbus_attach, ral_cardbus_detach,
	ral_cardbus_activate
};

static const struct pci_matchid ral_cardbus_devices[] = {
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2560 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2561 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2561S },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2661 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2860 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2890 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2760 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT2790 },
	{ PCI_VENDOR_AWT,    PCI_PRODUCT_AWT_RT2890 },
	{ PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_1 },
	{ PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_2 },
	{ PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_3 },
	{ PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_4 },
	{ PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_5 },
	{ PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_6 },
	{ PCI_VENDOR_EDIMAX, PCI_PRODUCT_EDIMAX_RT2860_7 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3062 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3090 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3091 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3092 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3562 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3592 },
	{ PCI_VENDOR_RALINK, PCI_PRODUCT_RALINK_RT3593 }
};

int	ral_cardbus_enable(struct rt2560_softc *);
void	ral_cardbus_disable(struct rt2560_softc *);
void	ral_cardbus_setup(struct ral_cardbus_softc *);
void	ral_cardbus_wakeup(struct ral_cardbus_softc *);

int
ral_cardbus_match(struct device *parent, void *match, void *aux)
{
	return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
	    ral_cardbus_devices, nitems(ral_cardbus_devices)));
}

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;
	bus_addr_t base;
	int error;

	if (PCI_VENDOR(ca->ca_id) == PCI_VENDOR_RALINK) {
		switch (PCI_PRODUCT(ca->ca_id)) {
		case PCI_PRODUCT_RALINK_RT2560:
			csc->sc_opns = &ral_rt2560_opns;
			break;
		case PCI_PRODUCT_RALINK_RT2561:
		case PCI_PRODUCT_RALINK_RT2561S:
		case PCI_PRODUCT_RALINK_RT2661:
			csc->sc_opns = &ral_rt2661_opns;
			break;
		default:
			csc->sc_opns = &ral_rt2860_opns;
			break;
		}
	} else {
		/* all other vendors are RT2860 only */
		csc->sc_opns = &ral_rt2860_opns;
	}
	sc->sc_dmat = ca->ca_dmat;
	csc->sc_ct = ct;
	csc->sc_tag = ca->ca_tag;
	csc->sc_intrline = ca->ca_intrline;
	csc->sc_pc = ca->ca_pc;

	/* 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,
	    PCI_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, &base,
	    &csc->sc_mapsize);
	if (error != 0) {
		printf(": can't map mem space\n");
		return;
	}

	csc->sc_bar_val = base | PCI_MAPREG_TYPE_MEM;

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

	printf(": irq %d", csc->sc_intrline);

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

	Cardbus_function_disable(ct);
}

int
ral_cardbus_detach(struct device *self, int flags)
{
	struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)self;
	struct rt2560_softc *sc = &csc->sc_sc;
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;
	int error;

	error = (*csc->sc_opns->detach)(sc);
	if (error != 0)
		return error;

	/* unhook the interrupt handler */
	if (csc->sc_ih != NULL) {
		cardbus_intr_disestablish(cc, cf, csc->sc_ih);
		csc->sc_ih = NULL;
	}

	/* release bus space and close window */
	Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_st, sc->sc_sh,
	    csc->sc_mapsize);

	return 0;
}

int
ral_cardbus_activate(struct device *self, int act)
{
	struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)self;
	struct rt2560_softc *sc = &csc->sc_sc;

	switch (act) {
	case DVACT_SUSPEND:
		(*csc->sc_opns->suspend)(sc);
		break;
	case DVACT_WAKEUP:
		ral_cardbus_wakeup(csc);
		break;
	}

	return 0;
}

int
ral_cardbus_enable(struct rt2560_softc *sc)
{
	struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)sc;
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;

	/* power on the socket */
	Cardbus_function_enable(ct);

	/* setup the PCI configuration registers */
	ral_cardbus_setup(csc);

	/* map and establish the interrupt handler */
	csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
	    csc->sc_opns->intr, sc, sc->sc_dev.dv_xname);
	if (csc->sc_ih == NULL) {
		printf("%s: could not establish interrupt at %d\n",
		    sc->sc_dev.dv_xname, csc->sc_intrline);
		Cardbus_function_disable(ct);
		return 1;
	}

	return 0;
}

void
ral_cardbus_disable(struct rt2560_softc *sc)
{
	struct ral_cardbus_softc *csc = (struct ral_cardbus_softc *)sc;
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;

	/* unhook the interrupt handler */
	cardbus_intr_disestablish(cc, cf, csc->sc_ih);
	csc->sc_ih = NULL;

	/* power down the socket */
	Cardbus_function_disable(ct);
}

void
ral_cardbus_setup(struct ral_cardbus_softc *csc)
{
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	pci_chipset_tag_t pc = csc->sc_pc;
	cardbus_function_tag_t cf = ct->ct_cf;
	pcireg_t reg;

	/* program the BAR */
	pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE0_REG,
	    csc->sc_bar_val);

	/* make sure the right access type is on the cardbus bridge */
	(*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
	(*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);

	/* enable the appropriate bits in the PCI CSR */
	reg = pci_conf_read(pc, csc->sc_tag,
	    PCI_COMMAND_STATUS_REG);
	reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE;
	pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
	    reg);
}

void
ral_cardbus_wakeup(struct ral_cardbus_softc *csc)
{
	struct rt2560_softc *sc = &csc->sc_sc;
	int s;

	s = splnet();
	(*csc->sc_opns->resume)(sc);
	splx(s);
}


code:
/*	$OpenBSD: if_re_cardbus.c,v 1.27 2015/03/14 03:38:47 jsg Exp $	*/

/*
 * Copyright (c) 2005 Peter Valchev <pvalchev@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Cardbus front-end for the Realtek 8169
 */

#include <sys/param.h>
#include <sys/endian.h>
#include <sys/systm.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/timeout.h>
#include <sys/socket.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>

#include <netinet/in.h>
#include <netinet/if_ether.h>

#include <dev/mii/miivar.h>

#include <dev/pci/pcidevs.h>

#include <dev/cardbus/cardbusvar.h>

#include <dev/ic/rtl81x9reg.h>
#include <dev/ic/revar.h>

struct re_cardbus_softc {
	/* General */
	struct rl_softc sc_rl;

	/* Cardbus-specific data */
	void *sc_ih;
	cardbus_devfunc_t ct;
	pcitag_t sc_tag;
	pci_chipset_tag_t sc_pc;
	int sc_csr;
	int sc_cben;
	int sc_bar_reg;
	pcireg_t sc_bar_val;
	int sc_intrline;

	bus_size_t sc_mapsize;
};

int	re_cardbus_probe(struct device *, void *, void *);
void	re_cardbus_attach(struct device *, struct device *, void *);
int	re_cardbus_detach(struct device *, int);
void	re_cardbus_setup(struct rl_softc *);

/*
 * Cardbus autoconfig definitions
 */
struct cfattach re_cardbus_ca = {
	sizeof(struct re_cardbus_softc),
	re_cardbus_probe,
	re_cardbus_attach,
	re_cardbus_detach
};

const struct pci_matchid re_cardbus_devices[] = {
	{ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169 },
};

/*
 * Probe for a Realtek 8169/8110 chip. Check the PCI vendor and device
 * IDs against our list and return a device name if we find a match.
 */
int
re_cardbus_probe(struct device *parent, void *match, void *aux)
{
	return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
	    re_cardbus_devices, nitems(re_cardbus_devices)));
}

/*
 * Attach the interface. Allocate softc structures, do ifmedia
 * setup and ethernet/BPF attach.
 */
void
re_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct re_cardbus_softc	*csc = (struct re_cardbus_softc *)self;
	struct rl_softc		*sc = &csc->sc_rl;
	struct cardbus_attach_args *ca = aux;
	struct cardbus_softc *psc =
	    (struct cardbus_softc *)sc->sc_dev.dv_parent;
	cardbus_chipset_tag_t cc = psc->sc_cc;
	cardbus_function_tag_t cf = psc->sc_cf;
	cardbus_devfunc_t ct = ca->ca_ct;
	bus_addr_t adr;
	char intrstr[16];

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

	/*
	 * Map control/status registers.
	 */
	if (Cardbus_mapreg_map(ct, RL_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
	    &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
		csc->sc_cben = CARDBUS_MEM_ENABLE;
		csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
		csc->sc_bar_reg = RL_PCI_LOMEM;
		csc->sc_bar_val = adr | PCI_MAPREG_TYPE_MEM;
	} else {
		printf(": can't map mem space\n");
		return;
	}

	/* Enable power */
	Cardbus_function_enable(ct);

	/* Get chip out of powersave mode (if applicable), initialize
	 * config registers */
	re_cardbus_setup(sc);

	/* Allocate interrupt */
	csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline,
	    IPL_NET, re_intr, sc, sc->sc_dev.dv_xname);
	if (csc->sc_ih == NULL) {
		printf(": couldn't establish interrupt at %d",
		    ca->ca_intrline);
		Cardbus_function_disable(csc->ct);
		return;
	}
	snprintf(intrstr, sizeof(intrstr), "irq %d", ca->ca_intrline);

	sc->sc_product = PCI_PRODUCT(ca->ca_id);

	/* Call bus-independent (common) attach routine */
	if (re_attach(sc, intrstr)) {
		cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
		Cardbus_mapreg_unmap(ct, csc->sc_bar_reg, sc->rl_btag,
		    sc->rl_bhandle, csc->sc_mapsize);
	}
}

/*
 * Get chip out of power-saving mode, init registers
 */
void
re_cardbus_setup(struct rl_softc *sc)
{
	struct re_cardbus_softc *csc = (struct re_cardbus_softc *)sc;
	cardbus_devfunc_t ct = csc->ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	pci_chipset_tag_t pc = csc->sc_pc;
	pcireg_t reg, command;
	int pmreg;

	/* Handle power management nonsense */
	if (pci_get_capability(pc, csc->sc_tag,
	    PCI_CAP_PWRMGMT, &pmreg, 0)) {
		command = pci_conf_read(pc, csc->sc_tag,
		    pmreg + PCI_PMCSR);

		if (command & RL_PSTATE_MASK) {
			pcireg_t iobase, membase, irq;

			/* Save important PCI config data */
			iobase = pci_conf_read(pc, csc->sc_tag, RL_PCI_LOIO);
			membase = pci_conf_read(pc, csc->sc_tag, RL_PCI_LOMEM);
			irq = pci_conf_read(pc, csc->sc_tag, RL_PCI_INTLINE);

			/* Reset the power state */
			printf("%s: chip is in D%d power mode "
			    "-- setting to D0\n", sc->sc_dev.dv_xname,
			    command & RL_PSTATE_MASK);
			command &= RL_PSTATE_MASK;
			pci_conf_write(pc, csc->sc_tag, pmreg + PCI_PMCSR,
			    command);

			/* Restore PCI config data */
			pci_conf_write(pc, csc->sc_tag, RL_PCI_LOIO, iobase);
			pci_conf_write(pc, csc->sc_tag, RL_PCI_LOMEM, membase);
			pci_conf_write(pc, csc->sc_tag, RL_PCI_INTLINE, irq);
		}
	}

	/* Make sure the right access type is on the Cardbus bridge */
	(*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
	(*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);

	/* Program the BAR */
	pci_conf_write(pc, csc->sc_tag, csc->sc_bar_reg, csc->sc_bar_val);

	/* Enable proper bits in CARDBUS CSR */
	reg = pci_conf_read(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG);
	reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
	reg |= csc->sc_csr;
	pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG, reg);

	/* Make sure the latency timer is set to some reasonable value */
	reg = pci_conf_read(pc, csc->sc_tag, PCI_BHLC_REG);
	if (PCI_LATTIMER(reg) < 0x20) {
		reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
		reg |= (0x20 << PCI_LATTIMER_SHIFT);
		pci_conf_write(pc, csc->sc_tag, PCI_BHLC_REG, reg);
	}
}

/*
 * Cardbus detach function: deallocate all resources
 */
int
re_cardbus_detach(struct device *self, int flags)
{
	struct re_cardbus_softc *csc = (void *)self;
	struct rl_softc *sc = &csc->sc_rl;
	struct cardbus_devfunc *ct = csc->ct;
	struct ifnet *ifp = &sc->sc_arpcom.ac_if;

	/* Remove timeout handler */
	timeout_del(&sc->timer_handle);

	/* Detach PHY */
	if (LIST_FIRST(&sc->sc_mii.mii_phys) != NULL)
		mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);

	/* Delete media stuff */
	ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
	ether_ifdetach(ifp);
	if_detach(ifp);

	/* Disable interrupts */
	if (csc->sc_ih != NULL)
		cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);

	/* Free cardbus resources */
	Cardbus_mapreg_unmap(ct, csc->sc_bar_reg, sc->rl_btag, sc->rl_bhandle,
	    csc->sc_mapsize);

	return (0);
}


code:
/*	$OpenBSD: if_rl_cardbus.c,v 1.28 2014/12/19 22:44:58 guenther Exp $ */
/*	$NetBSD: if_rl_cardbus.c,v 1.3.8.3 2001/11/14 19:14:02 nathanw Exp $	*/

/*
 * Copyright (c) 2000 Masanori Kanaoka
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * if_rl_cardbus.c:
 *	Cardbus specific routines for Realtek 8139 ethernet adapter.
 *	Tested for
 *		- elecom-Laneed	LD-10/100CBA (Accton MPX5030)
 *		- MELCO		LPC3-TX-CB   (Realtek 8139)
 */

#include "bpfilter.h"

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/timeout.h>
#include <sys/device.h>
#include <sys/endian.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_media.h>

#if NBPFILTER > 0
#include <net/bpf.h>
#endif

#include <netinet/in.h>
#include <netinet/if_ether.h>

#include <machine/bus.h>
#include <machine/intr.h>

#include <dev/mii/miivar.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

#include <dev/cardbus/cardbusvar.h>

/*
 * Default to using PIO access for this driver. On SMP systems,
 * there appear to be problems with memory mapped mode: it looks like
 * doing too many memory mapped access back to back in rapid succession
 * can hang the bus. I'm inclined to blame this on crummy design/construction
 * on the part of Realtek. Memory mapped mode does appear to work on
 * uniprocessor systems though.
 */
#define RL_USEIOSPACE

#include <dev/ic/rtl81x9reg.h>

/*
 * Various supported device vendors/types and their names.
 */
const struct pci_matchid rl_cardbus_devices[] = {
	{ PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2000VX },
	{ PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_5030 },
	{ PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_2CB_TXD },
	{ PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_CB_TXD },
	{ PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DFE690TXD },
	{ PCI_VENDOR_PLANEX, PCI_PRODUCT_PLANEX_FNW_3603_TX },
	{ PCI_VENDOR_PLANEX, PCI_PRODUCT_PLANEX_FNW_3800_TX },
	{ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8138 },
	{ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8139 },
};

struct rl_cardbus_softc {
	struct rl_softc sc_rl;	/* real rtk softc */

	/* CardBus-specific goo. */
	void *sc_ih;
	cardbus_devfunc_t sc_ct;
	pci_chipset_tag_t sc_pc;
	pcitag_t sc_tag;
	int sc_csr;
	int sc_cben;
	int sc_bar_reg;
	pcireg_t sc_bar_val;
	bus_size_t sc_mapsize;
	int sc_intrline;
};

static int rl_cardbus_match(struct device *, void *, void *);
static void rl_cardbus_attach(struct device *, struct device *, void *);
static int rl_cardbus_detach(struct device *, int);
void rl_cardbus_setup(struct rl_cardbus_softc *);

struct cfattach rl_cardbus_ca = {
	sizeof(struct rl_cardbus_softc), rl_cardbus_match, rl_cardbus_attach,
	    rl_cardbus_detach
};

int
rl_cardbus_match(struct device *parent, void *match, void *aux)
{
	return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
	    rl_cardbus_devices, nitems(rl_cardbus_devices)));
}

void
rl_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct rl_cardbus_softc		*csc =
	    (struct rl_cardbus_softc *)self;
	struct rl_softc			*sc = &csc->sc_rl;
	struct cardbus_attach_args	*ca = aux;
	struct cardbus_softc		*psc =
	    (struct cardbus_softc *)sc->sc_dev.dv_parent;
	cardbus_chipset_tag_t		cc = psc->sc_cc;
	cardbus_function_tag_t		cf = psc->sc_cf;
	cardbus_devfunc_t		ct = ca->ca_ct;
	bus_addr_t			adr;

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

	/*
	 * Map control/status registers.
	 */
	csc->sc_csr = PCI_COMMAND_MASTER_ENABLE;
#ifdef RL_USEIOSPACE
	if (Cardbus_mapreg_map(ct, RL_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
	    &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
		csc->sc_cben = CARDBUS_IO_ENABLE;
		csc->sc_csr |= PCI_COMMAND_IO_ENABLE;
		csc->sc_bar_reg = RL_PCI_LOIO;
		csc->sc_bar_val = adr | PCI_MAPREG_TYPE_IO;
	}
#else
	if (Cardbus_mapreg_map(ct, RL_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
	    &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
		csc->sc_cben = CARDBUS_MEM_ENABLE;
		csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
		csc->sc_bar_reg = RL_PCI_LOMEM;
		csc->sc_bar_val = adr | PCI_MAPREG_TYPE_MEM;
	}
#endif
	else {
		printf("%s: unable to map deviceregisters\n",
			 sc->sc_dev.dv_xname);
		return;
	}

	Cardbus_function_enable(ct);

	rl_cardbus_setup(csc);

	/*
	 * Map and establish the interrupt.
	 */
	csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
	    rl_intr, sc, sc->sc_dev.dv_xname);
	if (csc->sc_ih == NULL) {
		printf(": couldn't establish interrupt\n");
		Cardbus_function_disable(csc->sc_ct);
		return;
	}
	printf(": irq %d", csc->sc_intrline);

	sc->rl_type = RL_8139;

	rl_attach(sc);
}

int
rl_cardbus_detach(struct device *self, int flags)
{
	struct rl_cardbus_softc	*csc = (void *) self;
	struct rl_softc		*sc = &csc->sc_rl;
	struct cardbus_devfunc	*ct = csc->sc_ct;
	int			rv;

#ifdef DIAGNOSTIC
	if (ct == NULL)
		panic("%s: data structure lacks", sc->sc_dev.dv_xname);
#endif
	rv = rl_detach(sc);
	if (rv)
		return (rv);
	/*
	 * Unhook the interrupt handler.
	 */
	if (csc->sc_ih != NULL)
		cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);

	/*
	 * Release bus space and close window.
	 */
	if (csc->sc_bar_reg != 0)
		Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
			sc->rl_btag, sc->rl_bhandle, csc->sc_mapsize);

	return (0);
}

void
rl_cardbus_setup(struct rl_cardbus_softc *csc)
{
	struct rl_softc		*sc = &csc->sc_rl;
	cardbus_devfunc_t	ct = csc->sc_ct;
	cardbus_chipset_tag_t	cc = ct->ct_cc;
	pci_chipset_tag_t	pc = csc->sc_pc;
	pcireg_t		reg, command;
	int			pmreg;

	/*
	 * Handle power management nonsense.
	 */
	if (pci_get_capability(pc, csc->sc_tag,
	    PCI_CAP_PWRMGMT, &pmreg, 0)) {
		command = pci_conf_read(pc, csc->sc_tag, pmreg + 4);
		if (command & RL_PSTATE_MASK) {
			pcireg_t		iobase, membase, irq;

			/* Save important PCI config data. */
			iobase = pci_conf_read(pc, csc->sc_tag,
			    RL_PCI_LOIO);
			membase = pci_conf_read(pc, csc->sc_tag,
			    RL_PCI_LOMEM);
			irq = pci_conf_read(pc, csc->sc_tag,
			    PCI_PRODUCT_DELTA_8139);

			/* Reset the power state. */
			printf("%s: chip is in D%d power mode "
			    "-- setting to D0\n", sc->sc_dev.dv_xname,
			    command & RL_PSTATE_MASK);
			command &= 0xFFFFFFFC;
			pci_conf_write(pc, csc->sc_tag,
			    pmreg + 4, command);

			/* Restore PCI config data. */
			pci_conf_write(pc, csc->sc_tag,
			    RL_PCI_LOIO, iobase);
			pci_conf_write(pc, csc->sc_tag,
			    RL_PCI_LOMEM, membase);
			pci_conf_write(pc, csc->sc_tag,
			    PCI_PRODUCT_DELTA_8139, irq);
		}
	}

	/* Make sure the right access type is on the CardBus bridge. */
	(*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
	(*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);

	/* Program the BAR */
	pci_conf_write(pc, csc->sc_tag,
		csc->sc_bar_reg, csc->sc_bar_val);

	/* Enable the appropriate bits in the CARDBUS CSR. */
	reg = pci_conf_read(pc, csc->sc_tag,
	    PCI_COMMAND_STATUS_REG);
	reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
	reg |= csc->sc_csr;
	pci_conf_write(pc, csc->sc_tag,
	    PCI_COMMAND_STATUS_REG, reg);

	/*
	 * Make sure the latency timer is set to some reasonable
	 * value.
	 */
	reg = pci_conf_read(pc, csc->sc_tag, PCI_BHLC_REG);
	if (PCI_LATTIMER(reg) < 0x20) {
		reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
		reg |= (0x20 << PCI_LATTIMER_SHIFT);
		pci_conf_write(pc, csc->sc_tag, PCI_BHLC_REG, reg);
	}
}


code:
/*	$OpenBSD: if_rtw_cardbus.c,v 1.25 2015/03/14 03:38:47 jsg Exp $	*/
/* $NetBSD: if_rtw_cardbus.c,v 1.4 2004/12/20 21:05:34 dyoung Exp $ */

/*-
 * Copyright (c) 2004, 2005 David Young.  All rights reserved.
 *
 * Adapted for the RTL8180 by David Young.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of David Young may not be used to endorse or promote
 *    products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL David
 * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 */
/*-
 * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Cardbus front-end for the Realtek RTL8180 802.11 MAC/BBP driver.
 *
 * TBD factor with atw, tlp Cardbus front-ends?
 */

#include "bpfilter.h"

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/device.h>
#include <sys/endian.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>

#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_var.h>

#if NBPFILTER > 0
#include <net/bpf.h>
#endif

#include <machine/bus.h>

#include <dev/ic/rtwreg.h>
#include <dev/ic/rtwvar.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

#include <dev/cardbus/cardbusvar.h>

/*
 * PCI configuration space registers used by the RTL8180.
 */
#define	RTW_PCI_IOBA		0x10	/* i/o mapped base */
#define	RTW_PCI_MMBA		0x14	/* memory mapped base */

struct rtw_cardbus_softc {
	struct rtw_softc sc_rtw;	/* real RTL8180 softc */

	/* CardBus-specific goo. */
	void			*sc_ih;		/* interrupt handle */
	cardbus_devfunc_t	sc_ct;		/* our CardBus devfuncs */
	pcitag_t		sc_tag;		/* our CardBus tag */
	pci_chipset_tag_t	sc_pc;		/* PCI chipset */
	int			sc_csr;		/* CSR bits */
	bus_size_t		sc_mapsize;	/* size of the mapped bus space
						 * region
						 */

	int			sc_cben;	/* CardBus enables */
	int			sc_bar_reg;	/* which BAR to use */
	pcireg_t		sc_bar_val;	/* value of the BAR */

	int			sc_intrline;	/* interrupt line */
};

int rtw_cardbus_match(struct device *, void *, void *);
void rtw_cardbus_attach(struct device *, struct device *, void *);
int rtw_cardbus_detach(struct device *, int);
void rtw_cardbus_intr_ack(struct rtw_regs *);
void rtw_cardbus_funcregen(struct rtw_regs *, int);

struct cfattach rtw_cardbus_ca = {
    sizeof(struct rtw_cardbus_softc), rtw_cardbus_match, rtw_cardbus_attach,
    	rtw_cardbus_detach
};

void	rtw_cardbus_setup(struct rtw_cardbus_softc *);

int rtw_cardbus_enable(struct rtw_softc *);
void rtw_cardbus_disable(struct rtw_softc *);
void rtw_cardbus_power(struct rtw_softc *, int);

const struct pci_matchid rtw_cardbus_devices[] = {
	{ PCI_VENDOR_REALTEK,	PCI_PRODUCT_REALTEK_RT8180 },
#ifdef RTW_DEBUG
	{ PCI_VENDOR_REALTEK,	PCI_PRODUCT_REALTEK_RT8185 },
	{ PCI_VENDOR_BELKIN2,	PCI_PRODUCT_BELKIN2_F5D7010 },
#endif
	{ PCI_VENDOR_BELKIN2,	PCI_PRODUCT_BELKIN2_F5D6020V3 },
	{ PCI_VENDOR_DLINK,	PCI_PRODUCT_DLINK_DWL610 }
};

int
rtw_cardbus_match(struct device *parent, void *match, void *aux)
{
	return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
	    rtw_cardbus_devices, nitems(rtw_cardbus_devices)));
}

void
rtw_cardbus_intr_ack(struct rtw_regs *regs)
{
	RTW_WRITE(regs, RTW_FER, RTW_FER_INTR);
}

void
rtw_cardbus_funcregen(struct rtw_regs *regs, int enable)
{
	u_int32_t reg;
	rtw_config0123_enable(regs, 1);
	reg = RTW_READ(regs, RTW_CONFIG3);
	if (enable) {
		RTW_WRITE(regs, RTW_CONFIG3, reg | RTW_CONFIG3_FUNCREGEN);
	} else {
		RTW_WRITE(regs, RTW_CONFIG3, reg & ~RTW_CONFIG3_FUNCREGEN);
	}
	rtw_config0123_enable(regs, 0);
}

void
rtw_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct rtw_cardbus_softc *csc = (void *)self;
	struct rtw_softc *sc = &csc->sc_rtw;
	struct rtw_regs *regs = &sc->sc_regs;
	struct cardbus_attach_args *ca = aux;
	cardbus_devfunc_t ct = ca->ca_ct;
	bus_addr_t adr;
	int rev;

	sc->sc_dmat = ca->ca_dmat;
	csc->sc_ct = ct;
	csc->sc_tag = ca->ca_tag;
	csc->sc_pc = ca->ca_pc;

	/*
	 * Power management hooks.
	 */
	sc->sc_enable = rtw_cardbus_enable;
	sc->sc_disable = rtw_cardbus_disable;
	sc->sc_power = rtw_cardbus_power;

	sc->sc_intr_ack = rtw_cardbus_intr_ack;

	/* Get revision info. */
	rev = PCI_REVISION(ca->ca_class);

	RTW_DPRINTF(RTW_DEBUG_ATTACH,
	    ("%s: pass %d.%d signature %08x\n", sc->sc_dev.dv_xname,
	     (rev >> 4) & 0xf, rev & 0xf,
	     pci_conf_read(ca->ca_pc, csc->sc_tag, 0x80)));

	/*
	 * Map the device.
	 */
	csc->sc_csr = PCI_COMMAND_MASTER_ENABLE;
	if (Cardbus_mapreg_map(ct, RTW_PCI_MMBA,
	    PCI_MAPREG_TYPE_MEM, 0, &regs->r_bt, &regs->r_bh, &adr,
	    &csc->sc_mapsize) == 0) {
		RTW_DPRINTF(RTW_DEBUG_ATTACH,
		    ("%s: %s mapped %lu bytes mem space\n",
		     sc->sc_dev.dv_xname, __func__, (long)csc->sc_mapsize));
		csc->sc_cben = CARDBUS_MEM_ENABLE;
		csc->sc_csr |= PCI_COMMAND_MEM_ENABLE;
		csc->sc_bar_reg = RTW_PCI_MMBA;
		csc->sc_bar_val = adr | PCI_MAPREG_TYPE_MEM;
	} else if (Cardbus_mapreg_map(ct, RTW_PCI_IOBA,
	    PCI_MAPREG_TYPE_IO, 0, &regs->r_bt, &regs->r_bh, &adr,
	    &csc->sc_mapsize) == 0) {
		RTW_DPRINTF(RTW_DEBUG_ATTACH,
		    ("%s: %s mapped %lu bytes I/O space\n",
		     sc->sc_dev.dv_xname, __func__, (long)csc->sc_mapsize));
		csc->sc_cben = CARDBUS_IO_ENABLE;
		csc->sc_csr |= PCI_COMMAND_IO_ENABLE;
		csc->sc_bar_reg = RTW_PCI_IOBA;
		csc->sc_bar_val = adr | PCI_MAPREG_TYPE_IO;
	} else {
		printf("%s: unable to map device registers\n",
		    sc->sc_dev.dv_xname);
		return;
	}

	/*
	 * Bring the chip out of powersave mode and initialize the
	 * configuration registers.
	 */
	rtw_cardbus_setup(csc);

	/* Remember which interrupt line. */
	csc->sc_intrline = ca->ca_intrline;

	printf(": irq %d\n", csc->sc_intrline);

	/*
	 * Finish off the attach.
	 */
	rtw_attach(sc);

	rtw_cardbus_funcregen(regs, 1);

	RTW_WRITE(regs, RTW_FEMR, RTW_FEMR_INTR);
	RTW_WRITE(regs, RTW_FER, RTW_FER_INTR);

	/*
	 * Power down the socket.
	 */
	Cardbus_function_disable(csc->sc_ct);
}

int
rtw_cardbus_detach(struct device *self, int flags)
{
	struct rtw_cardbus_softc *csc = (void *)self;
	struct rtw_softc *sc = &csc->sc_rtw;
	struct rtw_regs *regs = &sc->sc_regs;
	struct cardbus_devfunc *ct = csc->sc_ct;
	int rv;

#if defined(DIAGNOSTIC)
	if (ct == NULL)
		panic("%s: data structure lacks", sc->sc_dev.dv_xname);
#endif

	rv = rtw_detach(sc);
	if (rv)
		return (rv);

	rtw_cardbus_funcregen(regs, 0);

	/*
	 * Unhook the interrupt handler.
	 */
	if (csc->sc_ih != NULL)
		cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);

	/*
	 * Release bus space and close window.
	 */
	if (csc->sc_bar_reg != 0)
		Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
		    regs->r_bt, regs->r_bh, csc->sc_mapsize);

	return (0);
}

int
rtw_cardbus_enable(struct rtw_softc *sc)
{
	struct rtw_cardbus_softc *csc = (void *) sc;
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;

	/*
	 * Power on the socket.
	 */
	Cardbus_function_enable(ct);

	/*
	 * Set up the PCI configuration registers.
	 */
	rtw_cardbus_setup(csc);

	/*
	 * Map and establish the interrupt.
	 */
	csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
	    rtw_intr, sc, sc->sc_dev.dv_xname);
	if (csc->sc_ih == NULL) {
		printf("%s: unable to establish interrupt at %d\n",
		    sc->sc_dev.dv_xname, csc->sc_intrline);
		Cardbus_function_disable(csc->sc_ct);
		return (1);
	}

	rtw_cardbus_funcregen(&sc->sc_regs, 1);

	RTW_WRITE(&sc->sc_regs, RTW_FEMR, RTW_FEMR_INTR);
	RTW_WRITE(&sc->sc_regs, RTW_FER, RTW_FER_INTR);

	return (0);
}

void
rtw_cardbus_disable(struct rtw_softc *sc)
{
	struct rtw_cardbus_softc *csc = (void *) sc;
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	cardbus_function_tag_t cf = ct->ct_cf;

	RTW_WRITE(&sc->sc_regs, RTW_FEMR,
	    RTW_READ(&sc->sc_regs, RTW_FEMR) & ~RTW_FEMR_INTR);

	rtw_cardbus_funcregen(&sc->sc_regs, 0);

	/* Unhook the interrupt handler. */
	cardbus_intr_disestablish(cc, cf, csc->sc_ih);
	csc->sc_ih = NULL;

	/* Power down the socket. */
	Cardbus_function_disable(ct);
}

void
rtw_cardbus_power(struct rtw_softc *sc, int why)
{
	RTW_DPRINTF(RTW_DEBUG_ATTACH,
	    ("%s: rtw_cardbus_power\n", sc->sc_dev.dv_xname));

	if (why == DVACT_RESUME)
		rtw_enable(sc);
}

void
rtw_cardbus_setup(struct rtw_cardbus_softc *csc)
{
	struct rtw_softc *sc = &csc->sc_rtw;
	cardbus_devfunc_t ct = csc->sc_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	pci_chipset_tag_t pc = csc->sc_pc;
	pcireg_t reg;
	int pmreg;

	if (pci_get_capability(pc, csc->sc_tag,
	    PCI_CAP_PWRMGMT, &pmreg, 0)) {
		reg = pci_conf_read(pc, csc->sc_tag, pmreg + 4) & 0x03;
#if 1 /* XXX Probably not right for CardBus. */
		if (reg == 3) {
			/*
			 * The card has lost all configuration data in
			 * this state, so punt.
			 */
			printf("%s: unable to wake up from power state D3\n",
			    sc->sc_dev.dv_xname);
			return;
		}
#endif
		if (reg != 0) {
			printf("%s: waking up from power state D%d\n",
			    sc->sc_dev.dv_xname, reg);
			pci_conf_write(pc, csc->sc_tag,
			    pmreg + 4, 0);
		}
	}

	/* Program the BAR. */
	pci_conf_write(pc, csc->sc_tag, csc->sc_bar_reg,
	    csc->sc_bar_val);

	/* Make sure the right access type is on the CardBus bridge. */
	(*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
	(*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);

	/* Enable the appropriate bits in the PCI CSR. */
	reg = pci_conf_read(pc, csc->sc_tag,
	    PCI_COMMAND_STATUS_REG);
	reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
	reg |= csc->sc_csr;
	pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
	    reg);

	/*
	 * Make sure the latency timer is set to some reasonable
	 * value.
	 */
	reg = pci_conf_read(pc, csc->sc_tag, PCI_BHLC_REG);
	if (PCI_LATTIMER(reg) < 0x20) {
		reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
		reg |= (0x20 << PCI_LATTIMER_SHIFT);
		pci_conf_write(pc, csc->sc_tag, PCI_BHLC_REG, reg);
	}
}


code:
/*	$OpenBSD: if_xl_cardbus.c,v 1.31 2015/03/14 03:38:47 jsg Exp $ */
/*	$NetBSD: if_xl_cardbus.c,v 1.13 2000/03/07 00:32:52 mycroft Exp $	*/

/*
 * CardBus specific routines for 3Com 3C575-family CardBus ethernet adapter
 *
 * Copyright (c) 1998 and 1999
 *       HAYAKAWA Koichi.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY HAYAKAWA KOICHI ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *
 */

#include "bpfilter.h"

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/device.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_media.h>

#include <netinet/in.h>
#include <netinet/if_ether.h>

#include <machine/cpu.h>
#include <machine/bus.h>

#include <dev/cardbus/cardbusvar.h>
#include <dev/pci/pcidevs.h>

#include <dev/mii/miivar.h>

#include <dev/ic/xlreg.h>

#if defined XL_DEBUG
#define DPRINTF(a) printf a
#else
#define DPRINTF(a)
#endif

#define CARDBUS_3C575BTX_FUNCSTAT_PCIREG  CARDBUS_BASE2_REG  /* means 0x18 */

int xl_cardbus_match(struct device *, void *, void *);
void xl_cardbus_attach(struct device *, struct device *,void *);
int xl_cardbus_detach(struct device *, int);
void xl_cardbus_intr_ack(struct xl_softc *);

#define XL_CARDBUS_BOOMERANG	0x0001
#define XL_CARDBUS_CYCLONE	0x0002

#define XL_CARDBUS_INTR		0x0004
#define XL_CARDBUS_INTR_ACK	0x8000

struct xl_cardbus_softc {
	struct xl_softc sc_softc;

	cardbus_devfunc_t sc_ct;
	int sc_intrline;
	u_int8_t sc_cardbus_flags;
	u_int8_t sc_cardtype;

	/* CardBus function status space.  575B requests it. */
	bus_space_tag_t sc_funct;
	bus_space_handle_t sc_funch;
	bus_size_t sc_funcsize;

	bus_size_t sc_mapsize;		/* size of mapped bus space region */
};

struct cfattach xl_cardbus_ca = {
	sizeof(struct xl_cardbus_softc), xl_cardbus_match,
	    xl_cardbus_attach, xl_cardbus_detach
};

const struct xl_cardbus_product {
	u_int32_t	ecp_prodid;	/* CardBus product ID */
	int		ecp_flags;	/* initial softc flags */
	pcireg_t	ecp_csr;	/* PCI CSR flags */
	int		ecp_cardtype;	/* card type */
} xl_cardbus_products[] = {
	{ PCI_PRODUCT_3COM_3C575,
	  XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM,
	  PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE,
	  XL_CARDBUS_BOOMERANG },

	{ PCI_PRODUCT_3COM_3CCFE575BT,
	  XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
	      XL_FLAG_INVERT_LED_PWR,
	  PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
	      PCI_COMMAND_MASTER_ENABLE,
	  XL_CARDBUS_CYCLONE },

	{ PCI_PRODUCT_3COM_3CCFE575CT,
	  XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
	      XL_FLAG_INVERT_MII_PWR,
	  PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
	      PCI_COMMAND_MASTER_ENABLE,
	  XL_CARDBUS_CYCLONE },

	{ PCI_PRODUCT_3COM_3CCFEM656,
	  XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
	      XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR,
	  PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
	      PCI_COMMAND_MASTER_ENABLE,
	  XL_CARDBUS_CYCLONE },

	{ PCI_PRODUCT_3COM_3CCFEM656B,
	  XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
	      XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR,
	  PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
	      PCI_COMMAND_MASTER_ENABLE,
	  XL_CARDBUS_CYCLONE },

	{ PCI_PRODUCT_3COM_3CCFEM656C,
	  XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
	      XL_FLAG_INVERT_MII_PWR,
	  PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
	      PCI_COMMAND_MASTER_ENABLE,
	  XL_CARDBUS_CYCLONE },

	{ 0,
	  0,
	  0,
	  0 },
};

const struct xl_cardbus_product *xl_cardbus_lookup(const struct cardbus_attach_args *);

const struct xl_cardbus_product *
xl_cardbus_lookup(const struct cardbus_attach_args *ca)
{
	const struct xl_cardbus_product *ecp;

	if (PCI_VENDOR(ca->ca_id) != PCI_VENDOR_3COM)
		return (NULL);

	for (ecp = xl_cardbus_products; ecp->ecp_prodid != 0; ecp++)
		if (PCI_PRODUCT(ca->ca_id) == ecp->ecp_prodid)
			return (ecp);
	return (NULL);
}

int
xl_cardbus_match(struct device *parent, void *match, void *aux)
{
	struct cardbus_attach_args *ca = aux;

	if (xl_cardbus_lookup(ca) != NULL)
		return (1);

	return (0);
}

void
xl_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct xl_cardbus_softc *csc = (void *)self;
	struct xl_softc *sc = &csc->sc_softc;
	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 command, bhlc;
	const struct xl_cardbus_product *ecp;
	bus_space_handle_t ioh;
	bus_addr_t adr;

	if (Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, PCI_MAPREG_TYPE_IO, 0,
	    &sc->xl_btag, &ioh, &adr, &csc->sc_mapsize)) {
		printf(": can't map i/o space\n");
		return;
	}

	ecp = xl_cardbus_lookup(ca);
	if (ecp == NULL) {
		printf("\n");
		panic("xl_cardbus_attach: impossible");
	}

	sc->xl_flags = ecp->ecp_flags;
	sc->sc_dmat = ca->ca_dmat;

	sc->xl_bhandle = ioh;

	(ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE);

	command = pci_conf_read(ca->ca_pc, ca->ca_tag,
	    PCI_COMMAND_STATUS_REG);
	command |= ecp->ecp_csr;
	csc->sc_cardtype = ecp->ecp_cardtype;

	if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) {
		/* map CardBus function status window */
		if (Cardbus_mapreg_map(ct, CARDBUS_BASE2_REG,
		    PCI_MAPREG_TYPE_MEM, 0, &csc->sc_funct,
		    &csc->sc_funch, 0, &csc->sc_funcsize)) {
			printf("%s: unable to map function status window\n",
			    self->dv_xname);
			return;
		}

		/*
		 * Make sure CardBus bridge can access memory space.  Usually
		 * memory access is enabled by BIOS, but some BIOSes do not
		 * enable it.
		 */
		(ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
	}

	(ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
	pci_conf_write(ca->ca_pc, ca->ca_tag, PCI_COMMAND_STATUS_REG,
	    command);

 	/*
	 * set latency timer
	 */
	bhlc = pci_conf_read(ca->ca_pc, ca->ca_tag, PCI_BHLC_REG);
	if (PCI_LATTIMER(bhlc) < 0x20) {
		/* at least the value of latency timer should 0x20. */
		DPRINTF(("if_xl_cardbus: lattimer 0x%x -> 0x20\n",
		    PCI_LATTIMER(bhlc)));
		bhlc &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
		bhlc |= (0x20 << PCI_LATTIMER_SHIFT);
		pci_conf_write(ca->ca_pc, ca->ca_tag, PCI_BHLC_REG, bhlc);
	}

	csc->sc_ct = ca->ca_ct;
	csc->sc_intrline = ca->ca_intrline;

	/* Map and establish the interrupt. */

	sc->xl_intrhand = cardbus_intr_establish(cc, cf, ca->ca_intrline,
	    IPL_NET, xl_intr, csc, self->dv_xname);

	if (sc->xl_intrhand == NULL) {
		printf(": couldn't establish interrupt");
		printf(" at %d", ca->ca_intrline);
		printf("\n");
		return;
	}
	printf(": irq %d", ca->ca_intrline);

	sc->intr_ack = xl_cardbus_intr_ack;

	xl_attach(sc);

	if (csc->sc_cardtype == XL_CARDBUS_CYCLONE)
		bus_space_write_4(csc->sc_funct, csc->sc_funch,
		    XL_CARDBUS_INTR, XL_CARDBUS_INTR_ACK);

}

int
xl_cardbus_detach(struct device *self, int arg)
{
	struct xl_cardbus_softc *csc = (void *)self;
	struct xl_softc *sc = &csc->sc_softc;
	struct cardbus_devfunc *ct = csc->sc_ct;

	cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf,
	    sc->xl_intrhand);
	xl_detach(sc);
	if (csc->sc_cardtype == XL_CARDBUS_CYCLONE)
		Cardbus_mapreg_unmap(ct, CARDBUS_BASE2_REG,
		    csc->sc_funct, csc->sc_funch, csc->sc_funcsize);
	Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->xl_btag,
	    sc->xl_bhandle, csc->sc_mapsize);
	return (0);
}

void
xl_cardbus_intr_ack(struct xl_softc *sc)
{
	struct xl_cardbus_softc *csc = (struct xl_cardbus_softc *)sc;

	bus_space_write_4(csc->sc_funct, csc->sc_funch, XL_CARDBUS_INTR,
	    XL_CARDBUS_INTR_ACK);
}


code:
/*	$OpenBSD: ohci_cardbus.c,v 1.21 2015/03/14 03:38:47 jsg Exp $ */
/*	$NetBSD: ohci_cardbus.c,v 1.19 2004/08/02 19:14:28 mycroft Exp $	*/

/*
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Lennart Augustsson (lennart@augustsson.net) at
 * Carlstedt Research & Technology.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * USB Open Host Controller driver.
 *
 * OHCI spec: http://www.intel.com/design/usb/ohci11d.pdf
 * USB spec: http://www.teleport.com/cgi-bin/mailmerge.cgi/~usb/cgiform.tpl
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>

#include <machine/bus.h>

#include <dev/cardbus/cardbusvar.h>

#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usb_mem.h>

#include <dev/usb/ohcireg.h>
#include <dev/usb/ohcivar.h>

int	ohci_cardbus_match(struct device *, void *, void *);
void	ohci_cardbus_attach(struct device *, struct device *, void *);
int	ohci_cardbus_detach(struct device *, int);

struct ohci_cardbus_softc {
	struct ohci_softc	sc;
	cardbus_chipset_tag_t	sc_cc;
	cardbus_function_tag_t	sc_cf;
	cardbus_devfunc_t	sc_ct;
	void 			*sc_ih;		/* interrupt vectoring */
};

struct cfattach ohci_cardbus_ca = {
	sizeof(struct ohci_cardbus_softc), ohci_cardbus_match,
	    ohci_cardbus_attach, ohci_cardbus_detach, ohci_activate
};

#define CARDBUS_CBMEM PCI_CBMEM
#define cardbus_findvendor pci_findvendor

int
ohci_cardbus_match(struct device *parent, void *match, void *aux)
{
	struct cardbus_attach_args *ca = (struct cardbus_attach_args *)aux;

	if (PCI_CLASS(ca->ca_class) == PCI_CLASS_SERIALBUS &&
	    PCI_SUBCLASS(ca->ca_class) == PCI_SUBCLASS_SERIALBUS_USB &&
	    PCI_INTERFACE(ca->ca_class) == PCI_INTERFACE_OHCI)
		return (1);

	return (0);
}

void
ohci_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct ohci_cardbus_softc *sc = (struct ohci_cardbus_softc *)self;
	struct cardbus_attach_args *ca = aux;
	cardbus_devfunc_t ct = ca->ca_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	pci_chipset_tag_t pc = ca->ca_pc;
	cardbus_function_tag_t cf = ct->ct_cf;
	pcireg_t csr;
	usbd_status r;
	const char *vendor;
	const char *devname = sc->sc.sc_bus.bdev.dv_xname;

	/* Map I/O registers */
	if (Cardbus_mapreg_map(ct, CARDBUS_CBMEM, PCI_MAPREG_TYPE_MEM, 0,
			   &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size)) {
		printf(": can't map mem space\n");
		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_MIE);

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

	(ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
	(ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);

	/* Enable the device. */
	csr = pci_conf_read(pc, ca->ca_tag,
				PCI_COMMAND_STATUS_REG);
	pci_conf_write(pc, ca->ca_tag, PCI_COMMAND_STATUS_REG,
		       csr | PCI_COMMAND_MASTER_ENABLE
			   | PCI_COMMAND_MEM_ENABLE);

	sc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline,
					   IPL_USB, ohci_intr, sc, devname);
	if (sc->sc_ih == NULL) {
		printf(": couldn't establish interrupt\n");
		return;
	}
	printf(": irq %d", ca->ca_intrline);

	/* Figure out vendor for root hub descriptor. */
	vendor = cardbus_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));

	/* Display revision and perform legacy emulation handover. */
	if (ohci_checkrev(&sc->sc) != USBD_NORMAL_COMPLETION ||
	    ohci_handover(&sc->sc) != USBD_NORMAL_COMPLETION) {
		cardbus_intr_disestablish(sc->sc_cc, sc->sc_cf, sc->sc_ih);
		sc->sc_ih = 0;
		return;
	}

	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(sc->sc_cc, sc->sc_cf, sc->sc_ih);
		sc->sc_ih = 0;

		return;
	}

	/* Attach usb device. */
	config_found(self, &sc->sc.sc_bus, usbctlprint);
}

int
ohci_cardbus_detach(struct device *self, int flags)
{
	struct ohci_cardbus_softc *sc = (struct ohci_cardbus_softc *)self;
	struct cardbus_devfunc *ct = sc->sc_ct;
	int rv;

	rv = ohci_detach(self, flags);
	if (rv)
		return (rv);

	if (sc->sc_ih != NULL) {
		cardbus_intr_disestablish(sc->sc_cc, sc->sc_cf, sc->sc_ih);
		sc->sc_ih = NULL;
	}
	if (sc->sc.sc_size) {
		Cardbus_mapreg_unmap(ct, CARDBUS_CBMEM, sc->sc.iot,
		    sc->sc.ioh, sc->sc.sc_size);
		sc->sc.sc_size = 0;
	}

	return (0);
}


code:
/*	$OpenBSD: puc_cardbus.c,v 1.8 2011/11/15 22:27:53 deraadt Exp $	*/

/*
 * Copyright (c) 2006 Michael Shalayeff
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/tty.h>

#include <machine/bus.h>
#include <dev/ic/comvar.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <dev/cardbus/cardbusvar.h>

#include <dev/pci/pucvar.h>

struct puc_cardbus_softc {
	struct puc_softc sc_psc;

	struct cardbus_devfunc *ct;
	int intrline;
};

int	puc_cardbus_match(struct device *, void *, void *);
void	puc_cardbus_attach(struct device *, struct device *, void *);
int	puc_cardbus_detach(struct device *, int);

const char *puc_cardbus_intr_string(struct puc_attach_args *);
void *puc_cardbus_intr_establish(struct puc_attach_args *, int,
    int (*)(void *), void *, char *);

struct cfattach puc_cardbus_ca = {
	sizeof(struct puc_cardbus_softc), puc_cardbus_match,
	puc_cardbus_attach, puc_cardbus_detach
};

int
puc_cardbus_match(struct device *parent, void *match, void *aux)
{
	struct cardbus_attach_args *ca = aux;
	pci_chipset_tag_t pc = ca->ca_pc;
	pcireg_t bhlc, reg;

	bhlc = pci_conf_read(pc, ca->ca_tag, PCI_BHLC_REG);
	if (PCI_HDRTYPE_TYPE(bhlc) != 0)
		return(0);

	/* this one is some sort of a bridge and not a puc */
	if (PCI_VENDOR(ca->ca_id) == PCI_VENDOR_OXFORD2 &&
	    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_OXFORD2_EXSYS_EX41098)
		return (0);

	reg = pci_conf_read(pc, ca->ca_tag, PCI_SUBSYS_ID_REG);
	if (puc_find_description(PCI_VENDOR(ca->ca_id),
	    PCI_PRODUCT(ca->ca_id), PCI_VENDOR(reg), PCI_PRODUCT(reg)))
		return (10);

	return (0);
}

void
puc_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct puc_cardbus_softc *csc = (struct puc_cardbus_softc *)self;
	struct puc_softc *sc = &csc->sc_psc;
	struct cardbus_attach_args *ca = aux;
	struct cardbus_devfunc *ct = ca->ca_ct;
	cardbus_chipset_tag_t cc = ct->ct_cc;
	pci_chipset_tag_t pc = ca->ca_pc;
	cardbus_function_tag_t cf = ct->ct_cf;
	struct puc_attach_args paa;
	pcireg_t reg;
	int i;

	Cardbus_function_enable(ct);

	csc->ct = ct;

	reg = pci_conf_read(pc, ca->ca_tag, PCI_SUBSYS_ID_REG);
	sc->sc_desc = puc_find_description(PCI_VENDOR(ca->ca_id),
	    PCI_PRODUCT(ca->ca_id), PCI_VENDOR(reg), PCI_PRODUCT(reg));

	puc_print_ports(sc->sc_desc);

	/* the fifth one is some memory we dunno */
	for (i = 0; i < PUC_NBARS; i++) {
		pcireg_t type;
		int bar;

		sc->sc_bar_mappings[i].mapped = 0;
		bar = PCI_MAPREG_START + 4 * i;
		if (!pci_mapreg_probe(pc, ca->ca_tag, bar, &type))
			continue;

		if (!(sc->sc_bar_mappings[i].mapped = !Cardbus_mapreg_map(ct,
		    bar, type, 0,
		    &sc->sc_bar_mappings[i].t, &sc->sc_bar_mappings[i].h,
		    &sc->sc_bar_mappings[i].a, &sc->sc_bar_mappings[i].s)))
			printf("%s: couldn't map BAR at offset 0x%lx\n",
			    sc->sc_dev.dv_xname, (long)bar);
		sc->sc_bar_mappings[i].type = type;
	}

	csc->intrline = ca->ca_intrline;

	if (pci_get_capability(pc, ca->ca_tag, PCI_CAP_PWRMGMT, &reg,
	    0)) {
		reg = pci_conf_read(pc, ca->ca_tag, reg + 4) & 3;
		if (reg) {
			printf("%s: awakening from state D%d\n",
			    sc->sc_dev.dv_xname, reg);
			pci_conf_write(pc, ca->ca_tag, reg + 4, 0);
		}
	}

	(*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
	(*cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE);
	(*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);

	paa.puc = sc;
	paa.intr_string = &puc_cardbus_intr_string;
	paa.intr_establish = &puc_cardbus_intr_establish;

	puc_common_attach(sc, &paa);
}

const char *
puc_cardbus_intr_string(struct puc_attach_args *paa)
{
	struct puc_cardbus_softc *sc = paa->puc;
	static char str[16];

	snprintf(str, sizeof str, "irq %d", sc->intrline);
	return (str);
}

void *
puc_cardbus_intr_establish(struct puc_attach_args *paa, int type,
    int (*func)(void *), void *arg, char *name)
{
	struct puc_cardbus_softc *sc = paa->puc;
	struct puc_softc *psc = &sc->sc_psc;
	struct cardbus_devfunc *ct = sc->ct;

	psc->sc_ports[paa->port].intrhand =
	    cardbus_intr_establish(ct->ct_cc, ct->ct_cf, sc->intrline,
		type, func, arg, name);

	return (psc->sc_ports[paa->port].intrhand);
}

int
puc_cardbus_detach(struct device *self, int flags)
{
	struct puc_cardbus_softc *sc = (struct puc_cardbus_softc *)self;
	struct puc_softc *psc = &sc->sc_psc;
	struct cardbus_devfunc *ct = sc->ct;
	int i, rv;

	for (i = PUC_MAX_PORTS; i--; ) {
		if (psc->sc_ports[i].intrhand)
			cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf,
			    psc->sc_ports[i].intrhand);
		if (psc->sc_ports[i].dev)
			if ((rv = config_detach(psc->sc_ports[i].dev, flags)))
				return (rv);
	}

	for (i = PUC_NBARS; i--; )
		if (psc->sc_bar_mappings[i].mapped)
			Cardbus_mapreg_unmap(ct, psc->sc_bar_mappings[i].type,
			    psc->sc_bar_mappings[i].t,
			    psc->sc_bar_mappings[i].h,
			    psc->sc_bar_mappings[i].s);

	return (0);
}


code:
/*	$OpenBSD: rbus.c,v 1.16 2010/09/22 02:28:37 jsg Exp $	*/
/*	$NetBSD: rbus.c,v 1.3 1999/11/06 06:20:53 soren Exp $	*/
/*
 * Copyright (c) 1999
 *     HAYAKAWA Koichi.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/extent.h>

#include <machine/bus.h>

#include <dev/cardbus/rbus.h>

/* #define RBUS_DEBUG */

#if defined RBUS_DEBUG
#define STATIC
#define DPRINTF(a) printf a
#else
#ifdef DDB
#define STATIC
#else
#define STATIC static
#endif
#define DPRINTF(a)
#endif

int
rbus_space_alloc(rbus_tag_t rbt, bus_addr_t addr, bus_size_t size,
    bus_addr_t mask, bus_addr_t align, int flags, bus_addr_t *addrp,
    bus_space_handle_t *bshp)
{
	return (rbus_space_alloc_subregion(rbt, rbt->rb_start, rbt->rb_end,
	    addr, size, mask, align, flags, addrp, bshp));
}

int
rbus_space_alloc_subregion(rbus_tag_t rbt, bus_addr_t substart,
    bus_addr_t subend, bus_addr_t addr, bus_size_t size,
    bus_addr_t mask, bus_addr_t align, int flags, bus_addr_t *addrp,
    bus_space_handle_t *bshp)
{
	bus_addr_t decodesize = mask + 1;
	bus_addr_t boundary, search_addr;
	int val;
	u_long result;
	int exflags = EX_FAST | EX_NOWAIT | EX_MALLOCOK;

	DPRINTF(("rbus_space_alloc: addr %lx, size %lx, mask %lx, align %lx\n",
	    (u_long)addr, (u_long)size, (u_long)mask, (u_long)align));

	if (mask == 0) {
		/* FULL Decode */
		decodesize = 0;
	}

	if (rbt->rb_flags == RBUS_SPACE_SHARE ||
	    rbt->rb_flags == RBUS_SPACE_DEDICATE) {
		/* rbt has its own sh_extent */

		/* sanity check: the subregion [substart, subend] should be
		   smaller than the region included in sh_extent */
		if (substart < rbt->rb_ext->ex_start ||
		    subend > rbt->rb_ext->ex_end) {
			DPRINTF(("rbus: out of range\n"));
			return (1);
		}

		if (decodesize == align) {
			if (extent_alloc_subregion(rbt->rb_ext, substart,
			    subend, size, align, 0, 0, exflags, &result))
				return (1);
		} else if (decodesize == 0) {
			/* maybe, the register is overflowed. */

			if (extent_alloc_subregion(rbt->rb_ext, addr,
			    addr + size, size, 1, 0, 0, exflags, &result))
				return (1);
		} else {
			boundary = decodesize > align ? decodesize : align;

			search_addr = (substart & ~(boundary - 1)) + addr;

			if (search_addr < substart)
				search_addr += boundary;

			val = 1;
			for (; search_addr + size <= subend;
			    search_addr += boundary) {
				val = extent_alloc_subregion(
				    rbt->rb_ext,search_addr,
				    search_addr + size, size, align, 0, 0,
				    exflags, &result);
				DPRINTF(("rbus: trying [%lx:%lx] %lx\n",
				    (u_long)search_addr,
				    (u_long)search_addr + size,
				    (u_long)align));
				if (val == 0)
					break;
			}

			if (val != 0) {
				/* no space found */
				DPRINTF(("rbus: no space found\n"));
				return (1);
			}
		}

		if (md_space_map(rbt, result, size, flags, bshp)) {
			/* map failed */
			extent_free(rbt->rb_ext, result, size, exflags);
			return (1);
		}

		if (addrp != NULL)
			*addrp = result;
		return (0);
	} else {
		/* error!! */
		DPRINTF(("rbus: no rbus type\n"));
		return (1);
	}
}

int
rbus_space_free(rbus_tag_t rbt, bus_space_handle_t bsh, bus_size_t size,
    bus_addr_t *addrp)
{
	int exflags = EX_FAST | EX_NOWAIT;
	bus_addr_t addr;
	int status = 1;

	if (rbt->rb_flags == RBUS_SPACE_SHARE ||
	    rbt->rb_flags == RBUS_SPACE_DEDICATE) {
		md_space_unmap(rbt, bsh, size, &addr);

		extent_free(rbt->rb_ext, addr, size, exflags);

		status = 0;
	} else {
		/* error. INVALID rbustag */
		status = 1;
	}

	if (addrp != NULL)
		*addrp = addr;

	return (status);
}

/*
 * rbus_tag_t
 * rbus_new_body(bus_space_tag_t bt,
 *               struct extent *ex, bus_addr_t start, bus_size_t end,
 *               int flags)
 *
 */
rbus_tag_t
rbus_new_body(bus_space_tag_t bt, struct extent *ex,
    bus_addr_t start, bus_addr_t end, int flags)
{
	rbus_tag_t rb;

	if ((rb = (rbus_tag_t)malloc(sizeof(struct rbustag), M_DEVBUF,
	    M_NOWAIT)) == NULL) {
		panic("no memory for rbus instance");
	}

	rb->rb_bt = bt;
	rb->rb_start = start;
	rb->rb_end = end;
	rb->rb_flags = flags;
	rb->rb_ext = ex;

	DPRINTF(("rbus_new_body: [%lx, %lx] type %s name [%s]\n",
	    (u_long)start, (u_long)end,
	   flags == RBUS_SPACE_SHARE ? "share" :
	   flags == RBUS_SPACE_DEDICATE ? "dedicated" : "invalid",
	   ex != NULL ? ex->ex_name : "noname"));

	return (rb);
}

/*
 * rbus_tag_t rbus_new_root_delegate(bus_space_tag, bus_addr_t,
 *                                   bus_size_t)
 *
 *  This function makes a root rbus instance.
 */
rbus_tag_t
rbus_new_root_delegate(bus_space_tag_t bt, bus_addr_t start, bus_size_t size)
{
	rbus_tag_t rb;
	struct extent *ex;

	if ((ex = extent_create("rbus root", start, start + size, M_DEVBUF,
	    NULL, 0, EX_NOCOALESCE|EX_NOWAIT)) == NULL)
		return (NULL);

	rb = rbus_new_body(bt, ex, start, start + size,
	    RBUS_SPACE_DEDICATE);

	if (rb == NULL)
		extent_destroy(ex);

	return (rb);
}

/*
 * rbus_tag_t rbus_new_root_share(bus_space_tag, struct extent *,
 *                                 bus_addr_t, bus_size_t)
 *
 *  This function makes a root rbus instance.
 */
rbus_tag_t
rbus_new_root_share(bus_space_tag_t bt, struct extent *ex, bus_addr_t start,
    bus_size_t size)
{
	/* sanity check */
	if (start < ex->ex_start || start + size > ex->ex_end) {
		/* out of range: [start, size] should be contained in
		 * parent space
		 */
		return (0);
		/* Should I invoke panic? */
	}

	return (rbus_new_body(bt, ex, start, start + size,
	    RBUS_SPACE_SHARE));
}


code:
/*	$OpenBSD: rbus.h,v 1.10 2010/09/22 02:28:37 jsg Exp $ */
/*	$NetBSD: rbus.h,v 1.3 1999/12/15 12:28:55 kleink Exp $	*/
/*
 * Copyright (c) 1999
 *     HAYAKAWA Koichi.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _DEV_CARDBUS_RBUS_H_
#define _DEV_CARDBUS_RBUS_H_

/*
 * This file defines the rbus (pseudo) class
 *
 * What is rbus?
 *
 *  Ths rbus is a recursive bus-space administrator.  This means a
 *  parent bus-space administrator, which usually belongs to a bus
 *  bridge, makes some child bus-space administrators and gives
 *  (restricted) bus-space to children.  There is a root bus-space
 *  administrator which maintains the whole bus-space.
 *
 * Why recursive?
 *
 *  The recursive bus-space administration has two reasons. For one
 *  this modelling matches the actual memory and io space management
 *  of bridge devices quite well. Furthermore  is the rbus a
 *  distributed management system, as such it plays well with
 *  multi-thread kernel.
 *
 * Abstraction
 *
 *  rbus can model a bus-to-bus bridge in two ways: dedicated or shared
 *  Dedicated: the bridge has its own bus space.
 *  Shared: the bridge has bus space, but this bus space is
 *  shared with other bus bridges.
 */

/* require sys/extent.h */
/* require machine/bus.h */

struct extent;

/*
 *     General rule
 *
 * 1) When a rbustag has its own space (whether shared or dedicated),
 *    allocate from rb_ext.
 */
struct rbustag {
	bus_space_tag_t rb_bt;
	struct extent *rb_ext;
	bus_addr_t rb_start;
	bus_addr_t rb_end;
	bus_addr_t rb_offset;
#if notyet
	int (*rb_space_alloc)(struct rbustag *, bus_addr_t, bus_addr_t,
	    bus_addr_t, bus_size_t, bus_addr_t, bus_addr_t,
	    int, bus_addr_t *, bus_space_handle_t *);
	int (*rbus_space_free)(struct rbustag *, bus_space_handle_t,
	    bus_size_t, bus_addr_t *);
#endif
	int rb_flags;
#define RBUS_SPACE_INVALID   0x00
#define RBUS_SPACE_SHARE     0x01
#define RBUS_SPACE_DEDICATE  0x02
#define RBUS_SPACE_MASK      0x03
	/* your own data below */
	void *rb_md;
};

typedef struct rbustag *rbus_tag_t;

/*
 * These functions sugarcoat rbus interface to make rbus being used
 * easier.  These functions should be member functions of rbus
 * `class'.
 */
int	rbus_space_alloc(rbus_tag_t, bus_addr_t, bus_size_t, bus_addr_t,
	    bus_addr_t, int, bus_addr_t *, bus_space_handle_t *);

int	rbus_space_alloc_subregion(rbus_tag_t, bus_addr_t, bus_addr_t,
	    bus_addr_t, bus_size_t, bus_addr_t, bus_addr_t, int,
	    bus_addr_t *, bus_space_handle_t *);

int	rbus_space_free(rbus_tag_t, bus_space_handle_t, bus_size_t,
	    bus_addr_t *);

/*
 * These functions create rbus instance.  These functions are
 * so-called-as a constructor of rbus.
 *
 */

rbus_tag_t	rbus_new_body(bus_space_tag_t, struct extent *,
		      bus_addr_t, bus_addr_t, int);

rbus_tag_t	rbus_new_root_delegate(bus_space_tag_t, bus_addr_t, bus_size_t);
rbus_tag_t	rbus_new_root_share(bus_space_tag_t, struct extent *,
		    bus_addr_t, bus_size_t);

/*
 * Machine-dependent definitions.
 */
#include <machine/rbus_machdep.h>

#endif /* !_DEV_CARDBUS_RBUS_H_ */