summaryrefslogtreecommitdiffstats
path: root/sys/dev
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
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')
-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
-rw-r--r--sys/dev/pccard/card_if.m54
-rw-r--r--sys/dev/pccard/pccard.c263
-rw-r--r--sys/dev/pccard/pccardvar.h4
-rw-r--r--sys/dev/pccbb/pccbb.c146
-rw-r--r--sys/dev/pccbb/pccbbvar.h3
8 files changed, 597 insertions, 207 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
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
OpenPOWER on IntegriCloud