summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2008-11-17 01:32:29 +0000
committerimp <imp@FreeBSD.org>2008-11-17 01:32:29 +0000
commit1f631eadf5d95ca7f65c5126fdcd3a117cbf9f5e (patch)
tree1732a330158d4708b5d48469fed6343f06f2a60d /sys/dev
parent2f08b43b9be491568cc2a93554372b16614e3a7a (diff)
downloadFreeBSD-src-1f631eadf5d95ca7f65c5126fdcd3a117cbf9f5e.zip
FreeBSD-src-1f631eadf5d95ca7f65c5126fdcd3a117cbf9f5e.tar.gz
Overhaul of CIS parsing, next step: keep a cached copy of the CIS,
read before we configure the card, so we can implement /dev/cardbus*.cis. Also, do this on a per-child basis, so we now have a different name than before. I think i'll have to fix that for some legacy tools to keep working. I can now do a dumpcis on my running atheros card and have it still work!
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/cardbus/cardbus.c12
-rw-r--r--sys/dev/cardbus/cardbus_cis.c1
-rw-r--r--sys/dev/cardbus/cardbus_device.c87
-rw-r--r--sys/dev/cardbus/cardbusvar.h41
4 files changed, 68 insertions, 73 deletions
diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c
index e7fdcad..8d9a72f 100644
--- a/sys/dev/cardbus/cardbus.c
+++ b/sys/dev/cardbus/cardbus.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003 M. Warner Losh. All Rights Reserved.
+ * Copyright (c) 2003-2008 M. Warner Losh. All Rights Reserved.
* Copyright (c) 2000,2001 Jonathan Chen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -99,20 +99,18 @@ cardbus_probe(device_t cbdev)
static int
cardbus_attach(device_t cbdev)
{
- struct cardbus_softc *sc = device_get_softc(cbdev);
+ struct cardbus_softc *sc;
+ 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);
}
@@ -165,7 +163,9 @@ cardbus_attach_card(device_t cbdev)
int bus, domain, slot, func;
int cardattached = 0;
int cardbusfunchigh = 0;
+ struct cardbus_softc *sc;
+ sc = device_get_softc(cbdev);
cardbus_detach_card(cbdev); /* detach existing cards */
POWER_ENABLE_SOCKET(brdev, cbdev);
domain = pcib_get_domain(cbdev);
@@ -192,6 +192,7 @@ cardbus_attach_card(device_t cbdev)
dinfo->pci.cfg.dev = child;
resource_list_init(&dinfo->pci.resources);
device_set_ivars(child, dinfo);
+ cardbus_device_create(sc, dinfo, cbdev, child);
if (cardbus_do_cis(cbdev, child) != 0)
DEVPRINTF((cbdev, "Warning: Bogus CIS ignored\n"));
pci_cfg_save(dinfo->pci.cfg.dev, &dinfo->pci, 0);
@@ -235,6 +236,7 @@ cardbus_detach_card(device_t cbdev)
if (status == DS_ATTACHED || status == DS_BUSY)
device_detach(devlist[tmp]);
cardbus_release_all_resources(cbdev, dinfo);
+ cardbus_device_destroy(dinfo);
device_delete_child(cbdev, devlist[tmp]);
pci_freecfg((struct pci_devinfo *)dinfo);
}
diff --git a/sys/dev/cardbus/cardbus_cis.c b/sys/dev/cardbus/cardbus_cis.c
index 9fe7477..2f68003 100644
--- a/sys/dev/cardbus/cardbus_cis.c
+++ b/sys/dev/cardbus/cardbus_cis.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2005-2008, M. Warner Losh
* Copyright (c) 2000,2001 Jonathan Chen.
* All rights reserved.
*
diff --git a/sys/dev/cardbus/cardbus_device.c b/sys/dev/cardbus/cardbus_device.c
index a409e0f..513caba 100644
--- a/sys/dev/cardbus/cardbus_device.c
+++ b/sys/dev/cardbus/cardbus_device.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005, M. Warner Losh
+ * Copyright (c) 2005-2008, M. Warner Losh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,26 +63,6 @@ static struct cdevsw cardbus_cdevsw = {
.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,
@@ -115,7 +95,8 @@ cardbus_build_cis(device_t cbdev, device_t child, int id,
}
static int
-cardbus_device_buffer_cis(device_t parent, device_t child)
+cardbus_device_buffer_cis(device_t parent, device_t child,
+ struct cis_buffer *cbp)
{
struct cardbus_softc *sc;
struct tuple_callbacks cb[] = {
@@ -123,46 +104,44 @@ cardbus_device_buffer_cis(device_t parent, device_t child)
};
sc = device_get_softc(parent);
- return (cardbus_parse_cis(parent, child, cb, &sc->sc_cis));
+ return (cardbus_parse_cis(parent, child, cb, cbp));
+}
+
+int
+cardbus_device_create(struct cardbus_softc *sc, struct cardbus_devinfo *devi,
+ device_t parent, device_t child)
+{
+ uint32_t minor;
+
+ cardbus_device_buffer_cis(parent, child, &devi->sc_cis);
+ minor = (device_get_unit(sc->sc_dev) << 8) + devi->pci.cfg.func;
+ devi->sc_cisdev = make_dev(&cardbus_cdevsw, minor, 0, 0, 0666,
+ "cardbus%d.%d.cis", device_get_unit(sc->sc_dev),
+ devi->pci.cfg.func);
+ /* XXX need cardbus%d.cis compat layer here ? */
+ devi->sc_cisdev->si_drv1 = devi;
+ return (0);
+}
+
+int
+cardbus_device_destroy(struct cardbus_devinfo *devi)
+{
+ if (devi->sc_cisdev)
+ destroy_dev(devi->sc_cisdev);
+ 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;
- 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;
- sc->sc_cis.len = 0;
- if (cnt == 0) {
- free(kids, M_TEMP);
- sc->sc_cis_open++;
- return (0);
- }
- child = kids[0];
- free(kids, M_TEMP);
- err = cardbus_device_buffer_cis(parent, child);
- if (err)
- 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;
- sc->sc_cis_open = 0;
return (0);
}
@@ -176,12 +155,12 @@ cardbus_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
static int
cardbus_read(struct cdev *dev, struct uio *uio, int ioflag)
{
- struct cardbus_softc *sc;
+ struct cardbus_devinfo *devi;
- sc = dev->si_drv1;
+ devi = dev->si_drv1;
/* EOF */
- if (uio->uio_offset >= sc->sc_cis.len)
+ if (uio->uio_offset >= devi->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));
+ return (uiomove(devi->sc_cis.buffer + uio->uio_offset,
+ MIN(uio->uio_resid, devi->sc_cis.len - uio->uio_offset), uio));
}
diff --git a/sys/dev/cardbus/cardbusvar.h b/sys/dev/cardbus/cardbusvar.h
index ca778c2..6264f69 100644
--- a/sys/dev/cardbus/cardbusvar.h
+++ b/sys/dev/cardbus/cardbusvar.h
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2008, M. Warner Losh
* Copyright (c) 2000,2001 Jonathan Chen.
* All rights reserved.
*
@@ -29,6 +30,21 @@
/*
* Structure definitions for the Cardbus Bus driver
*/
+
+/*
+ * Static copy of the CIS buffer. Technically, you aren't supposed
+ * to do this. In practice, however, it works well.
+ */
+struct cis_buffer
+{
+ size_t len; /* Actual length of the CIS */
+ uint8_t buffer[2040]; /* small enough to be 2k */
+};
+
+/*
+ * Per child information for the PCI device. Cardbus layers on some
+ * additional data.
+ */
struct cardbus_devinfo
{
struct pci_devinfo pci;
@@ -43,36 +59,33 @@ struct cardbus_devinfo
} lan;
} funce;
uint32_t fepresent; /* bit mask of funce values present */
+ struct cdev *sc_cisdev;
+ struct cis_buffer sc_cis;
};
-struct cis_buffer
-{
- size_t len; /* Actual length of the CIS */
- uint8_t buffer[2040]; /* small enough to be 2k */
-};
-
+/*
+ * Per cardbus soft info. Not sure why we even keep this around...
+ */
struct cardbus_softc
{
device_t sc_dev;
- /* The following fields should in be in struct cardbus_devinfo */
- struct cdev *sc_cisdev;
- struct cis_buffer sc_cis;
- int sc_cis_open;
};
+/*
+ * Per node callback structures.
+ */
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_device_create(struct cardbus_softc *sc,
+ struct cardbus_devinfo *devi, device_t parent, device_t child);
+int cardbus_device_destroy(struct cardbus_devinfo *devi);
int cardbus_parse_cis(device_t cbdev, device_t child,
struct tuple_callbacks *callbacks, void *);
OpenPOWER on IntegriCloud