summaryrefslogtreecommitdiffstats
path: root/sys/dev/cardbus
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2005-12-29 01:43:47 +0000
committerimp <imp@FreeBSD.org>2005-12-29 01:43:47 +0000
commit2d3e88cd9e999219b2101e65b3390d628941126e (patch)
treebf533208984821e83f178063f9eae3f952f8b8a9 /sys/dev/cardbus
parent10c2623c78422d9bb6f770ec6ab49b3f21dca64e (diff)
downloadFreeBSD-src-2d3e88cd9e999219b2101e65b3390d628941126e.zip
FreeBSD-src-2d3e88cd9e999219b2101e65b3390d628941126e.tar.gz
Implement /dev/cardbus%d.cis, same thing as /dev/pccard%d.cis. There
are some rough edges with this still, but it seems to work well enough to commit.
Diffstat (limited to 'sys/dev/cardbus')
-rw-r--r--sys/dev/cardbus/cardbus.c7
-rw-r--r--sys/dev/cardbus/cardbus_cis.c120
-rw-r--r--sys/dev/cardbus/cardbus_device.c180
-rw-r--r--sys/dev/cardbus/cardbusvar.h32
4 files changed, 268 insertions, 71 deletions
diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c
index 49bc7fd..3611543 100644
--- a/sys/dev/cardbus/cardbus.c
+++ b/sys/dev/cardbus/cardbus.c
@@ -406,13 +406,20 @@ cardbus_probe(device_t cbdev)
static int
cardbus_attach(device_t cbdev)
{
+ struct cardbus_softc *sc = device_get_softc(cbdev);
+
+ sc->sc_dev = cbdev;
+ cardbus_device_create(sc);
return 0;
}
static int
cardbus_detach(device_t cbdev)
{
+ struct cardbus_softc *sc = device_get_softc(cbdev);
+
cardbus_detach_card(cbdev);
+ cardbus_device_destroy(sc);
return 0;
}
diff --git a/sys/dev/cardbus/cardbus_cis.c b/sys/dev/cardbus/cardbus_cis.c
index 4d7b973..552d32d 100644
--- a/sys/dev/cardbus/cardbus_cis.c
+++ b/sys/dev/cardbus/cardbus_cis.c
@@ -58,45 +58,33 @@ extern int cardbus_cis_debug;
#define DPRINTF(a) if (cardbus_cis_debug) printf a
#define DEVPRINTF(x) if (cardbus_cis_debug) device_printf x
-struct tuple_callbacks;
-
-typedef int (tuple_cb) (device_t cbdev, device_t child, int id, int len,
- uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
-
-struct tuple_callbacks {
- int id;
- char *name;
- tuple_cb *func;
-};
-
static int decode_tuple_generic(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_linktarget(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_vers_1(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_funcid(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_manfid(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_funce(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_bar(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_unhandled(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_end(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int cardbus_read_tuple_conf(device_t cbdev, device_t child,
uint32_t start, uint32_t *off, int *tupleid, int *len,
@@ -113,9 +101,8 @@ static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child,
uint32_t *start, int *rid);
static int decode_tuple(device_t cbdev, device_t child, int tupleid,
int len, uint8_t *tupledata, uint32_t start,
- uint32_t *off, struct tuple_callbacks *callbacks);
-static int cardbus_parse_cis(device_t cbdev, device_t child,
- struct tuple_callbacks *callbacks);
+ uint32_t *off, struct tuple_callbacks *callbacks,
+ void *);
#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
@@ -139,7 +126,7 @@ static char *funcnames[] = {
static int
decode_tuple_generic(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
int i;
@@ -162,7 +149,7 @@ decode_tuple_generic(device_t cbdev, device_t child, int id,
static int
decode_tuple_linktarget(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
int i;
@@ -180,7 +167,7 @@ decode_tuple_linktarget(device_t cbdev, device_t child, int id,
tupledata[2] != 'S') {
printf("Invalid data for CIS Link Target!\n");
decode_tuple_generic(cbdev, child, id, len, tupledata,
- start, off, info);
+ start, off, info, argp);
return (EINVAL);
}
return (0);
@@ -189,7 +176,7 @@ decode_tuple_linktarget(device_t cbdev, device_t child, int id,
static int
decode_tuple_vers_1(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
int i;
@@ -212,7 +199,7 @@ decode_tuple_vers_1(device_t cbdev, device_t child, int id,
static int
decode_tuple_funcid(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
struct cardbus_devinfo *dinfo = device_get_ivars(child);
int numnames = sizeof(funcnames) / sizeof(funcnames[0]);
@@ -225,7 +212,7 @@ decode_tuple_funcid(device_t cbdev, device_t child, int id,
printf("%s", funcnames[tupledata[i]]);
else
printf("Unknown(%d)", tupledata[i]);
- if (i < len-1)
+ if (i < len - 1)
printf(", ");
}
printf("\n");
@@ -238,7 +225,7 @@ decode_tuple_funcid(device_t cbdev, device_t child, int id,
static int
decode_tuple_manfid(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
struct cardbus_devinfo *dinfo = device_get_ivars(child);
int i;
@@ -260,7 +247,7 @@ decode_tuple_manfid(device_t cbdev, device_t child, int id,
static int
decode_tuple_funce(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
struct cardbus_devinfo *dinfo = device_get_ivars(child);
int type, i;
@@ -295,7 +282,7 @@ decode_tuple_funce(device_t cbdev, device_t child, int id,
static int
decode_tuple_bar(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
struct cardbus_devinfo *dinfo = device_get_ivars(child);
int type;
@@ -390,17 +377,17 @@ decode_tuple_bar(device_t cbdev, device_t child, int id,
static int
decode_tuple_unhandled(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
/* Make this message suck less XXX */
printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
- return (-1);
+ return (EINVAL);
}
static int
decode_tuple_end(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
if (cardbus_cis_debug)
printf("CIS reading done\n");
@@ -479,8 +466,9 @@ cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
{
if (res != (struct resource*)~0UL) {
bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
- pci_write_config(child, rid, 0, 4);
- PCI_DISABLE_IO(cbdev, child, SYS_RES_MEMORY);
+ if (rid == PCIM_CIS_ASI_ROM)
+ pci_write_config(child, rid, pci_read_config(child,
+ rid, 4) & ~PCIR_BIOS, 4);
}
}
@@ -488,14 +476,14 @@ static struct resource *
cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
int *rid)
{
- uint32_t testval;
- uint32_t size;
struct resource *res;
uint32_t space;
space = *start & PCIM_CIS_ASI_MASK;
switch (space) {
case PCIM_CIS_ASI_TUPLE:
+ if (cardbus_cis_debug)
+ device_printf(cbdev, "CIS in PCI config space\n");
/* CIS in PCI config space need no initialization */
return ((struct resource*)~0UL);
case PCIM_CIS_ASI_BAR0:
@@ -505,9 +493,13 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
case PCIM_CIS_ASI_BAR4:
case PCIM_CIS_ASI_BAR5:
*rid = PCIR_BAR(space - PCIM_CIS_ASI_BAR0);
+ if (cardbus_cis_debug)
+ device_printf(cbdev, "CIS in BAR %#x\n", *rid);
break;
case PCIM_CIS_ASI_ROM:
*rid = PCIR_BIOS;
+ if (cardbus_cis_debug)
+ device_printf(cbdev, "CIS in option rom\n");
break;
default:
device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
@@ -515,35 +507,19 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
return (NULL);
}
- /* figure out how much space we need */
- pci_write_config(child, *rid, 0xffffffff, 4);
- testval = pci_read_config(child, *rid, 4);
-
- /*
- * This bit has a different meaning depending if we are dealing
- * with a normal BAR or an Option ROM BAR.
- */
- if (((testval & 0x1) == 0x1) && (*rid != PCIR_BIOS)) {
- device_printf(cbdev, "CIS Space is IO, expecting memory.\n");
- return (NULL);
- }
-
- size = CARDBUS_MAPREG_MEM_SIZE(testval);
- /* XXX Is this some kind of hack? */
- if (size < 4096)
- size = 4096;
/* allocate the memory space to read CIS */
- res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, size,
- rman_make_alignment_flags(size) | RF_ACTIVE);
+ res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, 1,
+ rman_make_alignment_flags(4096) | RF_ACTIVE);
if (res == NULL) {
device_printf(cbdev, "Unable to allocate resource "
"to read CIS.\n");
return (NULL);
}
- pci_write_config(child, *rid,
- rman_get_start(res) | ((*rid == PCIR_BIOS) ? PCIM_BIOS_ENABLE : 0),
- 4);
PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY);
+ pci_write_config(child, *rid, rman_get_start(res), 4);
+ if (*rid == PCIR_BIOS)
+ pci_write_config(child, *rid,
+ rman_get_start(res) | PCIM_BIOS_ENABLE, 4);
/* Flip to the right ROM image if CIS is in ROM */
if (space == PCIM_CIS_ASI_ROM) {
@@ -626,21 +602,21 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
static int
decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *callbacks)
+ struct tuple_callbacks *callbacks, void *argp)
{
int i;
for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
if (tupleid == callbacks[i].id)
return (callbacks[i].func(cbdev, child, tupleid, len,
- tupledata, start, off, &callbacks[i]));
+ tupledata, start, off, &callbacks[i], argp));
}
return (callbacks[i].func(cbdev, child, tupleid, len,
- tupledata, start, off, NULL));
+ tupledata, start, off, NULL, argp));
}
-static int
+int
cardbus_parse_cis(device_t cbdev, device_t child,
- struct tuple_callbacks *callbacks)
+ struct tuple_callbacks *callbacks, void *argp)
{
uint8_t tupledata[MAXTUPLESIZE];
int tupleid;
@@ -656,6 +632,8 @@ cardbus_parse_cis(device_t cbdev, device_t child,
device_printf(cbdev, "CIS pointer is 0!\n");
return (ENXIO);
}
+ if (cardbus_cis_debug)
+ device_printf(cbdev, "CIS pointer is %#x\n", start);
off = 0;
res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
if (res == NULL) {
@@ -664,8 +642,8 @@ cardbus_parse_cis(device_t cbdev, device_t child,
}
do {
- if (0 != cardbus_read_tuple(cbdev, child, res, start, &off,
- &tupleid, &len, tupledata)) {
+ if (cardbus_read_tuple(cbdev, child, res, start, &off,
+ &tupleid, &len, tupledata) != 0) {
device_printf(cbdev, "Failed to read CIS.\n");
cardbus_read_tuple_finish(cbdev, child, rid, res);
return (ENXIO);
@@ -678,7 +656,7 @@ cardbus_parse_cis(device_t cbdev, device_t child,
return (EINVAL);
}
expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
- tupledata, start, &off, callbacks);
+ tupledata, start, &off, callbacks, argp);
if (expect_linktarget != 0) {
device_printf(cbdev, "Parsing failed with %d\n",
expect_linktarget);
@@ -710,7 +688,7 @@ cardbus_do_cis(device_t cbdev, device_t child)
MAKETUPLE(GENERIC, generic),
};
- ret = cardbus_parse_cis(cbdev, child, init_callbacks);
+ ret = cardbus_parse_cis(cbdev, child, init_callbacks, NULL);
if (ret < 0)
return (ret);
return 0;
diff --git a/sys/dev/cardbus/cardbus_device.c b/sys/dev/cardbus/cardbus_device.c
new file mode 100644
index 0000000..c03a18a
--- /dev/null
+++ b/sys/dev/cardbus/cardbus_device.c
@@ -0,0 +1,180 @@
+/*-
+ * Copyright (c) 2005, M. Warner Losh
+ * 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 unmodified, 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 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 AUTHOR 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <sys/pciio.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pci_private.h>
+
+#include <dev/cardbus/cardbusreg.h>
+#include <dev/cardbus/cardbusvar.h>
+#include <dev/cardbus/cardbus_cis.h>
+#include <dev/pccard/pccard_cis.h>
+
+static d_open_t cardbus_open;
+static d_close_t cardbus_close;
+static d_read_t cardbus_read;
+static d_ioctl_t cardbus_ioctl;
+
+static struct cdevsw cardbus_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = cardbus_open,
+ .d_close = cardbus_close,
+ .d_read = cardbus_read,
+ .d_ioctl = cardbus_ioctl,
+ .d_name = "cardbus"
+};
+
+int
+cardbus_device_create(struct cardbus_softc *sc)
+{
+ uint32_t minor;
+
+ minor = device_get_unit(sc->sc_dev) << 16;
+ sc->sc_cisdev = make_dev(&cardbus_cdevsw, minor, 0, 0, 0666,
+ "cardbus%u.cis", device_get_unit(sc->sc_dev));
+ sc->sc_cisdev->si_drv1 = sc;
+ return (0);
+}
+
+int
+cardbus_device_destroy(struct cardbus_softc *sc)
+{
+ if (sc->sc_cisdev)
+ destroy_dev(sc->sc_cisdev);
+ return (0);
+}
+
+static int
+cardbus_build_cis(device_t cbdev, device_t child, int id,
+ int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
+ struct tuple_callbacks *info, void *argp)
+{
+ struct cis_buffer *cis;
+ int i;
+
+ cis = (struct cis_buffer *)argp;
+ /*
+ * CISTPL_END is a special case, it has no length field.
+ */
+ if (id == CISTPL_END) {
+ if (cis->len + 1 > sizeof(cis->buffer))
+ return (ENOSPC);
+ cis->buffer[cis->len++] = id;
+ return (0);
+ }
+ if (cis->len + 2 + len > sizeof(cis->buffer))
+ return (ENOSPC);
+ cis->buffer[cis->len++] = id;
+ cis->buffer[cis->len++] = len;
+ for (i = 0; i < len; i++)
+ cis->buffer[cis->len++] = tupledata[i];
+ return (0);
+}
+
+static int
+cardbus_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ device_t parent, child;
+ device_t *kids;
+ int cnt, err;
+ struct cardbus_softc *sc;
+ struct tuple_callbacks cb[] = {
+ {CISTPL_GENERIC, "GENERIC", cardbus_build_cis}
+ };
+
+ sc = dev->si_drv1;
+ if (sc->sc_cis_open)
+ return (EBUSY);
+ parent = sc->sc_dev;
+ err = device_get_children(parent, &kids, &cnt);
+ if (err)
+ return err;
+ if (cnt == 0) {
+ free(kids, M_TEMP);
+ sc->sc_cis_open++;
+ sc->sc_cis = NULL;
+ return (0);
+ }
+ child = kids[0];
+ free(kids, M_TEMP);
+ sc->sc_cis = malloc(sizeof(*sc->sc_cis), M_TEMP, M_ZERO | M_WAITOK);
+ err = cardbus_parse_cis(parent, child, cb, sc->sc_cis);
+ if (err) {
+ free(sc->sc_cis, M_TEMP);
+ sc->sc_cis = NULL;
+ return (err);
+ }
+ sc->sc_cis_open++;
+ return (0);
+}
+
+static int
+cardbus_close(struct cdev *dev, int fflags, int devtype, struct thread *td)
+{
+ struct cardbus_softc *sc;
+
+ sc = dev->si_drv1;
+ free(sc->sc_cis, M_TEMP);
+ sc->sc_cis = NULL;
+ sc->sc_cis_open = 0;
+ return (0);
+}
+
+static int
+cardbus_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
+ struct thread *td)
+{
+ return (ENOTTY);
+}
+
+static int
+cardbus_read(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ struct cardbus_softc *sc;
+
+ sc = dev->si_drv1;
+ /* EOF */
+ if (sc->sc_cis == NULL || uio->uio_offset > sc->sc_cis->len)
+ return (0);
+ return (uiomove(sc->sc_cis->buffer + uio->uio_offset,
+ MIN(uio->uio_resid, sc->sc_cis->len - uio->uio_offset), uio));
+}
diff --git a/sys/dev/cardbus/cardbusvar.h b/sys/dev/cardbus/cardbusvar.h
index edb98bb..4cbc3c4 100644
--- a/sys/dev/cardbus/cardbusvar.h
+++ b/sys/dev/cardbus/cardbusvar.h
@@ -46,3 +46,35 @@ struct cardbus_devinfo
} funce;
uint32_t fepresent; /* bit mask of funce values present */
};
+
+struct cis_buffer
+{
+ size_t len; /* Actual length of the CIS */
+ uint8_t buffer[2040]; /* small enough to be 2k */
+};
+
+struct cardbus_softc
+{
+ /* XXX need mutex XXX */
+ device_t sc_dev;
+ struct cdev *sc_cisdev;
+ struct cis_buffer *sc_cis;
+ int sc_cis_open;
+};
+
+struct tuple_callbacks;
+
+typedef int (tuple_cb) (device_t cbdev, device_t child, int id, int len,
+ uint8_t *tupledata, uint32_t start, uint32_t *off,
+ struct tuple_callbacks *info, void *);
+
+struct tuple_callbacks {
+ int id;
+ char *name;
+ tuple_cb *func;
+};
+
+int cardbus_device_create(struct cardbus_softc *);
+int cardbus_device_destroy(struct cardbus_softc *);
+int cardbus_parse_cis(device_t cbdev, device_t child,
+ struct tuple_callbacks *callbacks, void *);
OpenPOWER on IntegriCloud