diff options
author | jon <jon@FreeBSD.org> | 2001-01-06 18:04:55 +0000 |
---|---|---|
committer | jon <jon@FreeBSD.org> | 2001-01-06 18:04:55 +0000 |
commit | e564c617f8aadbc77f1edc9eddeb5206cc9fb74c (patch) | |
tree | 33661c6ea35ebf2bdf7d737967b65b1ea6e1b1fa /sys/dev/cardbus | |
parent | 56e99b7d35d909eaef84dafc091867116a08e54f (diff) | |
download | FreeBSD-src-e564c617f8aadbc77f1edc9eddeb5206cc9fb74c.zip FreeBSD-src-e564c617f8aadbc77f1edc9eddeb5206cc9fb74c.tar.gz |
* Better kld support in pccbb/cardbus
- pccbb no longer needs to remember whether a card is inserted.
- pccbb reissues insertion on load of cardbus/pccard modules.
- got rid of unnecessary delays in power functions.
- Cardbus children are no longer deleted if probe/attach fails.
- non-attached child devices are reprobed at driver_added.
* CARD interface to read CIS
- added card_cis_read/card_cis_free interface to read arbitrary CIS
data. This currently is only implemented in cardbus.
* pccard begins to work
- pccard can now use higher memory space (and uses it by default).
- set_memory_offset interface changed.
- fixed ccr access, which was broken at multiple locations.
- implement an interrupt handler - pccard can now share interrupts.
- resource alloc/release/activate/deactivate functions gutted: some
resources are allocated by the bridge before the child device is
probed or attached. Thus the resource "belongs" to the bridge, and
the pccard_*_resource functions need to fudge the owner/rid.
- changed some error conditions to panics to speed debugging.
* Mutex fix - Giant is entered at the beginning of thread
Diffstat (limited to 'sys/dev/cardbus')
-rw-r--r-- | sys/dev/cardbus/cardbus.c | 86 | ||||
-rw-r--r-- | sys/dev/cardbus/cardbus_cis.c | 241 | ||||
-rw-r--r-- | sys/dev/cardbus/cardbus_cis.h | 7 |
3 files changed, 245 insertions, 89 deletions
diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c index 0e5e7d2..98ed6c0 100644 --- a/sys/dev/cardbus/cardbus.c +++ b/sys/dev/cardbus/cardbus.c @@ -190,8 +190,9 @@ cardbus_attach_card(device_t dev) static int curr_bus_number = 2; /* XXX EVILE BAD (see below) */ int bus, slot, func; - POWER_ENABLE_SOCKET(bdev, dev); + cardbus_detach_card(dev, DETACH_NOWARN); /* detach existing cards */ + POWER_ENABLE_SOCKET(bdev, dev); bus = pcib_get_bus(dev); if (bus == 0) { /* @@ -205,7 +206,6 @@ cardbus_attach_card(device_t dev) pci_write_config (bdev, PCIR_SUBBUS_2, curr_bus_number+2, 1); curr_bus_number += 3; } - for (slot = 0; slot <= CARDBUS_SLOTMAX; slot++) { int cardbusfunchigh = 0; for (func = 0; func <= cardbusfunchigh; func++) { @@ -230,8 +230,6 @@ cardbus_attach_card(device_t dev) if (device_probe_and_attach(dinfo->cfg.dev) != 0) { cardbus_release_all_resources(dinfo->cfg.dev, &dinfo->resources); - device_delete_child(dev, dinfo->cfg.dev); - cardbus_freecfg(dinfo); } else cardattached++; } @@ -253,20 +251,30 @@ cardbus_detach_card(device_t dev, int flags) device_get_children(dev, &devlist, &numdevs); if (numdevs == 0) { - DEVPRINTF((dev, "Detaching card: no cards to detach!\n")); - POWER_DISABLE_SOCKET(device_get_parent(dev), dev); + if (!(flags & DETACH_NOWARN)) { + DEVPRINTF((dev, "Detaching card: no cards to detach!\n")); + POWER_DISABLE_SOCKET(device_get_parent(dev), dev); + } return ENOENT; } for (tmp = 0; tmp < numdevs; tmp++) { struct cardbus_devinfo *dinfo = device_get_ivars(devlist[tmp]); - if (device_detach(dinfo->cfg.dev) == 0 || flags & DETACH_FORCE){ - cardbus_release_all_resources(dinfo->cfg.dev, - &dinfo->resources); + int status = device_get_state(devlist[tmp]); + + if (status == DS_ATTACHED || status == DS_BUSY) { + if (device_detach(dinfo->cfg.dev) == 0 || + flags & DETACH_FORCE){ + cardbus_release_all_resources(dinfo->cfg.dev, + &dinfo->resources); + device_delete_child(dev, devlist[tmp]); + } else { + err++; + } + cardbus_freecfg(dinfo); + } else { device_delete_child(dev, devlist[tmp]); - } else - err++; - cardbus_freecfg(dinfo); + } } if (err == 0) POWER_DISABLE_SOCKET(device_get_parent(dev), dev); @@ -276,19 +284,39 @@ cardbus_detach_card(device_t dev, int flags) static void cardbus_driver_added(device_t dev, driver_t *driver) { - /* - * For this to work, we should: - * 1) power up the slot if it isn't powered. - * (Is this necessary? Can we assume _probe() doesn't need power?) - * 2) probe (we should probe even though we already have child?) - * 3) power up if we haven't done so and probe succeeds - * 4) attach if probe succeeds. - * 5) power down if probe or attach failed, and the slot was powered - * down to begin with. - */ - printf("I see you added a driver that could be a child of cardbus...\n"); - printf("If this is for a cardbus card, please remove and reinsert the card.\n"); - printf("(there is no current support for adding a driver like this)\n"); + int numdevs; + device_t *devlist; + device_t bdev = device_get_parent(dev); + int tmp, cardattached; + + device_get_children(dev, &devlist, &numdevs); + + cardattached = 0; + for (tmp = 0; tmp < numdevs; tmp++) { + if (device_get_state(devlist[tmp]) != DS_NOTPRESENT) + cardattached++; + } + + if (cardattached == 0) + POWER_ENABLE_SOCKET(bdev, dev); + DEVICE_IDENTIFY(driver, dev); + for (tmp = 0; tmp < numdevs; tmp++) { + if (device_get_state(devlist[tmp]) == DS_NOTPRESENT){ + struct cardbus_devinfo *dinfo; + dinfo = device_get_ivars(devlist[tmp]); + resource_list_init(&dinfo->resources); + cardbus_add_resources(dinfo->cfg.dev, &dinfo->cfg); + cardbus_do_cis(dev, dinfo->cfg.dev); + if (device_probe_and_attach(dinfo->cfg.dev) != 0) { + cardbus_release_all_resources(dinfo->cfg.dev, + &dinfo->resources); + } else + cardattached++; + } + } + + if (cardattached == 0) + POWER_DISABLE_SOCKET(bdev, dev); } /************************************************************************/ @@ -344,7 +372,7 @@ cardbus_read_device(device_t pcib, int b, int s, int f) cfg->intline = airq; } } else { - /* + /* * PCI interrupts might be redirected to the * ISA bus according to some MP tables. Use the * same methods as used by the ISA devices @@ -655,7 +683,7 @@ cardbus_alloc_resource(device_t self, device_t child, int type, rle = resource_list_find(rl, type, *rid); if (rle) { if (flags & RF_ACTIVE) { - if (bus_activate_resource(child, type, *rid, + if (bus_activate_resource(child, rle->type, *rid, rle->res)) { return NULL; } @@ -930,6 +958,8 @@ static device_method_t cardbus_methods[] = { /* Card Interface */ DEVMETHOD(card_attach_card, cardbus_attach_card), DEVMETHOD(card_detach_card, cardbus_detach_card), + DEVMETHOD(card_cis_read, cardbus_cis_read), + DEVMETHOD(card_cis_free, cardbus_cis_free), /* Cardbus/PCI interface */ DEVMETHOD(pci_read_config, cardbus_read_config_method), @@ -947,4 +977,6 @@ static driver_t cardbus_driver = { static devclass_t cardbus_devclass; DRIVER_MODULE(cardbus, pccbb, cardbus_driver, cardbus_devclass, 0, 0); +/* MODULE_DEPEND(cardbus, pccbb, 1, 1, 1); +*/ diff --git a/sys/dev/cardbus/cardbus_cis.c b/sys/dev/cardbus/cardbus_cis.c index 2845660..8d2059b 100644 --- a/sys/dev/cardbus/cardbus_cis.c +++ b/sys/dev/cardbus/cardbus_cis.c @@ -37,6 +37,7 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/malloc.h> #include <sys/bus.h> #include <machine/bus.h> @@ -48,6 +49,8 @@ #include <dev/cardbus/cardbusreg.h> #include <dev/cardbus/cardbus_cis.h> +#include "card_if.h" + #if defined CARDBUS_DEBUG #define STATIC #define DPRINTF(a) printf a @@ -63,7 +66,7 @@ static const char rcsid[] = "$FreeBSD$"; #endif -struct tupleinfo; +struct tuple_callbacks; static int cardbus_read_tuple_conf(device_t dev, device_t child, u_int32_t *start, u_int32_t *off, @@ -78,13 +81,19 @@ static int cardbus_read_tuple(device_t dev, device_t child, u_int32_t *start, u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata); static int decode_tuple(device_t dev, device_t child, int tupleid, int len, - u_int8_t *tupledata, u_int32_t *start, u_int32_t *off); + u_int8_t *tupledata, u_int32_t *start, u_int32_t *off, + struct tuple_callbacks *callbacks); +static int cardbus_parse_cis(device_t dev, device_t child, + struct tuple_callbacks *callbacks); -#define DECODE_PROTOTYPE(NAME) static int decode_tuple_ ## NAME \ +#define DECODE_PARAMS \ (device_t dev, device_t child, int id, int len, \ u_int8_t *tupledata, u_int32_t *start, u_int32_t *off, \ - struct tupleinfo *info) + struct tuple_callbacks *info) +#define DECODE_PROTOTYPE(NAME) static int decode_tuple_ ## NAME DECODE_PARAMS DECODE_PROTOTYPE(generic); +DECODE_PROTOTYPE(nothing); +DECODE_PROTOTYPE(copy); DECODE_PROTOTYPE(bar); DECODE_PROTOTYPE(linktarget); DECODE_PROTOTYPE(vers_1); @@ -94,54 +103,12 @@ DECODE_PROTOTYPE(funce); DECODE_PROTOTYPE(end); DECODE_PROTOTYPE(unhandled); -static struct tupleinfo { - u_int8_t id; +struct tuple_callbacks { + int id; char* name; - int (*func)(device_t dev, device_t child, int id, int len, - u_int8_t *tupledata, u_int32_t *start, u_int32_t *off, - struct tupleinfo *info); -} tupleinfo[] = { -#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC } - MAKETUPLE(NULL, generic), - MAKETUPLE(DEVICE, generic), - MAKETUPLE(LONG_LINK_CB, unhandled), - MAKETUPLE(INDIRECT, unhandled), - MAKETUPLE(CONFIG_CB, generic), - MAKETUPLE(CFTABLE_ENTRY_CB, generic), - MAKETUPLE(LONGLINK_MFC, unhandled), - MAKETUPLE(BAR, bar), - MAKETUPLE(PWR_MGMNT, generic), - MAKETUPLE(EXTDEVICE, generic), - MAKETUPLE(CHECKSUM, generic), - MAKETUPLE(LONGLINK_A, unhandled), - MAKETUPLE(LONGLINK_C, unhandled), - MAKETUPLE(LINKTARGET, linktarget), - MAKETUPLE(NO_LINK, generic), - MAKETUPLE(VERS_1, vers_1), - MAKETUPLE(ALTSTR, generic), - MAKETUPLE(DEVICE_A, generic), - MAKETUPLE(JEDEC_C, generic), - MAKETUPLE(JEDEC_A, generic), - MAKETUPLE(CONFIG, generic), - MAKETUPLE(CFTABLE_ENTRY, generic), - MAKETUPLE(DEVICE_OC, generic), - MAKETUPLE(DEVICE_OA, generic), - MAKETUPLE(DEVICE_GEO, generic), - MAKETUPLE(DEVICE_GEO_A, generic), - MAKETUPLE(MANFID, manfid), - MAKETUPLE(FUNCID, funcid), - MAKETUPLE(FUNCE, funce), - MAKETUPLE(SWIL, generic), - MAKETUPLE(VERS_2, generic), - MAKETUPLE(FORMAT, generic), - MAKETUPLE(GEOMETRY, generic), - MAKETUPLE(BYTEORDER, generic), - MAKETUPLE(DATE, generic), - MAKETUPLE(BATTERY, generic), - MAKETUPLE(ORG, generic), - MAKETUPLE(END, end), -#undef MAKETUPLE + int (*func) DECODE_PARAMS; }; +#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC } static char* funcnames[] = { "Multi-Functioned", @@ -156,6 +123,9 @@ static char* funcnames[] = { "Security" }; +static struct cis_tupleinfo* cisread_buf; +static int ncisread_buf; + DECODE_PROTOTYPE(generic) { #ifdef CARDBUS_DEBUG @@ -176,6 +146,32 @@ DECODE_PROTOTYPE(generic) return 0; } +DECODE_PROTOTYPE(nothing) +{ + return 0; +} + +DECODE_PROTOTYPE(copy) +{ + struct cis_tupleinfo* tmpbuf; + + tmpbuf = malloc(sizeof(struct cis_tupleinfo)*(ncisread_buf+1), + M_DEVBUF, M_WAITOK); + if (ncisread_buf > 0) { + memcpy(tmpbuf, cisread_buf, + sizeof(struct cis_tupleinfo)*ncisread_buf); + free(cisread_buf, M_DEVBUF); + } + cisread_buf = tmpbuf; + + cisread_buf[ncisread_buf].id = id; + cisread_buf[ncisread_buf].len = len; + cisread_buf[ncisread_buf].data = malloc(len, M_DEVBUF, M_WAITOK); + memcpy (cisread_buf[ncisread_buf].data, tupledata, len); + ncisread_buf++; + return 0; +} + DECODE_PROTOTYPE(linktarget) { #ifdef CARDBUS_DEBUG @@ -277,7 +273,7 @@ DECODE_PROTOTYPE(bar) if (bar < 0 || bar > 5 || (type == SYS_RES_IOPORT && bar == 5)) { device_printf(dev, "Invalid BAR number: %02x(%02x)\n", reg, bar); - return EINVAL; + return 0; } bar = CARDBUS_BASE0_REG + bar * 4; DEVPRINTF((dev, "Opening BAR: type=%s, bar=%02x, len=%04x\n", @@ -299,6 +295,7 @@ DECODE_PROTOTYPE(unhandled) DECODE_PROTOTYPE(end) { + printf("CIS reading done\n"); return 0; } @@ -451,27 +448,29 @@ cardbus_read_tuple(device_t dev, device_t child, u_int32_t *start, static int decode_tuple(device_t dev, device_t child, int tupleid, int len, - u_int8_t *tupledata, u_int32_t *start, u_int32_t *off) + u_int8_t *tupledata, u_int32_t *start, u_int32_t *off, + struct tuple_callbacks *callbacks) { int i; - int numtupleids = sizeof(tupleinfo)/sizeof(tupleinfo[0]); - for (i = 0; i < numtupleids; i++) { - if (tupleid == tupleinfo[i].id) - return tupleinfo[i].func(dev, child, tupleid, len, + for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) { + if (tupleid == callbacks[i].id) + return callbacks[i].func(dev, child, tupleid, len, tupledata, start, off, - &tupleinfo[i]); + &callbacks[i]); } if (tupleid < CISTPL_CUSTOMSTART) { device_printf(dev, "Undefined tuple encountered, CIS parsing terminated\n"); return EINVAL; } - return decode_tuple_generic(dev, child, tupleid, len, tupledata, - start, off, NULL); + return callbacks[i].func(dev, child, tupleid, len, + tupledata, start, off, + NULL); } -int -cardbus_do_cis(device_t dev, device_t child) +static int +cardbus_parse_cis(device_t dev, device_t child, + struct tuple_callbacks *callbacks) { u_int8_t tupledata[MAXTUPLESIZE]; int tupleid; @@ -493,10 +492,128 @@ cardbus_do_cis(device_t dev, device_t child) return EINVAL; } expect_linktarget = decode_tuple(dev, child, tupleid, len, - tupledata, &start, &off); + tupledata, &start, &off, + callbacks); if (expect_linktarget != 0) return expect_linktarget; } while (tupleid != CISTPL_END); return 0; } +int +cardbus_cis_read(device_t dev, device_t child, u_int8_t id, + struct cis_tupleinfo** buff, int* nret) +{ + struct tuple_callbacks cisread_callbacks[] = { + MAKETUPLE(NULL, nothing), + /* first entry will be overwritten */ + MAKETUPLE(NULL, nothing), + MAKETUPLE(DEVICE, nothing), + MAKETUPLE(LONG_LINK_CB, unhandled), + MAKETUPLE(INDIRECT, unhandled), + MAKETUPLE(CONFIG_CB, nothing), + MAKETUPLE(CFTABLE_ENTRY_CB, nothing), + MAKETUPLE(LONGLINK_MFC, unhandled), + MAKETUPLE(BAR, nothing), + MAKETUPLE(PWR_MGMNT, nothing), + MAKETUPLE(EXTDEVICE, nothing), + MAKETUPLE(CHECKSUM, nothing), + MAKETUPLE(LONGLINK_A, unhandled), + MAKETUPLE(LONGLINK_C, unhandled), + MAKETUPLE(LINKTARGET, nothing), + MAKETUPLE(NO_LINK, nothing), + MAKETUPLE(VERS_1, nothing), + MAKETUPLE(ALTSTR, nothing), + MAKETUPLE(DEVICE_A, nothing), + MAKETUPLE(JEDEC_C, nothing), + MAKETUPLE(JEDEC_A, nothing), + MAKETUPLE(CONFIG, nothing), + MAKETUPLE(CFTABLE_ENTRY, nothing), + MAKETUPLE(DEVICE_OC, nothing), + MAKETUPLE(DEVICE_OA, nothing), + MAKETUPLE(DEVICE_GEO, nothing), + MAKETUPLE(DEVICE_GEO_A, nothing), + MAKETUPLE(MANFID, nothing), + MAKETUPLE(FUNCID, nothing), + MAKETUPLE(FUNCE, nothing), + MAKETUPLE(SWIL, nothing), + MAKETUPLE(VERS_2, nothing), + MAKETUPLE(FORMAT, nothing), + MAKETUPLE(GEOMETRY, nothing), + MAKETUPLE(BYTEORDER, nothing), + MAKETUPLE(DATE, nothing), + MAKETUPLE(BATTERY, nothing), + MAKETUPLE(ORG, nothing), + MAKETUPLE(END, end), + MAKETUPLE(GENERIC, nothing), + }; + int ret; + + cisread_callbacks[0].id = id; + cisread_callbacks[0].name = "COPY"; + cisread_callbacks[0].func = decode_tuple_copy; + ncisread_buf = 0; + cisread_buf = NULL; + ret = cardbus_parse_cis(dev, child, cisread_callbacks); + + *buff = cisread_buf; + *nret = ncisread_buf; + return ret; +} + +void +cardbus_cis_free(device_t dev, struct cis_tupleinfo *buff, int* nret) +{ + int i; + for (i = 0; i < nret; i++) + free(buff[i].data, M_DEVBUF); + if (nret > 0) + free(buff, M_DEVBUF); +} + +int +cardbus_do_cis(device_t dev, device_t child) +{ + struct tuple_callbacks init_callbacks[] = { + MAKETUPLE(NULL, generic), + MAKETUPLE(DEVICE, generic), + MAKETUPLE(LONG_LINK_CB, unhandled), + MAKETUPLE(INDIRECT, unhandled), + MAKETUPLE(CONFIG_CB, generic), + MAKETUPLE(CFTABLE_ENTRY_CB, generic), + MAKETUPLE(LONGLINK_MFC, unhandled), + MAKETUPLE(BAR, bar), + MAKETUPLE(PWR_MGMNT, generic), + MAKETUPLE(EXTDEVICE, generic), + MAKETUPLE(CHECKSUM, generic), + MAKETUPLE(LONGLINK_A, unhandled), + MAKETUPLE(LONGLINK_C, unhandled), + MAKETUPLE(LINKTARGET, linktarget), + MAKETUPLE(NO_LINK, generic), + MAKETUPLE(VERS_1, vers_1), + MAKETUPLE(ALTSTR, generic), + MAKETUPLE(DEVICE_A, generic), + MAKETUPLE(JEDEC_C, generic), + MAKETUPLE(JEDEC_A, generic), + MAKETUPLE(CONFIG, generic), + MAKETUPLE(CFTABLE_ENTRY, generic), + MAKETUPLE(DEVICE_OC, generic), + MAKETUPLE(DEVICE_OA, generic), + MAKETUPLE(DEVICE_GEO, generic), + MAKETUPLE(DEVICE_GEO_A, generic), + MAKETUPLE(MANFID, manfid), + MAKETUPLE(FUNCID, funcid), + MAKETUPLE(FUNCE, funce), + MAKETUPLE(SWIL, generic), + MAKETUPLE(VERS_2, generic), + MAKETUPLE(FORMAT, generic), + MAKETUPLE(GEOMETRY, generic), + MAKETUPLE(BYTEORDER, generic), + MAKETUPLE(DATE, generic), + MAKETUPLE(BATTERY, generic), + MAKETUPLE(ORG, generic), + MAKETUPLE(END, end), + MAKETUPLE(GENERIC, generic), + }; + return cardbus_parse_cis(dev, child, init_callbacks); +} diff --git a/sys/dev/cardbus/cardbus_cis.h b/sys/dev/cardbus/cardbus_cis.h index 9268582..f884eef 100644 --- a/sys/dev/cardbus/cardbus_cis.h +++ b/sys/dev/cardbus/cardbus_cis.h @@ -32,7 +32,12 @@ * Cardbus CIS definitions */ +struct cis_tupleinfo; + int cardbus_do_cis(device_t dev, device_t child); +int cardbus_cis_read(device_t dev, device_t child, u_int8_t id, + struct cis_tupleinfo** buff, int* nret); +void cardbus_cis_free(device_t dev, struct cis_tupleinfo *buff, int* nret); #define MAXTUPLESIZE 0x400 @@ -78,6 +83,8 @@ int cardbus_do_cis(device_t dev, device_t child); #define CISTPL_CUSTOMSTART 0x80 #define CISTPL_END 0xFF +#define CISTPL_GENERIC -1 /* catchall */ + /* BAR */ #define TPL_BAR_REG_ASI_MASK 0x07 #define TPL_BAR_REG_AS 0x10 |