summaryrefslogtreecommitdiffstats
path: root/sys/dev/cardbus
diff options
context:
space:
mode:
authorjon <jon@FreeBSD.org>2000-11-28 00:08:18 +0000
committerjon <jon@FreeBSD.org>2000-11-28 00:08:18 +0000
commit49bd2bf0607af99945e5e2b456be122bc22f2247 (patch)
treede1622108bfa2fcf633ecee95704daea931d0233 /sys/dev/cardbus
parent8dd21cd21d32b92d7eec0ad527eb4164660a5892 (diff)
downloadFreeBSD-src-49bd2bf0607af99945e5e2b456be122bc22f2247.zip
FreeBSD-src-49bd2bf0607af99945e5e2b456be122bc22f2247.tar.gz
overhaul cis functions to read cis tuple by tuple (instead of all at once).
Also fix incorrect parsing of BAR.
Diffstat (limited to 'sys/dev/cardbus')
-rw-r--r--sys/dev/cardbus/cardbus_cis.c269
1 files changed, 139 insertions, 130 deletions
diff --git a/sys/dev/cardbus/cardbus_cis.c b/sys/dev/cardbus/cardbus_cis.c
index f6565ec..af1719e 100644
--- a/sys/dev/cardbus/cardbus_cis.c
+++ b/sys/dev/cardbus/cardbus_cis.c
@@ -48,8 +48,6 @@
#include <dev/cardbus/cardbusreg.h>
#include <dev/cardbus/cardbus_cis.h>
-#include "pccbb_if.h"
-
#if defined CARDBUS_DEBUG
#define STATIC
#define DPRINTF(a) printf a
@@ -67,22 +65,25 @@ static const char rcsid[] =
struct tupleinfo;
-static int decode_tuples(device_t dev, device_t child,
- u_int8_t *tuples, int len);
-static int cardbus_read_exrom_cis(device_t dev, struct resource *res,
- int cis, u_int8_t* tuple, int len);
-static int cardbus_read_tuples_conf(device_t dev, device_t child,
- u_int32_t cis_ptr, u_int8_t *tuples,
- int len);
-static int cardbus_read_tuples_mem(device_t dev, device_t child, int space,
- u_int32_t cis_ptr, u_int8_t *tuples,
- int len);
-static int cardbus_read_tuples(device_t dev, device_t child, u_int8_t *tuples,
- int len);
+static int cardbus_read_tuple_conf(device_t dev, device_t child,
+ u_int32_t *space, u_int32_t *off,
+ int *tupleid, int *len, u_int8_t *tupledata);
+static int cardbus_read_tuple_exrom(device_t dev, struct resource *mem,
+ u_int32_t *space, u_int32_t *off,
+ int *tupleid, int *len, u_int8_t *tupledata);
+static int cardbus_read_tuple_mem(device_t dev, device_t child, u_int32_t *space,
+ u_int32_t *off, int *tupleid, int *len,
+ u_int8_t *tupledata);
+static int cardbus_read_tuple(device_t dev, device_t child, u_int32_t *space,
+ 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 *space, u_int32_t *off);
#define DECODE_PROTOTYPE(NAME) static int decode_tuple_ ## NAME \
- (device_t dev, device_t child, int id, int len, \
- u_int8_t *buff, struct tupleinfo *info)
+ (device_t dev, device_t child, int id, int len, \
+ u_int8_t *tupledata, u_int32_t *space, u_int32_t *off, \
+ struct tupleinfo *info)
DECODE_PROTOTYPE(generic);
DECODE_PROTOTYPE(bar);
DECODE_PROTOTYPE(linktarget);
@@ -97,7 +98,8 @@ static struct tupleinfo {
u_int8_t id;
char* name;
int (*func)(device_t dev, device_t child, int id, int len,
- u_int8_t *buff, struct tupleinfo *info);
+ u_int8_t *tupledata, u_int32_t *space, u_int32_t *off,
+ struct tupleinfo *info);
} tupleinfo[] = {
#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
MAKETUPLE(NULL, generic),
@@ -137,7 +139,7 @@ static struct tupleinfo {
MAKETUPLE(DATE, generic),
MAKETUPLE(BATTERY, generic),
MAKETUPLE(ORG, generic),
- MAKETUPLE(END, end),
+ MAKETUPLE(END, end),
#undef MAKETUPLE
};
@@ -167,7 +169,7 @@ DECODE_PROTOTYPE(generic)
for (i = 0; i < len; i++) {
if (i % 0x10 == 0 && len > 0x10)
printf ("\n 0x%02x:", i);
- printf (" %02x", buff[i]);
+ printf (" %02x", tupledata[i]);
}
printf ("\n");
#endif
@@ -176,9 +178,11 @@ DECODE_PROTOTYPE(generic)
DECODE_PROTOTYPE(linktarget)
{
- if (len != 3 || buff[0] != 'C' || buff[1] != 'I' || buff[2] != 'S') {
+ if (len != 3 || tupledata[0] != 'C' || tupledata[1] != 'I' ||
+ tupledata[2] != 'S') {
printf("Invalid data for CIS Link Target!\n");
- decode_tuple_generic(dev, child, id, len, buff, info);
+ decode_tuple_generic(dev, child, id, len, tupledata,
+ space, off, info);
return EINVAL;
}
return 0;
@@ -187,15 +191,15 @@ DECODE_PROTOTYPE(linktarget)
DECODE_PROTOTYPE(vers_1)
{
int i;
- printf("Product version: %d.%d\n", buff[0], buff[1]);
+ printf("Product version: %d.%d\n", tupledata[0], tupledata[1]);
printf("Product name: ");
for (i = 2; i < len; i++) {
- if (buff[i] == '\0')
+ if (tupledata[i] == '\0')
printf (" | ");
- else if (buff[i] == 0xff)
+ else if (tupledata[i] == 0xff)
break;
else
- printf("%c", buff[i]);
+ printf("%c", tupledata[i]);
}
printf("\n");
return 0;
@@ -208,10 +212,10 @@ DECODE_PROTOTYPE(funcid)
printf("Functions: ");
for(i = 0; i < len; i++) {
- if (buff[i] < numnames)
- printf ("%s", funcnames[buff[i]]);
+ if (tupledata[i] < numnames)
+ printf ("%s", funcnames[tupledata[i]]);
else
- printf ("Unknown(%d)", buff[i]);
+ printf ("Unknown(%d)", tupledata[i]);
if (i < len-1) printf(", ");
}
printf ("\n");
@@ -223,7 +227,7 @@ DECODE_PROTOTYPE(manfid)
int i;
printf ("Manufacturer ID: ");
for (i = 0; i < len; i++)
- printf("%02x", buff[i]);
+ printf("%02x", tupledata[i]);
printf("\n");
return 0;
}
@@ -233,7 +237,7 @@ DECODE_PROTOTYPE(funce)
int i;
printf ("Function Extension: ");
for (i = 0; i < len; i++)
- printf("%02x", buff[i]);
+ printf("%02x", tupledata[i]);
printf("\n");
return 0;
}
@@ -250,8 +254,8 @@ DECODE_PROTOTYPE(bar)
u_int32_t start, len;
struct resource *res;
- reg = *(u_int16_t*)buff;
- len = *(u_int32_t*)(buff+2);
+ reg = *(u_int16_t*)tupledata;
+ len = *(u_int32_t*)(tupledata+2);
if (reg & TPL_BAR_REG_AS) {
type = SYS_RES_IOPORT;
} else {
@@ -272,7 +276,6 @@ DECODE_PROTOTYPE(bar)
device_printf(dev, "Cannot allocate BAR %02x\n", reg);
} else {
start = rman_get_start(res);
- if (reg == CARDBUS_ROM_REG) start |= 1;
pci_write_config(child, reg, start, 4);
}
}
@@ -287,60 +290,53 @@ DECODE_PROTOTYPE(unhandled)
DECODE_PROTOTYPE(end)
{
- return -1;
+ return 0;
}
-static int decode_tuples(device_t dev, device_t child,
- u_int8_t *tuples, int len)
+static int
+cardbus_read_tuple_conf(device_t dev, device_t child, u_int32_t *space,
+ u_int32_t *off, int *tupleid, int *len,
+ u_int8_t *tupledata)
{
- int ret = 0;
- if (CISTPL_LINKTARGET != *tuples) {
- device_printf(dev, "CIS does not start with link target\n");
- return EINVAL;
- }
- do {
- int i;
- int numtupleids = sizeof(tupleinfo)/sizeof(tupleinfo[0]);
- for (i = 0; i < numtupleids; i++) {
- if (tuples[0] == tupleinfo[i].id) {
- ret = tupleinfo[i].func(dev, child, tuples[0],
- tuples[1], tuples+2,
- &tupleinfo[i]);
- break;
- }
- }
- if (i == numtupleids)
- ret = decode_tuple_generic(dev, child, tuples[0],
- tuples[1], tuples+2, NULL);
-
- len -= (tuples[1]+2);
- tuples += tuples[1]+2;
- } while (len > 0 && ret == 0);
-
- if (ret < 0) return 0;
- else if (ret != 0) return ret;
- else {
- device_printf(dev, "CIS too long or END not encountered!\n");
- return EFBIG;
+ int i, j;
+ u_int32_t e;
+
+ e = pci_read_config(child, *off - *off%4, 4);
+ for (j = *off%4; j>0; j--)
+ e >>= 8;
+ *len = 0;
+ for (i = *off, j = -2; j < *len; j++, i++) {
+ if (i % 4 == 0)
+ e = pci_read_config(child, i, 4);
+ if (j == -2)
+ *tupleid = 0xff & e;
+ else if (j == -1)
+ *len = 0xff & e;
+ else
+ tupledata[j] = 0xff & e;
+ e >>= 8;
}
+ *off += *len+2;
+ return 0;
}
+
static int
-cardbus_read_exrom_cis(device_t dev, struct resource *res, int cis,
- u_int8_t* tuple, int len)
+cardbus_read_tuple_exrom(device_t dev, struct resource *mem, u_int32_t *space,
+ u_int32_t *off, int *tupleid, int *len,
+ u_int8_t *tupledata)
{
#define READROM(rom, type, offset) \
(*((u_int ## type ##_t *)(((unsigned char*)rom) + offset)))
- u_int32_t addr = 0; /* offset of current rom image */
int romnum = 0;
unsigned char *data;
u_int32_t imagesize;
unsigned char *image;
int imagenum;
- image = (unsigned char*)rman_get_virtual(res);
- imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(cis);
+ image = (unsigned char*)rman_get_virtual(mem);
+ imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*off);
do {
if (READROM(image, 16, CARDBUS_EXROM_SIGNATURE) != 0xaa55) {
device_printf (dev, "Bad header in rom %d: %04x\n",
@@ -351,21 +347,24 @@ cardbus_read_exrom_cis(device_t dev, struct resource *res, int cis,
data = image + READROM(image, 16, CARDBUS_EXROM_DATA_PTR);
imagesize = READROM(data, 16, CARDBUS_EXROM_DATA_IMAGE_LENGTH);
- if(imagesize == 0)
+ if(imagesize == 0) {
/*
* XXX some ROMs seem to have this as zero,
* can we assume this means 1 block?
*/
imagesize = 1;
+ }
imagesize <<= 9;
if (imagenum == romnum) {
- romnum = -1;
- memcpy(tuple, image+CARDBUS_CIS_ADDR(cis), len);
+ image += CARDBUS_CIS_ADDR(*off);
+ *tupleid = image[0];
+ *len = image[1];
+ memcpy(tupledata, image+2, *len);
+ *off += *len+2;
return 0;
- }
+ }
- addr += imagesize;
romnum++;
} while ((READROM(data, 8, CARDBUS_EXROM_DATA_INDICATOR) & 0x80) == 0);
device_printf(dev, "Cannot read CIS: Not enough images of rom\n");
@@ -374,40 +373,18 @@ cardbus_read_exrom_cis(device_t dev, struct resource *res, int cis,
}
static int
-cardbus_read_tuples_conf(device_t dev, device_t child, u_int32_t cis_ptr,
- u_int8_t *tuples, int len)
-{
- int i, j;
-
- DEVPRINTF((dev, "reading CIS data from configuration space\n"));
- for (i = cis_ptr, j = 0; i < len; i += 4) {
- u_int32_t e = pci_read_config(child, i, 4);
- tuples[j] = 0xff & e;
- e >>= 8;
- tuples[j + 1] = 0xff & e;
- e >>= 8;
- tuples[j + 2] = 0xff & e;
- e >>= 8;
- tuples[j + 3] = 0xff & e;
- j += 4;
- }
- return 0;
-}
-
-static int
-cardbus_read_tuples_mem(device_t dev, device_t child, int space,
- u_int32_t cis_ptr, u_int8_t *tuples, int len)
+cardbus_read_tuple_mem(device_t dev, device_t child, u_int32_t *space,
+ u_int32_t *off, int *tupleid, int *len,
+ u_int8_t *tupledata)
{
struct resource *mem;
int rid;
int ret;
- if(space == CARDBUS_CIS_ASI_ROM) {
+ if (*space == CARDBUS_CIS_ASI_ROM) {
rid = CARDBUS_ROM_REG;
- DEVPRINTF((dev, "reading CIS data from ROM\n"));
} else {
- rid = CARDBUS_BASE0_REG + (space - 1) * 4;
- DEVPRINTF((dev, "reading CIS data from BAR%d\n", space - 1));
+ rid = CARDBUS_BASE0_REG + (*space - 1) * 4;
}
mem = bus_alloc_resource(child, SYS_RES_MEMORY, &rid, 0, ~0,
1, RF_ACTIVE);
@@ -416,34 +393,32 @@ cardbus_read_tuples_mem(device_t dev, device_t child, int space,
return ENOMEM;
}
- if(space == CARDBUS_CIS_ASI_ROM) {
- int s;
- s = splhigh();
- ret = cardbus_read_exrom_cis(dev, mem, cis_ptr, tuples, len);
- splx(s);
+ if(*space == CARDBUS_CIS_ASI_ROM) {
+ ret = cardbus_read_tuple_exrom(dev, mem, space, off, tupleid,
+ len, tupledata);
} else {
/* XXX byte order? */
- memcpy(tuples, (unsigned char*)rman_get_virtual(mem)+cis_ptr,
- len);
+ unsigned char* ptr;
+ ptr = (unsigned char*)rman_get_virtual(mem)+*off;
+ *tupleid = ptr[0];
+ *len = ptr[1];
+ memcpy(tupledata, ptr+2, *len);
ret = 0;
+ *off += *len+2;
}
bus_release_resource(child, SYS_RES_MEMORY, rid, mem);
return ret;
}
static int
-cardbus_read_tuples(device_t dev, device_t child, u_int8_t *tuples, int len)
+cardbus_read_tuple(device_t dev, device_t child, u_int32_t *space,
+ u_int32_t *off, int *tupleid, int *len,
+ u_int8_t *tupledata)
{
- u_int32_t cis_ptr = pci_read_config(child, CARDBUS_CIS_REG, 4);
- int cardbus_space = cis_ptr & CARDBUS_CIS_ASIMASK;
- int ret = 0;
- cis_ptr = cis_ptr & CARDBUS_CIS_ADDRMASK;
-
- switch(cardbus_space) {
+ switch(*space) {
case CARDBUS_CIS_ASI_TUPLE:
- ret = cardbus_read_tuples_conf(dev, child, cis_ptr, tuples,
- len);
- break;
+ return cardbus_read_tuple_conf(dev, child, space, off,
+ tupleid, len, tupledata);
case CARDBUS_CIS_ASI_BAR0:
case CARDBUS_CIS_ASI_BAR1:
case CARDBUS_CIS_ASI_BAR2:
@@ -451,27 +426,61 @@ cardbus_read_tuples(device_t dev, device_t child, u_int8_t *tuples, int len)
case CARDBUS_CIS_ASI_BAR4:
case CARDBUS_CIS_ASI_BAR5:
case CARDBUS_CIS_ASI_ROM:
- ret = cardbus_read_tuples_mem(dev, child, cardbus_space,
- cis_ptr, tuples, len);
- break;
+ return cardbus_read_tuple_mem(dev, child, space, off,
+ tupleid, len, tupledata);
default:
device_printf(dev, "Unable to read CIS: Unknown space: %d\n",
- cardbus_space);
- ret = EINVAL;
+ *space);
+ return EINVAL;
}
- return ret;
+}
+
+static int
+decode_tuple(device_t dev, device_t child, int tupleid, int len,
+ u_int8_t *tupledata, u_int32_t *space, u_int32_t *off)
+{
+ 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,
+ tupledata, space, off,
+ &tupleinfo[i]);
+ }
+
+ return decode_tuple_generic(dev, child, tupleid, len, tupledata,
+ space, off, NULL);
}
int
cardbus_do_cis(device_t dev, device_t child)
{
u_int8_t tupledata[MAXTUPLESIZE];
- int ret;
-
+ int tupleid;
+ int len;
+ int expect_linktarget;
+ u_int32_t space, off;
+
bzero(tupledata, MAXTUPLESIZE);
+ expect_linktarget = TRUE;
+ off = pci_read_config(child, CARDBUS_CIS_REG, 4);
+ space = off & CARDBUS_CIS_ASIMASK;
+ off &= CARDBUS_CIS_ADDRMASK;
- ret = cardbus_read_tuples(dev, child, tupledata, MAXTUPLESIZE);
- if (ret != 0) return ret;
- return decode_tuples(dev, child, tupledata, MAXTUPLESIZE);
+ do {
+ cardbus_read_tuple(dev, child, &space, &off, &tupleid, &len,
+ tupledata);
+
+ if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
+ device_printf(dev, "Expecting link target, got 0x%x\n",
+ tupleid);
+ return EINVAL;
+ }
+ expect_linktarget = decode_tuple(dev, child, tupleid, len,
+ tupledata, &space, &off);
+ if (expect_linktarget != 0)
+ return expect_linktarget;
+ } while (tupleid != CISTPL_END);
+ return 0;
}
OpenPOWER on IntegriCloud