From e564c617f8aadbc77f1edc9eddeb5206cc9fb74c Mon Sep 17 00:00:00 2001 From: jon Date: Sat, 6 Jan 2001 18:04:55 +0000 Subject: * 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 --- sys/dev/cardbus/cardbus.c | 86 +++++++++----- sys/dev/cardbus/cardbus_cis.c | 241 ++++++++++++++++++++++++++++---------- sys/dev/cardbus/cardbus_cis.h | 7 ++ sys/dev/pccard/card_if.m | 54 ++++++++- sys/dev/pccard/pccard.c | 263 ++++++++++++++++++++++++++++++++---------- sys/dev/pccard/pccardvar.h | 4 + sys/dev/pccbb/pccbb.c | 146 ++++++++++++++--------- sys/dev/pccbb/pccbbvar.h | 3 +- 8 files changed, 597 insertions(+), 207 deletions(-) (limited to 'sys/dev') 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 #include #include +#include #include #include @@ -48,6 +49,8 @@ #include #include +#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 diff --git a/sys/dev/pccard/card_if.m b/sys/dev/pccard/card_if.m index 47376c7..f3813ee 100644 --- a/sys/dev/pccard/card_if.m +++ b/sys/dev/pccard/card_if.m @@ -63,7 +63,8 @@ METHOD int set_memory_offset { device_t dev; device_t child; int rid; - u_int32_t offset; + u_int32_t cardaddr; + u_int32_t *offsetp; } METHOD int get_memory_offset { @@ -90,6 +91,7 @@ METHOD int detach_card { HEADER { #define DETACH_FORCE 0x01 + #define DETACH_NOWARN 0x02 } # @@ -163,3 +165,53 @@ METHOD int compat_attach { METHOD int compat_match { device_t dev; } + +# +# Method for devices to ask its CIS-enabled parent bus for CIS info. +# Device driver requests all tuples if type 'id', the routine places +# 'nret' number of tuples in 'buff'. Returns 0 if all tuples processed, +# or an error code if processing was aborted. +# Users of this method will be responsible for freeing the memory allocated +# by calling the cis_free method. +# + +HEADER { + struct cis_tupleinfo { + u_int8_t id; + int len; + char* data; + }; +}; + +CODE { + static int + null_cis_read(device_t dev, device_t child, u_int8_t id, + struct cis_tupleinfo **buff, int* nret) + { + *nret = 0; + *buff = NULL; + return ENXIO; + } + static void + null_cis_free(device_t dev, struct cis_tupleinfo *buff, int* nret) + { + return; + } +}; + + +METHOD int cis_read { + device_t dev; + device_t child; + u_int8_t id; + struct cis_tupleinfo **buff; + int* nret; +} DEFAULT null_cis_read; + +METHOD int cis_free { + device_t dev; + struct cis_tupleinfo *buff; + int nret; +} DEFAULT null_cis_free; + + diff --git a/sys/dev/pccard/pccard.c b/sys/dev/pccard/pccard.c index 03a0cce..6bbbd12 100644 --- a/sys/dev/pccard/pccard.c +++ b/sys/dev/pccard/pccard.c @@ -103,6 +103,7 @@ pccard_attach_card(device_t dev) device_t child; int attached; + sc->intr_handler_count = 0; /* * this is here so that when socket_enable calls gettype, trt happens */ @@ -122,10 +123,14 @@ pccard_attach_card(device_t dev) * the cis. */ - if (sc->card.error) + if (sc->card.error) { + device_printf (dev, "CARD ERROR!\n"); return (1); - if (STAILQ_EMPTY(&sc->card.pf_head)) + } + if (STAILQ_EMPTY(&sc->card.pf_head)) { + device_printf (dev, "Card has no functions!\n"); return (1); + } if (1) pccard_print_cis(dev); @@ -228,7 +233,7 @@ pccard_product_lookup(device_t dev, const struct pccard_product *tab, #ifdef DIAGNOSTIC if (sizeof *ent > ent_size) - panic("pccard_product_lookup: bogus ent_size %ld", + panic("pccard_product_lookup: bogus ent_size %ld", (long) ent_size); #endif if (pccard_get_vendor(dev, &vendor)) @@ -241,7 +246,7 @@ pccard_product_lookup(device_t dev, const struct pccard_product *tab, return (NULL); if (pccard_get_product_str(dev, &prodstr)) return (NULL); - for (ent = tab; ent->pp_name != NULL; + for (ent = tab; ent->pp_name != NULL; ent = (const struct pccard_product *) ((const char *) ent + ent_size)) { matches = 1; @@ -253,10 +258,10 @@ pccard_product_lookup(device_t dev, const struct pccard_product *tab, matches = 0; if (matches && fcn != ent->pp_expfunc) matches = 0; - if (matches && ent->pp_vendor_str && + if (matches && ent->pp_vendor_str && strcmp(ent->pp_vendor_str, vendorstr) != 0) matches = 0; - if (matches && ent->pp_product_str && + if (matches && ent->pp_product_str && strcmp(ent->pp_product_str, prodstr) != 0) matches = 0; if (matchfn != NULL) @@ -267,7 +272,7 @@ pccard_product_lookup(device_t dev, const struct pccard_product *tab, return (NULL); } -static int +static int pccard_card_gettype(device_t dev, int *type) { struct pccard_softc *sc = PCCARD_SOFTC(dev); @@ -293,7 +298,7 @@ pccard_card_gettype(device_t dev, int *type) * disabled. */ void -pccard_function_init(struct pccard_function *pf) +pccard_function_init(struct pccard_function *pf) { struct pccard_config_entry *cfe; int i; @@ -304,9 +309,10 @@ pccard_function_init(struct pccard_function *pf) int start; int end; - if (pf->pf_flags & PFF_ENABLED) - panic("pccard_function_init: function is enabled"); - + if (pf->pf_flags & PFF_ENABLED) { + printf("pccard_function_init: function is enabled"); + return; + } bus = device_get_parent(pf->dev); /* Remember which configuration entry we are using. */ for (cfe = STAILQ_FIRST(&pf->cfe_head); cfe != NULL; @@ -323,13 +329,17 @@ pccard_function_init(struct pccard_function *pf) cfe->iorid[i] = i; r = cfe->iores[i] = bus_alloc_resource(bus, SYS_RES_IOPORT, &cfe->iorid[i], start, end, - cfe->iospace[i].length, + cfe->iospace[i].length, rman_make_alignment_flags(cfe->iospace[i].length)); if (cfe->iores[i] == 0) goto not_this_one; resource_list_add(rl, SYS_RES_IOPORT, cfe->iorid[i], rman_get_start(r), rman_get_end(r), cfe->iospace[i].length); + { + struct resource_list_entry *rle = resource_list_find(rl, SYS_RES_IOPORT, cfe->iorid[i]); + rle->res = r; + } } if (cfe->num_memspace > 0) { goto not_this_one; @@ -342,6 +352,10 @@ pccard_function_init(struct pccard_function *pf) goto not_this_one; resource_list_add(rl, SYS_RES_IRQ, cfe->irqrid, rman_get_start(r), rman_get_end(r), 1); + { + struct resource_list_entry *rle = resource_list_find(rl, SYS_RES_IRQ, cfe->irqrid); + rle->res = r; + } } /* XXX Don't know how to deal with maxtwins */ /* If we get to here, we've allocated all we need */ @@ -357,7 +371,7 @@ pccard_function_init(struct pccard_function *pf) for (i = 0; i < cfe->num_iospace; i++) { resource_list_delete(rl, SYS_RES_IOPORT, i); if (cfe->iores[i]) - bus_release_resource(bus, SYS_RES_IOPORT, + bus_release_resource(bus, SYS_RES_IOPORT, cfe->iorid[i], cfe->iores[i]); cfe->iores[i] = NULL; } @@ -377,7 +391,6 @@ pccard_function_enable(struct pccard_function *pf) struct pccard_function *tmp; int reg; device_t dev = pf->sc->dev; - if (pf->cfe == NULL) { DEVPRVERBOSE((dev, "No config entry could be allocated.\n")); return ENOMEM; @@ -416,29 +429,27 @@ pccard_function_enable(struct pccard_function *pf) * pf->pf_ccr_offset = (tmp->pf_ccr_offset - * tmp->ccr_base) + pf->ccr_base; */ - pf->pf_ccr_offset = + /* pf->pf_ccr_offset = (tmp->pf_ccr_offset + pf->ccr_base) - - tmp->ccr_base; + tmp->ccr_base; */ pf->pf_ccr_window = tmp->pf_ccr_window; break; } } - if (tmp == NULL) { pf->ccr_rid = 0; pf->ccr_res = bus_alloc_resource(dev, SYS_RES_MEMORY, - &pf->ccr_rid, 0xa0000, 0xdffff, 1 << 10, RF_ACTIVE); - if (!pf->ccr_res) { - DEVPRINTF((dev, "ccr_res == 0\n")); + &pf->ccr_rid, 0, ~0, 1 << 10, RF_ACTIVE); + if (!pf->ccr_res) goto bad; - } + DEVPRINTF((dev, "ccr_res == %lx-%lx, base=%lx\n", rman_get_start(pf->ccr_res), rman_get_end(pf->ccr_res), pf->ccr_base)); CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, pf->ccr_rid, PCCARD_A_MEM_ATTR); - CARD_SET_MEMORY_OFFSET(device_get_parent(dev), dev, - pf->ccr_rid, (pf->ccr_rid >> 10) << 10); + CARD_SET_MEMORY_OFFSET(device_get_parent(dev), dev, + pf->ccr_rid, pf->ccr_base, + &pf->pf_ccr_offset); pf->pf_ccrt = rman_get_bustag(pf->ccr_res); pf->pf_ccrh = rman_get_bushandle(pf->ccr_res); - pf->pf_ccr_offset = rman_get_start(pf->ccr_res); pf->pf_ccr_realsize = 1; } @@ -447,12 +458,12 @@ pccard_function_enable(struct pccard_function *pf) if (pccard_mfc(pf->sc)) { reg |= (PCCARD_CCR_OPTION_FUNC_ENABLE | PCCARD_CCR_OPTION_ADDR_DECODE); - /* + /* * XXX Need to enable PCCARD_CCR_OPTION_IRQ_ENABLE if * XXX we have an interrupt handler, but we don't know that * XXX at this point. */ - reg |= PCCARD_CCR_OPTION_IREQ_ENABLE; +/* reg |= PCCARD_CCR_OPTION_IREQ_ENABLE;*/ } pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg); @@ -487,17 +498,17 @@ pccard_function_enable(struct pccard_function *pf) #ifdef PCCARDDEBUG if (pccard_debug) { STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) { - device_printf(tmp->sc->dev, + device_printf(tmp->sc->dev, "function %d CCR at %d offset %x: " "%x %x %x %x, %x %x %x %x, %x\n", - tmp->number, tmp->pf_ccr_window, + tmp->number, tmp->pf_ccr_window, tmp->pf_ccr_offset, pccard_ccr_read(tmp, 0x00), pccard_ccr_read(tmp, 0x02), pccard_ccr_read(tmp, 0x04), pccard_ccr_read(tmp, 0x06), pccard_ccr_read(tmp, 0x0A), - pccard_ccr_read(tmp, 0x0C), + pccard_ccr_read(tmp, 0x0C), pccard_ccr_read(tmp, 0x0E), pccard_ccr_read(tmp, 0x10), pccard_ccr_read(tmp, 0x12)); @@ -536,6 +547,27 @@ pccard_function_disable(struct pccard_function *pf) return; } + if (pf->intr_handler != NULL) { + pf->intr_handler = NULL; + pf->intr_handler_arg = NULL; + pf->intr_handler_cookie = NULL; + pccard_ccr_write(pf, PCCARD_CCR_OPTION, + pccard_ccr_read(pf, PCCARD_CCR_OPTION) & + ~PCCARD_CCR_OPTION_IREQ_ENABLE); + + if (pf->sc->intr_handler_count == 1) { + struct pccard_ivar *ivar = PCCARD_IVAR(pf->dev); + struct resource_list_entry *rle = NULL; + + pf->sc->intr_handler_count--; + rle = resource_list_find(&ivar->resources, SYS_RES_IRQ, 0); + if (rle == NULL) + panic("No IRQ for pccard?"); + + bus_teardown_intr(dev, rle->res, &pf->sc->intr_handler_count); + } + } + /* * it's possible for different functions' CCRs to be in the same * underlying page. Check for that. Note we mark us as disabled @@ -553,7 +585,7 @@ pccard_function_disable(struct pccard_function *pf) /* Not used by anyone else; unmap the CCR. */ if (tmp == NULL) { - bus_release_resource(dev, SYS_RES_MEMORY, pf->ccr_rid, + bus_release_resource(dev, SYS_RES_MEMORY, pf->ccr_rid, pf->ccr_res); pf->ccr_res = NULL; } @@ -605,7 +637,7 @@ pccard_io_map(struct pccard_function *pf, int width, bus_addr_t offset, ; iosize--; - pccard_ccr_write(pf, PCCARD_CCR_IOBASE0, + pccard_ccr_write(pf, PCCARD_CCR_IOBASE0, pf->pf_mfc_iobase & 0xff); pccard_ccr_write(pf, PCCARD_CCR_IOBASE1, (pf->pf_mfc_iobase >> 8) & 0xff); @@ -728,7 +760,7 @@ pccard_print_child(device_t dev, device_t child) PCCARD_NMEM, "%#lx"); pccard_print_resources(rl, "irq", SYS_RES_IRQ, PCCARD_NIRQ, "%ld"); - pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ, + pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ, "%ld"); retval += printf(" function %d config %d", devi->fcn->number, devi->fcn->cfe->number); @@ -776,7 +808,7 @@ pccard_get_resource(device_t dev, device_t child, int type, int rid, rle = resource_list_find(rl, type, rid); if (!rle) return ENOENT; - + if (startp) *startp = rle->start; if (countp) @@ -803,10 +835,11 @@ pccard_set_res_flags(device_t dev, device_t child, int type, int rid, static int pccard_set_memory_offset(device_t dev, device_t child, int rid, - u_int32_t offset) + u_int32_t offset, u_int32_t *offsetp) + { return CARD_SET_MEMORY_OFFSET(device_get_parent(dev), child, rid, - offset); + offset, offsetp); } static int @@ -866,33 +899,21 @@ static struct resource * pccard_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { - struct pccard_ivar *ivar; - struct pccard_function *pf; - struct resource *r = 0; + struct resource_list_entry *rle = NULL; + + /* XXX: This is an ugly way to fudge the resources. */ if (device_get_parent(child) == dev) { - ivar = PCCARD_IVAR(child); - pf = ivar->fcn; - switch (type) { - case SYS_RES_IRQ: - if (*rid > 0) - return NULL; - r = pf->cfe->irqres; - break; - case SYS_RES_IOPORT: - if (*rid > 3) /* XXX */ - return NULL; - r = pf->cfe->iores[*rid]; - break; - default: - break; - } + struct pccard_ivar *devi = PCCARD_IVAR(child); + struct resource_list *rl = &devi->resources; + + rle = resource_list_find(rl, type, *rid); } - if (r != NULL) { - if (flags & RF_ACTIVE) - bus_generic_activate_resource(dev, child, type, - *rid, r); - return (r); + + if (rle != NULL) { + if (flags & RF_ACTIVE) + bus_activate_resource(dev, type, rle->rid, rle->res); + return (rle->res); } return (bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags)); @@ -902,6 +923,19 @@ static int pccard_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { + struct resource_list_entry *rle = NULL; + + if (device_get_parent(child) == dev) { + struct pccard_ivar *devi = PCCARD_IVAR(child); + struct resource_list *rl = &devi->resources; + + rle = resource_list_find(rl, type, rid); + } + + if (rle != NULL) { + return bus_release_resource(dev, type, rle->rid, rle->res); + } + return bus_generic_release_resource(dev, child, type, rid, r); } @@ -910,6 +944,19 @@ pccard_activate_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { /* XXX need to write to the COR to activate this for mf cards */ + struct resource_list_entry *rle = NULL; + + if (device_get_parent(child) == dev) { + struct pccard_ivar *devi = PCCARD_IVAR(child); + struct resource_list *rl = &devi->resources; + + rle = resource_list_find(rl, type, rid); + } + + if (rle != NULL) { + return (bus_activate_resource(dev, type, rle->rid, rle->res)); + } + return (bus_generic_activate_resource(dev, child, type, rid, r)); } @@ -918,6 +965,19 @@ pccard_deactivate_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { /* XXX need to write to the COR to deactivate this for mf cards */ + struct resource_list_entry *rle = NULL; + + if (device_get_parent(child) == dev) { + struct pccard_ivar *devi = PCCARD_IVAR(child); + struct resource_list *rl = &devi->resources; + + rle = resource_list_find(rl, type, rid); + } + + if (rle != NULL) { + return (bus_deactivate_resource(dev, type, rle->rid, rle->res)); + } + return (bus_generic_deactivate_resource(dev, child, type, rid, r)); } @@ -930,6 +990,85 @@ pccard_child_detached(device_t parent, device_t dev) free(ivar, M_DEVBUF); } +static void +pccard_intr(void *arg) { + struct pccard_function *pf; + STAILQ_FOREACH(pf, &((struct pccard_softc*)arg)->card.pf_head, pf_list) { + if (pf->intr_handler != NULL) { + int reg = pccard_ccr_read(pf, PCCARD_CCR_STATUS); + if (reg & PCCARD_CCR_STATUS_INTR) { + pccard_ccr_write(pf, PCCARD_CCR_STATUS, + reg & ~PCCARD_CCR_STATUS_INTR); + pf->intr_handler(pf->intr_handler_arg); + } + } + } +} + +static int +pccard_setup_intr(device_t dev, device_t child, + struct resource *irq, int flags, + driver_intr_t *intr, void *arg, void **cookiep) +{ + struct pccard_ivar *ivar = PCCARD_IVAR(child); + struct pccard_function *func = ivar->fcn; + struct resource_list_entry *rle = NULL; + struct pccard_softc *sc = device_get_softc(dev); + + if (func->intr_handler != NULL) + panic("Only one interrupt handler per function allowed for pccard\n"); + + rle = resource_list_find(&ivar->resources, SYS_RES_IRQ, 0); + if (rle == NULL || rle->res != irq) + panic("irq in setup_intr does not match allocated irq\n"); + + func->intr_handler = intr; + func->intr_handler_arg = arg; + func->intr_handler_cookie = cookiep; + pccard_ccr_write(func, PCCARD_CCR_OPTION, + pccard_ccr_read(func, PCCARD_CCR_OPTION) | + PCCARD_CCR_OPTION_IREQ_ENABLE); + + if (sc->intr_handler_count++ == 0) { + rle = resource_list_find(&ivar->resources, SYS_RES_IRQ, 0); + if (rle == NULL) + panic("No IRQ for pccard?"); + + bus_setup_intr(dev, rle->res, INTR_TYPE_TTY/* | INTR_FAST*/, + pccard_intr, sc, (void*)&sc->intr_handler_count); + } + return 0; +} + +static int +pccard_teardown_intr(device_t dev, device_t child, struct resource *r, void *cookie) +{ + struct pccard_ivar *ivar = PCCARD_IVAR(child); + struct pccard_function *func = ivar->fcn; + struct pccard_softc *sc = device_get_softc(dev); + + if (func->intr_handler_cookie != cookie) + panic("pccard teardown of unknown interrupt handler\n"); + + func->intr_handler = NULL; + func->intr_handler_arg = NULL; + func->intr_handler_cookie = NULL; + pccard_ccr_write(func, PCCARD_CCR_OPTION, + pccard_ccr_read(func, PCCARD_CCR_OPTION) & + ~PCCARD_CCR_OPTION_IREQ_ENABLE); + + if (--sc->intr_handler_count == 0) { + struct resource_list_entry *rle = NULL; + + rle = resource_list_find(&ivar->resources, SYS_RES_IRQ, 0); + if (rle == NULL) + panic("No IRQ for pccard?"); + + bus_teardown_intr(dev, rle->res, &sc->intr_handler_count); + } + return 0; +} + static device_method_t pccard_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pccard_probe), @@ -947,8 +1086,8 @@ static device_method_t pccard_methods[] = { DEVMETHOD(bus_release_resource, pccard_release_resource), DEVMETHOD(bus_activate_resource, pccard_activate_resource), DEVMETHOD(bus_deactivate_resource, pccard_deactivate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_setup_intr, pccard_setup_intr), + DEVMETHOD(bus_teardown_intr, pccard_teardown_intr), DEVMETHOD(bus_set_resource, pccard_set_resource), DEVMETHOD(bus_get_resource, pccard_get_resource), DEVMETHOD(bus_delete_resource, pccard_delete_resource), @@ -977,4 +1116,4 @@ DRIVER_MODULE(pccard, pc98pcic, pccard_driver, pccard_devclass, 0, 0); DRIVER_MODULE(pccard, pccbb, pccard_driver, pccard_devclass, 0, 0); DRIVER_MODULE(pccard, tcic, pccard_driver, pccard_devclass, 0, 0); MODULE_VERSION(pccard, 1); -MODULE_DEPEND(pccard, pcic, 1, 1, 1); +/*MODULE_DEPEND(pccard, pcic, 1, 1, 1);*/ diff --git a/sys/dev/pccard/pccardvar.h b/sys/dev/pccard/pccardvar.h index 4b7cce4..e5117cc 100644 --- a/sys/dev/pccard/pccardvar.h +++ b/sys/dev/pccard/pccardvar.h @@ -136,6 +136,9 @@ struct pccard_function { long pf_mfc_iobase; long pf_mfc_iomax; int pf_flags; + driver_intr_t *intr_handler; + void *intr_handler_arg; + void *intr_handler_cookie; }; /* pf_flags */ @@ -181,6 +184,7 @@ struct pccard_softc { /* this stuff is for the card */ struct pccard_card card; int sc_enabled_count; /* num functions enabled */ + int intr_handler_count; }; void diff --git a/sys/dev/pccbb/pccbb.c b/sys/dev/pccbb/pccbb.c index 0615a32..e39e956 100644 --- a/sys/dev/pccbb/pccbb.c +++ b/sys/dev/pccbb/pccbb.c @@ -242,7 +242,7 @@ static int pccbb_pcic_release_resource(device_t self, device_t child, int type, static int pccbb_pcic_set_res_flags(device_t self, device_t child, int type, int rid, u_int32_t flags); static int pccbb_pcic_set_memory_offset(device_t self, device_t child, int rid, - u_int32_t offset); + u_int32_t offset, u_int32_t *offsetp); static int pccbb_power_enable_socket(device_t self, device_t child); static void pccbb_power_disable_socket(device_t self, device_t child); static int pccbb_activate_resource(device_t self, device_t child, int type, @@ -378,7 +378,6 @@ static int pccbb_attach(device_t dev) { struct pccbb_softc *sc = (struct pccbb_softc *)device_get_softc(dev); - int flags; int rid; u_int32_t tmp; @@ -387,9 +386,8 @@ pccbb_attach(device_t dev) STAILQ_INIT(&softcs); } mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_DEF); - sc->sc_chipset = cb_chipset(pci_get_devid(dev), NULL, &flags); + sc->sc_chipset = cb_chipset(pci_get_devid(dev), NULL, &sc->sc_flags); sc->sc_dev = dev; - sc->sc_flags = 0; sc->sc_cbdev = NULL; sc->sc_pccarddev = NULL; sc->sc_secbus = pci_read_config(dev, PCIR_SECBUS_2, 1); @@ -562,7 +560,7 @@ pccbb_driver_added(device_t dev, driver_t *driver) device_t *devlist; int tmp; int numdevs; - + DEVICE_IDENTIFY(driver, dev); device_get_children(dev, &devlist, &numdevs); for (tmp = 0; tmp < numdevs; tmp++) { @@ -570,12 +568,24 @@ pccbb_driver_added(device_t dev, driver_t *driver) device_probe_and_attach(devlist[tmp]) == 0) { if (devlist[tmp] == NULL) /* NOTHING */; - else if (strcmp(driver->name, "cardbus") == 0) + else if (strcmp(driver->name, "cardbus") == 0) { sc->sc_cbdev = devlist[tmp]; - else if (strcmp(driver->name, "pccard") == 0) + if ((sc->sc_socketreg->socket_state + & PCCBB_SOCKET_STAT_CD) == 0) { + mtx_enter(&sc->sc_mtx, MTX_DEF); + wakeup(sc); + mtx_exit(&sc->sc_mtx, MTX_DEF); + } + } else if (strcmp(driver->name, "pccard") == 0) { sc->sc_pccarddev = devlist[tmp]; - else - device_printf(dev, + if ((sc->sc_socketreg->socket_state + & PCCBB_SOCKET_STAT_CD) == 0) { + mtx_enter(&sc->sc_mtx, MTX_DEF); + wakeup(sc); + mtx_exit(&sc->sc_mtx, MTX_DEF); + } + } else + device_printf(dev, "Unsupported child bus: %s\n", driver->name); } @@ -605,6 +615,7 @@ pccbb_event_thread (void *arg) struct pccbb_softc *sc = arg; u_int32_t status; + mtx_enter(&Giant, MTX_DEF); for(;;) { if (!(sc->sc_flags & PCCBB_KTHREAD_RUNNING)) sc->sc_flags |= PCCBB_KTHREAD_RUNNING; @@ -623,24 +634,15 @@ pccbb_event_thread (void *arg) status = sc->sc_socketreg->socket_state; if ((status & PCCBB_SOCKET_STAT_CD) == 0) { - if (!(sc->sc_flags & PCCBB_CARDATTACHED)) - pccbb_insert(sc); - else - device_printf(sc->sc_dev, - "duplicate card insert\n"); + pccbb_insert(sc); } else { - if (!(sc->sc_flags & PCCBB_CARDATTACHED)) - DEVPRINTF((sc->sc_dev, - "removal of nonexistant card!\n")); - else - pccbb_removal(sc); + pccbb_removal(sc); } mtx_exit(&sc->sc_mtx, MTX_DEF); } mtx_exit(&sc->sc_mtx, MTX_DEF); sc->sc_flags &= ~PCCBB_KTHREAD_RUNNING; wakeup(sc); - mtx_enter(&Giant, MTX_DEF); kthread_exit(0); } @@ -689,18 +691,13 @@ pccbb_insert (struct pccbb_softc *sc) sockevent, sockstate)); if (sockstate & PCCBB_SOCKET_STAT_16BIT && sc->sc_pccarddev != NULL) { - sc->sc_flags |= PCCBB_CARDATTACHED | PCCBB_16BIT_CARD; - if (CARD_ATTACH_CARD(sc->sc_pccarddev) != 0) { + sc->sc_flags |= PCCBB_16BIT_CARD; + if (CARD_ATTACH_CARD(sc->sc_pccarddev) != 0) device_printf(sc->sc_dev, "card activation failed\n"); - sc->sc_flags &= ~PCCBB_CARDATTACHED; - } } else if (sockstate & PCCBB_SOCKET_STAT_CB && sc->sc_cbdev != NULL) { - sc->sc_flags |= PCCBB_CARDATTACHED; sc->sc_flags &= ~PCCBB_16BIT_CARD; - if (CARD_ATTACH_CARD(sc->sc_cbdev) != 0) { + if (CARD_ATTACH_CARD(sc->sc_cbdev) != 0) device_printf(sc->sc_dev, "card activation failed\n"); - sc->sc_flags &= ~PCCBB_CARDATTACHED; - } } else { device_printf (sc->sc_dev, "Unsupported card type detected\n"); } @@ -714,10 +711,9 @@ pccbb_removal (struct pccbb_softc *sc) sockstate = sc->sc_socketreg->socket_state; - sc->sc_flags &= ~PCCBB_CARDATTACHED; - if (sockstate & PCCBB_16BIT_CARD) + if (sockstate & PCCBB_16BIT_CARD && sc->sc_pccarddev != NULL) CARD_DETACH_CARD(sc->sc_pccarddev, DETACH_FORCE); - else + else if ((!(sockstate & PCCBB_16BIT_CARD)) && sc->sc_cbdev != NULL) CARD_DETACH_CARD(sc->sc_cbdev, DETACH_FORCE); while (NULL != (rle = SLIST_FIRST(&sc->rl))) { @@ -862,6 +858,9 @@ pccbb_power(device_t dev, int volts) break; } + if (sc->sc_socketreg->socket_control == sock_ctrl) + return 1; /* no change necessary */ + sc->sc_socketreg->socket_control = sock_ctrl; status = sc->sc_socketreg->socket_state; @@ -926,7 +925,7 @@ pccbb_cardbus_reset(device_t dev) DELAY(delay_us); /* If a card exists, unreset it! */ - if (sc->sc_flags & PCCBB_CARDATTACHED) { + if ((sc->sc_socketreg->socket_state & PCCBB_SOCKET_STAT_CD) == 0) { PCI_MASK_CONFIG(dev, PCCBBR_BRIDGECTRL, &~PCCBBM_BRIDGECTRL_RESET, 2); DELAY(delay_us); @@ -936,8 +935,13 @@ pccbb_cardbus_reset(device_t dev) static int pccbb_cardbus_power_enable_socket(device_t self, device_t child) { + struct pccbb_softc *sc = device_get_softc(self); int voltage; - + + if ((sc->sc_socketreg->socket_state & PCCBB_SOCKET_STAT_CD) + == PCCBB_SOCKET_STAT_CD) + return ENODEV; + voltage = pccbb_detect_voltage(self); pccbb_power(self, CARD_VCC_0V | CARD_VPP_0V); @@ -1285,6 +1289,7 @@ pccbb_pcic_wait_ready(struct pccbb_softc *sc) PCIC_SYSMEM_ADDR ## NUM ## _START_MSB, \ PCIC_SYSMEM_ADDR ## NUM ## _STOP_LSB, \ PCIC_SYSMEM_ADDR ## NUM ## _STOP_MSB, \ + PCIC_SYSMEM_ADDR ## NUM ## _WIN, \ PCIC_CARDMEM_ADDR ## NUM ## _LSB, \ PCIC_CARDMEM_ADDR ## NUM ## _MSB, \ PCIC_ADDRWIN_ENABLE_MEM ## NUM ## , \ @@ -1295,6 +1300,7 @@ static struct mem_map_index_st { int sysmem_start_msb; int sysmem_stop_lsb; int sysmem_stop_msb; + int sysmem_win; int cardmem_lsb; int cardmem_msb; int memenable; @@ -1314,7 +1320,7 @@ pccbb_pcic_do_mem_map(struct pccbb_softc *sc, int win) (sc->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff); PCIC_WRITE(sc, mem_map_index[win].sysmem_start_msb, ((sc->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) & - PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK)); + PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK) | 0x80); PCIC_WRITE(sc, mem_map_index[win].sysmem_stop_lsb, ((sc->mem[win].addr + sc->mem[win].realsize - 1) >> @@ -1325,6 +1331,9 @@ pccbb_pcic_do_mem_map(struct pccbb_softc *sc, int win) PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) | PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2); + PCIC_WRITE(sc, mem_map_index[win].sysmem_win, + (sc->mem[win].addr >> PCIC_MEMREG_WIN_SHIFT) & 0xff); + PCIC_WRITE(sc, mem_map_index[win].cardmem_lsb, (sc->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff); PCIC_WRITE(sc, mem_map_index[win].cardmem_msb, @@ -1340,15 +1349,17 @@ pccbb_pcic_do_mem_map(struct pccbb_softc *sc, int win) #ifdef CBB_DEBUG { - int r1, r2, r3, r4, r5, r6; + int r1, r2, r3, r4, r5, r6, r7; r1 = PCIC_READ(sc, mem_map_index[win].sysmem_start_msb); r2 = PCIC_READ(sc, mem_map_index[win].sysmem_start_lsb); r3 = PCIC_READ(sc, mem_map_index[win].sysmem_stop_msb); r4 = PCIC_READ(sc, mem_map_index[win].sysmem_stop_lsb); r5 = PCIC_READ(sc, mem_map_index[win].cardmem_msb); r6 = PCIC_READ(sc, mem_map_index[win].cardmem_lsb); + r7 = PCIC_READ(sc, mem_map_index[win].sysmem_win); DPRINTF(("pccbb_pcic_do_mem_map window %d: %02x%02x %02x%02x " - "%02x%02x\n", win, r1, r2, r3, r4, r5, r6)); + "%02x%02x %02x (%08x+%08x.%08x*%08lx)\n", win, r1, r2, r3, r4, r5, r6, r7, + sc->mem[win].addr, sc->mem[win].size, sc->mem[win].realsize, sc->mem[win].offset)); } #endif } @@ -1371,7 +1382,6 @@ pccbb_pcic_mem_map(struct pccbb_softc *sc, int kind, return (1); card_addr = card_addr - card_addr % PCIC_MEM_PAGESIZE; - sc->mem[*win].memt = rman_get_bustag(r); sc->mem[*win].memh = rman_get_bushandle(r); sc->mem[*win].addr = rman_get_start(r); @@ -1399,7 +1409,6 @@ pccbb_pcic_mem_unmap(struct pccbb_softc *sc, int window) panic("pccbb_pcic_mem_unmap: window out of range"); PCIC_MASK(sc, PCIC_ADDRWIN_ENABLE, & ~mem_map_index[window].memenable); - sc->memalloc &= ~(1 << window); } @@ -1452,6 +1461,18 @@ static void pccbb_pcic_do_io_map(struct pccbb_softc *sc, int win) | io_map_index[win].ioctlbits[sc->io[win].width]); PCIC_MASK(sc, PCIC_ADDRWIN_ENABLE, | io_map_index[win].ioenable); +#ifdef CBB_DEBUG + { + int r1, r2, r3, r4; + r1 = PCIC_READ(sc, io_map_index[win].start_msb); + r2 = PCIC_READ(sc, io_map_index[win].start_lsb); + r3 = PCIC_READ(sc, io_map_index[win].stop_msb); + r4 = PCIC_READ(sc, io_map_index[win].stop_lsb); + DPRINTF(("pccbb_pcic_do_io_map window %d: %02x%02x %02x%02x " + "(%08x+%08x)\n", win, r1, r2, r3, r4, + sc->io[win].addr, sc->io[win].size)); + } +#endif } static int @@ -1517,6 +1538,9 @@ pccbb_pcic_activate_resource(device_t self, device_t child, int type, int rid, struct pccbb_reslist *rle; struct pccbb_softc *sc = device_get_softc(self); + if (rman_get_flags(r) & RF_ACTIVE) + return 0; + switch (type) { case SYS_RES_IOPORT: err = pccbb_pcic_io_map(sc, 0, r, 0, &win); @@ -1549,7 +1573,6 @@ pccbb_pcic_deactivate_resource(device_t self, device_t child, int type, struct pccbb_softc *sc = device_get_softc(self); int win; struct pccbb_reslist *rle; - win = -1; SLIST_FOREACH(rle, &sc->rl, entries) { if (type == rle->type && rid == rle->rid && @@ -1558,8 +1581,10 @@ pccbb_pcic_deactivate_resource(device_t self, device_t child, int type, break; } } - if (win == -1) + if (win == -1) { + panic("pccbb_pcic: deactivating bogus resoure"); return 1; + } switch (type) { case SYS_RES_IOPORT: @@ -1582,18 +1607,16 @@ pccbb_pcic_alloc_resource(device_t self, device_t child, int type, int* rid, struct pccbb_softc *sc = device_get_softc(self); struct pccbb_reslist *rle; - /* Nearly default */ - if (type == SYS_RES_MEMORY && start == 0 && end == ~0 && count != 1) { - start = 0xd0000; /* XXX */ - end = 0xdffff; + if ((sc->sc_flags & PCCBB_PCIC_MEM_32) == 0) { + panic("PCCBB bridge cannot handle non MEM_32 bridges\n"); } switch (type) { case SYS_RES_MEMORY: /* Nearly default */ if (start == 0 && end == ~0 && count != 1) { - start = 0xd0000; /* XXX -- should be tweakable*/ - end = 0xdffff; + start = CARDBUS_SYS_RES_MEMORY_START; /* XXX -- should be tweakable*/ + end = CARDBUS_SYS_RES_MEMORY_END; } flags = (flags & ~RF_ALIGNMENT_MASK) | rman_make_alignment_flags(PCCBB_MEMALIGN); @@ -1639,15 +1662,27 @@ pccbb_pcic_release_resource(device_t self, device_t child, int type, { struct pccbb_softc *sc = device_get_softc(self); struct pccbb_reslist *rle; + int count = 0; + + if (rman_get_flags(res) & RF_ACTIVE) { + int error; + error = bus_deactivate_resource(child, type, rid, res); + if (error != 0) + return error; + } SLIST_FOREACH(rle, &sc->rl, entries) { if (type == rle->type && rid == rle->rid && child == rle->odev) { SLIST_REMOVE(&sc->rl, rle, pccbb_reslist, entries); free(rle, M_DEVBUF); + count++; break; } } + if (count == 0) { + panic("pccbb_pcic: releasing bogus resource"); + } return bus_generic_release_resource(self, child, type, rid, res); } @@ -1671,13 +1706,14 @@ pccbb_pcic_set_res_flags(device_t self, device_t child, int type, int rid, static int pccbb_pcic_set_memory_offset(device_t self, device_t child, int rid, - u_int32_t offset) + u_int32_t cardaddr, u_int32_t *offsetp) { struct pccbb_softc *sc = device_get_softc(self); int win; struct pccbb_reslist *rle; win = -1; + SLIST_FOREACH(rle, &sc->rl, entries) { if (SYS_RES_MEMORY == rle->type && rid == rle->rid && child == rle->odev) { @@ -1685,13 +1721,17 @@ pccbb_pcic_set_memory_offset(device_t self, device_t child, int rid, break; } } - if (win == -1) + if (win == -1) { + panic("pccbb_pcic: setting memory offset of bogus resource"); return 1; + } - offset = offset - offset % PCIC_MEM_PAGESIZE; - sc->mem[win].offset = ((long)offset) - - ((long)(sc->mem[win].addr)); - + *offsetp = cardaddr % PCIC_MEM_PAGESIZE; + cardaddr -= *offsetp; + sc->mem[win].realsize = sc->mem[win].size + *offsetp + PCIC_MEM_PAGESIZE - 1; + sc->mem[win].realsize = sc->mem[win].realsize - + (sc->mem[win].realsize % PCIC_MEM_PAGESIZE); + sc->mem[win].offset = cardaddr - sc->mem[win].addr; pccbb_pcic_do_mem_map(sc, win); return 0; @@ -1785,7 +1825,7 @@ static int pccbb_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { struct pccbb_softc *sc = device_get_softc(dev); - + switch (which) { case PCIB_IVAR_BUS: *result = sc->sc_secbus; diff --git a/sys/dev/pccbb/pccbbvar.h b/sys/dev/pccbb/pccbbvar.h index 2e4ef7c..76aed70 100644 --- a/sys/dev/pccbb/pccbbvar.h +++ b/sys/dev/pccbb/pccbbvar.h @@ -71,7 +71,6 @@ struct pccbb_softc { u_int32_t sc_flags; #define PCCBB_PCIC_IO_RELOC 0x01 #define PCCBB_PCIC_MEM_32 0x02 -#define PCCBB_CARDATTACHED 0x01000000 #define PCCBB_16BIT_CARD 0x02000000 #define PCCBB_KTHREAD_RUNNING 0x04000000 #define PCCBB_KTHREAD_DONE 0x08000000 @@ -122,7 +121,7 @@ struct pccbb_softc { #define CARD_VPPMASK 0x00f0 /* XXX: rman is dumb */ -#define CARDBUS_SYS_RES_MEMORY_START 0x18020000 +#define CARDBUS_SYS_RES_MEMORY_START 0x44000000 #define CARDBUS_SYS_RES_MEMORY_END 0xEFFFFFFF #define CARDBUS_SYS_RES_IOPORT_START 0x3000 #define CARDBUS_SYS_RES_IOPORT_END 0xEFFF -- cgit v1.1