summaryrefslogtreecommitdiffstats
path: root/sys/dev/cardbus/cardbus_cis.c
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2005-12-29 01:43:47 +0000
committerimp <imp@FreeBSD.org>2005-12-29 01:43:47 +0000
commit2d3e88cd9e999219b2101e65b3390d628941126e (patch)
treebf533208984821e83f178063f9eae3f952f8b8a9 /sys/dev/cardbus/cardbus_cis.c
parent10c2623c78422d9bb6f770ec6ab49b3f21dca64e (diff)
downloadFreeBSD-src-2d3e88cd9e999219b2101e65b3390d628941126e.zip
FreeBSD-src-2d3e88cd9e999219b2101e65b3390d628941126e.tar.gz
Implement /dev/cardbus%d.cis, same thing as /dev/pccard%d.cis. There
are some rough edges with this still, but it seems to work well enough to commit.
Diffstat (limited to 'sys/dev/cardbus/cardbus_cis.c')
-rw-r--r--sys/dev/cardbus/cardbus_cis.c120
1 files changed, 49 insertions, 71 deletions
diff --git a/sys/dev/cardbus/cardbus_cis.c b/sys/dev/cardbus/cardbus_cis.c
index 4d7b973..552d32d 100644
--- a/sys/dev/cardbus/cardbus_cis.c
+++ b/sys/dev/cardbus/cardbus_cis.c
@@ -58,45 +58,33 @@ extern int cardbus_cis_debug;
#define DPRINTF(a) if (cardbus_cis_debug) printf a
#define DEVPRINTF(x) if (cardbus_cis_debug) device_printf x
-struct tuple_callbacks;
-
-typedef int (tuple_cb) (device_t cbdev, device_t child, int id, int len,
- uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
-
-struct tuple_callbacks {
- int id;
- char *name;
- tuple_cb *func;
-};
-
static int decode_tuple_generic(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_linktarget(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_vers_1(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_funcid(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_manfid(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_funce(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_bar(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_unhandled(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int decode_tuple_end(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info);
+ struct tuple_callbacks *info, void *);
static int cardbus_read_tuple_conf(device_t cbdev, device_t child,
uint32_t start, uint32_t *off, int *tupleid, int *len,
@@ -113,9 +101,8 @@ static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child,
uint32_t *start, int *rid);
static int decode_tuple(device_t cbdev, device_t child, int tupleid,
int len, uint8_t *tupledata, uint32_t start,
- uint32_t *off, struct tuple_callbacks *callbacks);
-static int cardbus_parse_cis(device_t cbdev, device_t child,
- struct tuple_callbacks *callbacks);
+ uint32_t *off, struct tuple_callbacks *callbacks,
+ void *);
#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
@@ -139,7 +126,7 @@ static char *funcnames[] = {
static int
decode_tuple_generic(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
int i;
@@ -162,7 +149,7 @@ decode_tuple_generic(device_t cbdev, device_t child, int id,
static int
decode_tuple_linktarget(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
int i;
@@ -180,7 +167,7 @@ decode_tuple_linktarget(device_t cbdev, device_t child, int id,
tupledata[2] != 'S') {
printf("Invalid data for CIS Link Target!\n");
decode_tuple_generic(cbdev, child, id, len, tupledata,
- start, off, info);
+ start, off, info, argp);
return (EINVAL);
}
return (0);
@@ -189,7 +176,7 @@ decode_tuple_linktarget(device_t cbdev, device_t child, int id,
static int
decode_tuple_vers_1(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
int i;
@@ -212,7 +199,7 @@ decode_tuple_vers_1(device_t cbdev, device_t child, int id,
static int
decode_tuple_funcid(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
struct cardbus_devinfo *dinfo = device_get_ivars(child);
int numnames = sizeof(funcnames) / sizeof(funcnames[0]);
@@ -225,7 +212,7 @@ decode_tuple_funcid(device_t cbdev, device_t child, int id,
printf("%s", funcnames[tupledata[i]]);
else
printf("Unknown(%d)", tupledata[i]);
- if (i < len-1)
+ if (i < len - 1)
printf(", ");
}
printf("\n");
@@ -238,7 +225,7 @@ decode_tuple_funcid(device_t cbdev, device_t child, int id,
static int
decode_tuple_manfid(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
struct cardbus_devinfo *dinfo = device_get_ivars(child);
int i;
@@ -260,7 +247,7 @@ decode_tuple_manfid(device_t cbdev, device_t child, int id,
static int
decode_tuple_funce(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
struct cardbus_devinfo *dinfo = device_get_ivars(child);
int type, i;
@@ -295,7 +282,7 @@ decode_tuple_funce(device_t cbdev, device_t child, int id,
static int
decode_tuple_bar(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
struct cardbus_devinfo *dinfo = device_get_ivars(child);
int type;
@@ -390,17 +377,17 @@ decode_tuple_bar(device_t cbdev, device_t child, int id,
static int
decode_tuple_unhandled(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
/* Make this message suck less XXX */
printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
- return (-1);
+ return (EINVAL);
}
static int
decode_tuple_end(device_t cbdev, device_t child, int id,
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *info)
+ struct tuple_callbacks *info, void *argp)
{
if (cardbus_cis_debug)
printf("CIS reading done\n");
@@ -479,8 +466,9 @@ cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
{
if (res != (struct resource*)~0UL) {
bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
- pci_write_config(child, rid, 0, 4);
- PCI_DISABLE_IO(cbdev, child, SYS_RES_MEMORY);
+ if (rid == PCIM_CIS_ASI_ROM)
+ pci_write_config(child, rid, pci_read_config(child,
+ rid, 4) & ~PCIR_BIOS, 4);
}
}
@@ -488,14 +476,14 @@ static struct resource *
cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
int *rid)
{
- uint32_t testval;
- uint32_t size;
struct resource *res;
uint32_t space;
space = *start & PCIM_CIS_ASI_MASK;
switch (space) {
case PCIM_CIS_ASI_TUPLE:
+ if (cardbus_cis_debug)
+ device_printf(cbdev, "CIS in PCI config space\n");
/* CIS in PCI config space need no initialization */
return ((struct resource*)~0UL);
case PCIM_CIS_ASI_BAR0:
@@ -505,9 +493,13 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
case PCIM_CIS_ASI_BAR4:
case PCIM_CIS_ASI_BAR5:
*rid = PCIR_BAR(space - PCIM_CIS_ASI_BAR0);
+ if (cardbus_cis_debug)
+ device_printf(cbdev, "CIS in BAR %#x\n", *rid);
break;
case PCIM_CIS_ASI_ROM:
*rid = PCIR_BIOS;
+ if (cardbus_cis_debug)
+ device_printf(cbdev, "CIS in option rom\n");
break;
default:
device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
@@ -515,35 +507,19 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
return (NULL);
}
- /* figure out how much space we need */
- pci_write_config(child, *rid, 0xffffffff, 4);
- testval = pci_read_config(child, *rid, 4);
-
- /*
- * This bit has a different meaning depending if we are dealing
- * with a normal BAR or an Option ROM BAR.
- */
- if (((testval & 0x1) == 0x1) && (*rid != PCIR_BIOS)) {
- device_printf(cbdev, "CIS Space is IO, expecting memory.\n");
- return (NULL);
- }
-
- size = CARDBUS_MAPREG_MEM_SIZE(testval);
- /* XXX Is this some kind of hack? */
- if (size < 4096)
- size = 4096;
/* allocate the memory space to read CIS */
- res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, size,
- rman_make_alignment_flags(size) | RF_ACTIVE);
+ res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, 1,
+ rman_make_alignment_flags(4096) | RF_ACTIVE);
if (res == NULL) {
device_printf(cbdev, "Unable to allocate resource "
"to read CIS.\n");
return (NULL);
}
- pci_write_config(child, *rid,
- rman_get_start(res) | ((*rid == PCIR_BIOS) ? PCIM_BIOS_ENABLE : 0),
- 4);
PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY);
+ pci_write_config(child, *rid, rman_get_start(res), 4);
+ if (*rid == PCIR_BIOS)
+ pci_write_config(child, *rid,
+ rman_get_start(res) | PCIM_BIOS_ENABLE, 4);
/* Flip to the right ROM image if CIS is in ROM */
if (space == PCIM_CIS_ASI_ROM) {
@@ -626,21 +602,21 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
static int
decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
uint8_t *tupledata, uint32_t start, uint32_t *off,
- struct tuple_callbacks *callbacks)
+ struct tuple_callbacks *callbacks, void *argp)
{
int i;
for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
if (tupleid == callbacks[i].id)
return (callbacks[i].func(cbdev, child, tupleid, len,
- tupledata, start, off, &callbacks[i]));
+ tupledata, start, off, &callbacks[i], argp));
}
return (callbacks[i].func(cbdev, child, tupleid, len,
- tupledata, start, off, NULL));
+ tupledata, start, off, NULL, argp));
}
-static int
+int
cardbus_parse_cis(device_t cbdev, device_t child,
- struct tuple_callbacks *callbacks)
+ struct tuple_callbacks *callbacks, void *argp)
{
uint8_t tupledata[MAXTUPLESIZE];
int tupleid;
@@ -656,6 +632,8 @@ cardbus_parse_cis(device_t cbdev, device_t child,
device_printf(cbdev, "CIS pointer is 0!\n");
return (ENXIO);
}
+ if (cardbus_cis_debug)
+ device_printf(cbdev, "CIS pointer is %#x\n", start);
off = 0;
res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
if (res == NULL) {
@@ -664,8 +642,8 @@ cardbus_parse_cis(device_t cbdev, device_t child,
}
do {
- if (0 != cardbus_read_tuple(cbdev, child, res, start, &off,
- &tupleid, &len, tupledata)) {
+ if (cardbus_read_tuple(cbdev, child, res, start, &off,
+ &tupleid, &len, tupledata) != 0) {
device_printf(cbdev, "Failed to read CIS.\n");
cardbus_read_tuple_finish(cbdev, child, rid, res);
return (ENXIO);
@@ -678,7 +656,7 @@ cardbus_parse_cis(device_t cbdev, device_t child,
return (EINVAL);
}
expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
- tupledata, start, &off, callbacks);
+ tupledata, start, &off, callbacks, argp);
if (expect_linktarget != 0) {
device_printf(cbdev, "Parsing failed with %d\n",
expect_linktarget);
@@ -710,7 +688,7 @@ cardbus_do_cis(device_t cbdev, device_t child)
MAKETUPLE(GENERIC, generic),
};
- ret = cardbus_parse_cis(cbdev, child, init_callbacks);
+ ret = cardbus_parse_cis(cbdev, child, init_callbacks, NULL);
if (ret < 0)
return (ret);
return 0;
OpenPOWER on IntegriCloud