summaryrefslogtreecommitdiffstats
path: root/sys/dev/cardbus
diff options
context:
space:
mode:
authorjon <jon@FreeBSD.org>2001-01-06 18:04:55 +0000
committerjon <jon@FreeBSD.org>2001-01-06 18:04:55 +0000
commite564c617f8aadbc77f1edc9eddeb5206cc9fb74c (patch)
tree33661c6ea35ebf2bdf7d737967b65b1ea6e1b1fa /sys/dev/cardbus
parent56e99b7d35d909eaef84dafc091867116a08e54f (diff)
downloadFreeBSD-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.c86
-rw-r--r--sys/dev/cardbus/cardbus_cis.c241
-rw-r--r--sys/dev/cardbus/cardbus_cis.h7
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
OpenPOWER on IntegriCloud