diff options
author | imp <imp@FreeBSD.org> | 2008-11-17 01:32:29 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2008-11-17 01:32:29 +0000 |
commit | 1f631eadf5d95ca7f65c5126fdcd3a117cbf9f5e (patch) | |
tree | 1732a330158d4708b5d48469fed6343f06f2a60d /sys/dev | |
parent | 2f08b43b9be491568cc2a93554372b16614e3a7a (diff) | |
download | FreeBSD-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.c | 12 | ||||
-rw-r--r-- | sys/dev/cardbus/cardbus_cis.c | 1 | ||||
-rw-r--r-- | sys/dev/cardbus/cardbus_device.c | 87 | ||||
-rw-r--r-- | sys/dev/cardbus/cardbusvar.h | 41 |
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 *); |