Deleted Added
full compact
cardbus_cis.c (82375) cardbus_cis.c (82378)
1/*
2 * Copyright (c) 2000,2001 Jonathan Chen.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
1/*
2 * Copyright (c) 2000,2001 Jonathan Chen.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/dev/cardbus/cardbus_cis.c 82375 2001-08-26 23:55:34Z jon $
28 * $FreeBSD: head/sys/dev/cardbus/cardbus_cis.c 82378 2001-08-27 00:09:42Z jon $
29 */
30
31/*
32 * CIS Handling for the Cardbus Bus
33 */
34
35#define CARDBUS_DEBUG
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#include <sys/malloc.h>
41
42#include <sys/bus.h>
43#include <machine/bus.h>
44#include <machine/resource.h>
45#include <sys/rman.h>
46
29 */
30
31/*
32 * CIS Handling for the Cardbus Bus
33 */
34
35#define CARDBUS_DEBUG
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#include <sys/malloc.h>
41
42#include <sys/bus.h>
43#include <machine/bus.h>
44#include <machine/resource.h>
45#include <sys/rman.h>
46
47#include
47#include <dev/pci/pcivar.h>
48#include <dev/pci/pcireg.h>
49#include <sys/pciio.h>
48
49#include <dev/cardbus/cardbusreg.h>
50
51#include <dev/cardbus/cardbusreg.h>
52#include <dev/cardbus/cardbusvar.h>
50#include <dev/cardbus/cardbus_cis.h>
51
52#include "card_if.h"
53
54#if defined CARDBUS_DEBUG
55#define DPRINTF(a) printf a
56#define DEVPRINTF(x) device_printf x
57#else
58#define DPRINTF(a)
59#define DEVPRINTF(x)
60#endif
61
62#if !defined(lint)
63static const char rcsid[] =
53#include <dev/cardbus/cardbus_cis.h>
54
55#include "card_if.h"
56
57#if defined CARDBUS_DEBUG
58#define DPRINTF(a) printf a
59#define DEVPRINTF(x) device_printf x
60#else
61#define DPRINTF(a)
62#define DEVPRINTF(x)
63#endif
64
65#if !defined(lint)
66static const char rcsid[] =
64 "$FreeBSD: head/sys/dev/cardbus/cardbus_cis.c 82375 2001-08-26 23:55:34Z jon $";
67 "$FreeBSD: head/sys/dev/cardbus/cardbus_cis.c 82378 2001-08-27 00:09:42Z jon $";
65#endif
66
67#define DECODE_PARAMS \
68 (device_t cbdev, device_t child, int id, int len, \
68#endif
69
70#define DECODE_PARAMS \
71 (device_t cbdev, device_t child, int id, int len, \
69 u_int8_t *tupledata, u_int32_t *start, u_int32_t *off, \
72 u_int8_t *tupledata, u_int32_t start, u_int32_t *off, \
70 struct tuple_callbacks *info)
71
72struct tuple_callbacks {
73 int id;
74 char *name;
75 int (*func) DECODE_PARAMS;
76};
77

--- 5 unchanged lines hidden (view full) ---

83DECODE_PROTOTYPE(vers_1);
84DECODE_PROTOTYPE(funcid);
85DECODE_PROTOTYPE(manfid);
86DECODE_PROTOTYPE(funce);
87DECODE_PROTOTYPE(bar);
88DECODE_PROTOTYPE(unhandled);
89DECODE_PROTOTYPE(end);
90static int cardbus_read_tuple_conf(device_t cbdev, device_t child,
73 struct tuple_callbacks *info)
74
75struct tuple_callbacks {
76 int id;
77 char *name;
78 int (*func) DECODE_PARAMS;
79};
80

--- 5 unchanged lines hidden (view full) ---

86DECODE_PROTOTYPE(vers_1);
87DECODE_PROTOTYPE(funcid);
88DECODE_PROTOTYPE(manfid);
89DECODE_PROTOTYPE(funce);
90DECODE_PROTOTYPE(bar);
91DECODE_PROTOTYPE(unhandled);
92DECODE_PROTOTYPE(end);
93static int cardbus_read_tuple_conf(device_t cbdev, device_t child,
91 u_int32_t *start, u_int32_t *off, int *tupleid, int *len,
94 u_int32_t start, u_int32_t *off, int *tupleid, int *len,
92 u_int8_t *tupledata);
95 u_int8_t *tupledata);
93static int cardbus_read_tuple_exrom(device_t cbdev, struct resource *mem,
94 u_int32_t *start, u_int32_t *off, int *tupleid, int *len,
96static int cardbus_read_tuple_mem(device_t cbdev, struct resource *res,
97 u_int32_t start, u_int32_t *off, int *tupleid, int *len,
95 u_int8_t *tupledata);
98 u_int8_t *tupledata);
96static int cardbus_read_tuple_mem(device_t cbdev, device_t child,
97 u_int32_t *start, u_int32_t *off, int *tupleid, int *len,
98 u_int8_t *tupledata);
99static int cardbus_read_tuple(device_t cbdev, device_t child,
99static int cardbus_read_tuple(device_t cbdev, device_t child,
100 u_int32_t *start, u_int32_t *off, int *tupleid, int *len,
101 u_int8_t *tupledata);
100 struct resource *res, u_int32_t start, u_int32_t *off,
101 int *tupleid, int *len, u_int8_t *tupledata);
102static void cardbus_read_tuple_finish(device_t cbdev, device_t child,
103 int rid, struct resource *res);
104static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child,
105 u_int32_t *start, int *rid);
102static int decode_tuple(device_t cbdev, device_t child, int tupleid,
106static int decode_tuple(device_t cbdev, device_t child, int tupleid,
103 int len, u_int8_t *tupledata, u_int32_t *start,
107 int len, u_int8_t *tupledata, u_int32_t start,
104 u_int32_t *off, struct tuple_callbacks *callbacks);
105static int cardbus_parse_cis(device_t cbdev, device_t child,
106 struct tuple_callbacks *callbacks);
108 u_int32_t *off, struct tuple_callbacks *callbacks);
109static int cardbus_parse_cis(device_t cbdev, device_t child,
110 struct tuple_callbacks *callbacks);
111static int barsort(const void *a, const void *b);
112static int cardbus_alloc_resources(device_t cbdev, device_t child);
113static void cardbus_add_map(device_t cbdev, device_t child, int reg);
114static void cardbus_pickup_maps(device_t cbdev, device_t child);
107
115
116
108#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
109
110static char *funcnames[] = {
111 "Multi-Functioned",
112 "Memory",
113 "Serial Port",
114 "Parallel Port",
115 "Fixed Disk",
116 "Video Adaptor",
117 "Network Adaptor",
118 "AIMS",
119 "SCSI",
120 "Security"
121};
122
117#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
118
119static char *funcnames[] = {
120 "Multi-Functioned",
121 "Memory",
122 "Serial Port",
123 "Parallel Port",
124 "Fixed Disk",
125 "Video Adaptor",
126 "Network Adaptor",
127 "AIMS",
128 "SCSI",
129 "Security"
130};
131
132struct cardbus_quirk {
133 u_int32_t devid; /* Vendor/device of the card */
134 int type;
135#define CARDBUS_QUIRK_MAP_REG 1 /* PCI map register in weird place */
136 int arg1;
137 int arg2;
138};
139
140struct cardbus_quirk cardbus_quirks[] = {
141 { 0 }
142};
143
123static struct cis_tupleinfo *cisread_buf;
124static int ncisread_buf;
125
126/*
127 * Handler functions for various CIS tuples
128 */
129
130DECODE_PROTOTYPE(generic)

--- 122 unchanged lines hidden (view full) ---

253}
254
255DECODE_PROTOTYPE(bar)
256{
257 if (len != 6) {
258 printf("*** ERROR *** BAR length not 6 (%d)\n", len);
259 return EINVAL;
260 } else {
144static struct cis_tupleinfo *cisread_buf;
145static int ncisread_buf;
146
147/*
148 * Handler functions for various CIS tuples
149 */
150
151DECODE_PROTOTYPE(generic)

--- 122 unchanged lines hidden (view full) ---

274}
275
276DECODE_PROTOTYPE(bar)
277{
278 if (len != 6) {
279 printf("*** ERROR *** BAR length not 6 (%d)\n", len);
280 return EINVAL;
281 } else {
282 struct cardbus_devinfo *dinfo = device_get_ivars(child);
261 int type;
262 int reg;
263 u_int32_t bar;
283 int type;
284 int reg;
285 u_int32_t bar;
264 u_int32_t len;
265 struct resource *res;
266
267 reg = *(u_int16_t*)tupledata;
268 len = *(u_int32_t*)(tupledata + 2);
269 if (reg & TPL_BAR_REG_AS) {
270 type = SYS_RES_IOPORT;
271 } else {
272 type = SYS_RES_MEMORY;
273 }
274 bar = (reg & TPL_BAR_REG_ASI_MASK) - 1;
275 if (bar < 0 || bar > 5 ||
276 (type == SYS_RES_IOPORT && bar == 5)) {
277 device_printf(cbdev, "Invalid BAR number: %02x(%02x)\n",
278 reg, bar);
279 return 0;
280 }
281 bar = CARDBUS_BASE0_REG + bar * 4;
286
287 reg = *(u_int16_t*)tupledata;
288 len = *(u_int32_t*)(tupledata + 2);
289 if (reg & TPL_BAR_REG_AS) {
290 type = SYS_RES_IOPORT;
291 } else {
292 type = SYS_RES_MEMORY;
293 }
294 bar = (reg & TPL_BAR_REG_ASI_MASK) - 1;
295 if (bar < 0 || bar > 5 ||
296 (type == SYS_RES_IOPORT && bar == 5)) {
297 device_printf(cbdev, "Invalid BAR number: %02x(%02x)\n",
298 reg, bar);
299 return 0;
300 }
301 bar = CARDBUS_BASE0_REG + bar * 4;
282 DEVPRINTF((cbdev, "Opening BAR: type=%s, bar=%02x, len=%04x\n",
283 (type==SYS_RES_MEMORY)?"MEM":"IO", bar, len));
284 res = bus_generic_alloc_resource(child, child, type, &bar, 0,
285 ~0, len, rman_make_alignment_flags(len) | RF_ACTIVE);
286 if (res == NULL) {
287 device_printf(cbdev, "Cannot allocate BAR %02x\n", bar);
302 if (type == SYS_RES_MEMORY) {
303 if (bar & TPL_BAR_REG_PREFETCHABLE)
304 dinfo->mprefetchable |= BARBIT(bar);
305 if (bar & TPL_BAR_REG_BELOW1MB)
306 dinfo->mbelow1mb |= BARBIT(bar);
307 } else if (type == SYS_RES_IOPORT) {
308 if (bar & TPL_BAR_REG_BELOW1MB)
309 dinfo->ibelow1mb |= BARBIT(bar);
288 }
310 }
311 DEVPRINTF((cbdev, "Opening BAR: type=%s, bar=%02x, "
312 "len=%04x%s%s\n",
313 (type==SYS_RES_MEMORY)?"MEM":"IO", bar, len,
314 (type==SYS_RES_MEMORY&&dinfo->mprefetchable&BARBIT(bar))?
315 " (Prefetchable)":"",
316 type==SYS_RES_MEMORY?
317 ((dinfo->mbelow1mb&BARBIT(bar))?" (Below 1Mb)":"")
318 :(dinfo->ibelow1mb&BARBIT(bar))?" (Below 1Mb)":""
319 ));
320
321 resource_list_add(&dinfo->resources, type, bar, 0UL, ~0UL, len);
289 }
290 return 0;
291}
292
293DECODE_PROTOTYPE(unhandled)
294{
295 printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
296 return -1;

--- 5 unchanged lines hidden (view full) ---

302 return 0;
303}
304
305/*
306 * Functions to read the a tuple from the card
307 */
308
309static int
322 }
323 return 0;
324}
325
326DECODE_PROTOTYPE(unhandled)
327{
328 printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
329 return -1;

--- 5 unchanged lines hidden (view full) ---

335 return 0;
336}
337
338/*
339 * Functions to read the a tuple from the card
340 */
341
342static int
310cardbus_read_tuple_conf(device_t cbdev, device_t child, u_int32_t *start,
343cardbus_read_tuple_conf(device_t cbdev, device_t child, u_int32_t start,
311 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata)
312{
313 int i, j;
314 u_int32_t e;
315 u_int32_t loc;
316
344 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata)
345{
346 int i, j;
347 u_int32_t e;
348 u_int32_t loc;
349
317 loc = CARDBUS_CIS_ADDR(*start) + *off;
350 loc = start + *off;
318
319 e = pci_read_config(child, loc - loc % 4, 4);
320 for (j = loc % 4; j > 0; j--)
321 e >>= 8;
322 *len = 0;
323 for (i = loc, j = -2; j < *len; j++, i++) {
324 if (i % 4 == 0)
325 e = pci_read_config(child, i, 4);

--- 5 unchanged lines hidden (view full) ---

331 tupledata[j] = 0xff & e;
332 e >>= 8;
333 }
334 *off += *len + 2;
335 return 0;
336}
337
338static int
351
352 e = pci_read_config(child, loc - loc % 4, 4);
353 for (j = loc % 4; j > 0; j--)
354 e >>= 8;
355 *len = 0;
356 for (i = loc, j = -2; j < *len; j++, i++) {
357 if (i % 4 == 0)
358 e = pci_read_config(child, i, 4);

--- 5 unchanged lines hidden (view full) ---

364 tupledata[j] = 0xff & e;
365 e >>= 8;
366 }
367 *off += *len + 2;
368 return 0;
369}
370
371static int
339cardbus_read_tuple_exrom(device_t cbdev, struct resource *mem, u_int32_t *start,
372cardbus_read_tuple_mem(device_t cbdev, struct resource *res, u_int32_t start,
340 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata)
341{
373 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata)
374{
342#define READROM(rom, type, offset) \
343 (*((u_int ## type ##_t *)(((unsigned char*)rom) + offset)))
375 bus_space_tag_t bt;
376 bus_space_handle_t bh;
377 int ret;
344
378
345 int romnum = 0;
346 unsigned char *data;
347 u_int32_t imagesize;
348 unsigned char *image;
349 int imagenum;
379 bt = rman_get_bustag(res);
380 bh = rman_get_bushandle(res);
350
381
351 image = (unsigned char*)rman_get_virtual(mem);
352 imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start);
353 do {
354 if (READROM(image, 16, CARDBUS_EXROM_SIGNATURE) != 0xaa55) {
355 device_printf(cbdev, "Bad header in rom %d: %04x\n",
356 romnum, *(u_int16_t*)(image +
357 CARDBUS_EXROM_SIGNATURE));
358 return ENXIO;
359 }
360 data = image + READROM(image, 16, CARDBUS_EXROM_DATA_PTR);
361 imagesize = READROM(data, 16, CARDBUS_EXROM_DATA_IMAGE_LENGTH);
362
363 if (imagesize == 0) {
364 /*
365 * XXX some ROMs seem to have this as zero,
366 * can we assume this means 1 block?
367 */
368 imagesize = 1;
369 }
370 imagesize <<= 9;
371
372 if (imagenum == romnum) {
373 image += CARDBUS_CIS_ADDR(*start) + *off;
374 *tupleid = image[0];
375 *len = image[1];
376 memcpy(tupledata, image+2, *len);
377 *off += *len+2;
378 return 0;
379 }
380 image += imagesize;
381 romnum++;
382 } while ((READROM(data, 8, CARDBUS_EXROM_DATA_INDICATOR) & 0x80) == 0);
383 device_printf(cbdev, "Cannot read CIS: Not enough images of rom\n");
384 return ENOENT;
385#undef READROM
382 *tupleid = bus_space_read_1(bt, bh, start + *off);
383 *len = bus_space_read_1(bt, bh, start + *off + 1);
384 bus_space_read_region_1(bt, bh, *off + start + 2, tupledata, *len);
385 ret = 0;
386 *off += *len + 2;
387 return ret;
386}
387
388static int
388}
389
390static int
389cardbus_read_tuple_mem(device_t cbdev, device_t child, u_int32_t *start,
390 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata)
391cardbus_read_tuple(device_t cbdev, device_t child, struct resource *res,
392 u_int32_t start, u_int32_t *off, int *tupleid, int *len,
393 u_int8_t *tupledata)
391{
394{
392 struct resource *mem;
393 bus_space_tag_t bt;
394 bus_space_handle_t bh;
395 int rid;
396 int ret;
397
398 if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) {
399 rid = CARDBUS_ROM_REG;
395 if (res == (struct resource*)~0UL) {
396 return cardbus_read_tuple_conf(cbdev, child, start, off,
397 tupleid, len, tupledata);
400 } else {
398 } else {
401 rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4;
399 return cardbus_read_tuple_mem(cbdev, res, start, off,
400 tupleid, len, tupledata);
402 }
401 }
402}
403
403
404 mem = bus_alloc_resource(child, SYS_RES_MEMORY, &rid, 0, ~0,
405 1, RF_ACTIVE);
406 bt = rman_get_bustag(mem);
407 bh = rman_get_bushandle(mem);
408 if (mem == NULL) {
409 device_printf(cbdev, "Failed to get memory for CIS reading\n");
410 return ENOMEM;
404static void
405cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
406 struct resource *res)
407{
408 if (res != (struct resource*)~0UL) {
409 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
410 pci_write_config(child, rid, 0, 4);
411 PCI_DISABLE_IO(cbdev, child, SYS_RES_MEMORY);
411 }
412 }
412
413 if(CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) {
414 ret = cardbus_read_tuple_exrom(cbdev, mem, start, off, tupleid,
415 len, tupledata);
416 } else {
417 *tupleid = bus_space_read_1(bt, bh,
418 CARDBUS_CIS_ADDR(*start) + *off);
419 *len = bus_space_read_1(bt, bh,
420 CARDBUS_CIS_ADDR(*start) + *off + 1);
421 bus_space_read_multi_1(rman_get_bustag(mem),
422 rman_get_bushandle(mem),
423 *off + CARDBUS_CIS_ADDR(*start), tupledata, *len);
424 ret = 0;
425 *off += *len+2;
426 }
427 bus_release_resource(child, SYS_RES_MEMORY, rid, mem);
428 return ret;
429}
430
413}
414
431static int
432cardbus_read_tuple(device_t cbdev, device_t child, u_int32_t *start,
433 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata)
415static struct resource *
416cardbus_read_tuple_init(device_t cbdev, device_t child, u_int32_t *start,
417 int *rid)
434{
418{
435 switch(CARDBUS_CIS_SPACE(*start)) {
419 u_int32_t testval;
420 u_int32_t size;
421 struct resource *res;
422
423 switch (CARDBUS_CIS_SPACE(*start)) {
436 case CARDBUS_CIS_ASI_TUPLE:
424 case CARDBUS_CIS_ASI_TUPLE:
437 return cardbus_read_tuple_conf(cbdev, child, start, off,
438 tupleid, len, tupledata);
425 /* CIS in tuple space need no initialization */
426 return (struct resource*)~0UL;
439 case CARDBUS_CIS_ASI_BAR0:
440 case CARDBUS_CIS_ASI_BAR1:
441 case CARDBUS_CIS_ASI_BAR2:
442 case CARDBUS_CIS_ASI_BAR3:
443 case CARDBUS_CIS_ASI_BAR4:
444 case CARDBUS_CIS_ASI_BAR5:
427 case CARDBUS_CIS_ASI_BAR0:
428 case CARDBUS_CIS_ASI_BAR1:
429 case CARDBUS_CIS_ASI_BAR2:
430 case CARDBUS_CIS_ASI_BAR3:
431 case CARDBUS_CIS_ASI_BAR4:
432 case CARDBUS_CIS_ASI_BAR5:
433 *rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4;
434 pci_write_config(child, *rid, ~0UL, 4);
435 break;
445 case CARDBUS_CIS_ASI_ROM:
436 case CARDBUS_CIS_ASI_ROM:
446 return cardbus_read_tuple_mem(cbdev, child, start, off,
447 tupleid, len, tupledata);
437 *rid = CARDBUS_ROM_REG;
438 pci_write_config(child, *rid, CARDBUS_ROM_ADDRMASK, 4);
439 break;
448 default:
449 device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
450 CARDBUS_CIS_SPACE(*start));
440 default:
441 device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
442 CARDBUS_CIS_SPACE(*start));
451 return EINVAL;
443 return NULL;
452 }
444 }
445
446 /* figure out how much space we need */
447 testval = pci_read_config(child, *rid, 4);
448 if (testval & 1) {
449 device_printf(cbdev, "CIS Space is IO, expecting memory.\n");
450 return NULL;
451 }
452 size = CARDBUS_MAPREG_MEM_SIZE(testval);
453 if (size < 4096)
454 size = 4096;
455 /* allocate the memory space to read CIS */
456 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, size,
457 rman_make_alignment_flags(size) | RF_ACTIVE);
458 if (res == NULL) {
459 device_printf(cbdev, "Unable to allocate resource "
460 "to read CIS.\n");
461 return NULL;
462 }
463 pci_write_config(child, *rid,
464 rman_get_start(res) | ((*rid == CARDBUS_ROM_REG)?
465 CARDBUS_ROM_ENABLE : 0),
466 4);
467 PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY);
468
469 /* Flip to the right ROM image if CIS is in ROM */
470 if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) {
471 bus_space_tag_t bt;
472 bus_space_handle_t bh;
473 int imagenum;
474 u_int32_t imagesize;
475 int mystart = 0;
476 int romnum = 0;
477 int dataptr;
478
479 bt = rman_get_bustag(res);
480 bh = rman_get_bushandle(res);
481
482 imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start);
483 for (romnum = 0;; romnum++) {
484 if (bus_space_read_2(bt, bh,
485 mystart+CARDBUS_EXROM_SIGNATURE) != 0xaa55) {
486 device_printf(cbdev, "Bad header in rom %d: "
487 "[%x] %04x\n", romnum, mystart +
488 CARDBUS_EXROM_SIGNATURE,
489 bus_space_read_2(bt, bh,
490 mystart+CARDBUS_EXROM_SIGNATURE));
491 bus_release_resource(cbdev, SYS_RES_MEMORY,
492 *rid, res);
493 *rid = 0;
494 return NULL;
495 }
496 dataptr = mystart + bus_space_read_2(bt, bh,
497 mystart + CARDBUS_EXROM_DATA_PTR);
498 imagesize = bus_space_read_2(bt, bh,
499 dataptr + CARDBUS_EXROM_DATA_IMAGE_LENGTH);
500
501 if (imagesize == 0) {
502 /*
503 * XXX some ROMs seem to have this as zero,
504 * can we assume this means 1 block?
505 */
506 imagesize = 1;
507 }
508 imagesize <<= 9;
509
510 if (romnum == imagenum)
511 break;
512 if ((bus_space_read_1(bt, bh, mystart +
513 CARDBUS_EXROM_DATA_INDICATOR) & 0x80) == 0) {
514 device_printf(cbdev, "Cannot read CIS: "
515 "Not enough images of rom\n");
516 return NULL;
517 }
518 mystart += imagesize;
519 }
520 *start = mystart + CARDBUS_CIS_ADDR(*start);
521 } else {
522 *start = CARDBUS_CIS_SPACE(*start);
523 }
524 return res;
453}
454
455/*
456 * Dispatch the right handler function per tuple
457 */
458
459static int
460decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
525}
526
527/*
528 * Dispatch the right handler function per tuple
529 */
530
531static int
532decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
461 u_int8_t *tupledata, u_int32_t *start, u_int32_t *off,
533 u_int8_t *tupledata, u_int32_t start, u_int32_t *off,
462 struct tuple_callbacks *callbacks)
463{
464 int i;
465 for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
466 if (tupleid == callbacks[i].id)
467 return callbacks[i].func(cbdev, child, tupleid, len,
468 tupledata, start, off, &callbacks[i]);
469 }

--- 11 unchanged lines hidden (view full) ---

481cardbus_parse_cis(device_t cbdev, device_t child,
482 struct tuple_callbacks *callbacks)
483{
484 u_int8_t tupledata[MAXTUPLESIZE];
485 int tupleid;
486 int len;
487 int expect_linktarget;
488 u_int32_t start, off;
534 struct tuple_callbacks *callbacks)
535{
536 int i;
537 for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
538 if (tupleid == callbacks[i].id)
539 return callbacks[i].func(cbdev, child, tupleid, len,
540 tupledata, start, off, &callbacks[i]);
541 }

--- 11 unchanged lines hidden (view full) ---

553cardbus_parse_cis(device_t cbdev, device_t child,
554 struct tuple_callbacks *callbacks)
555{
556 u_int8_t tupledata[MAXTUPLESIZE];
557 int tupleid;
558 int len;
559 int expect_linktarget;
560 u_int32_t start, off;
561 struct resource *res;
562 int rid;
489
490 bzero(tupledata, MAXTUPLESIZE);
491 expect_linktarget = TRUE;
492 start = pci_read_config(child, CARDBUS_CIS_REG, 4);
493 off = 0;
563
564 bzero(tupledata, MAXTUPLESIZE);
565 expect_linktarget = TRUE;
566 start = pci_read_config(child, CARDBUS_CIS_REG, 4);
567 off = 0;
568 res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
569 if (res == NULL)
570 return ENXIO;
494 do {
571 do {
495 cardbus_read_tuple(cbdev, child, &start, &off, &tupleid, &len,
496 tupledata);
572 if (0 != cardbus_read_tuple(cbdev, child, res, start, &off,
573 &tupleid, &len, tupledata)) {
574 device_printf(cbdev, "Failed to read CIS.\n");
575 cardbus_read_tuple_finish(cbdev, child, rid, res);
576 return ENXIO;
577 }
497
498 if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
499 device_printf(cbdev, "Expecting link target, got 0x%x\n",
500 tupleid);
578
579 if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
580 device_printf(cbdev, "Expecting link target, got 0x%x\n",
581 tupleid);
582 cardbus_read_tuple_finish(cbdev, child, rid, res);
501 return EINVAL;
502 }
503 expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
583 return EINVAL;
584 }
585 expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
504 tupledata, &start, &off,
505 callbacks);
506 if (expect_linktarget != 0)
586 tupledata, start, &off, callbacks);
587 if (expect_linktarget != 0) {
588 cardbus_read_tuple_finish(cbdev, child, rid, res);
507 return expect_linktarget;
589 return expect_linktarget;
590 }
508 } while (tupleid != CISTPL_END);
591 } while (tupleid != CISTPL_END);
592 cardbus_read_tuple_finish(cbdev, child, rid, res);
509 return 0;
510}
511
593 return 0;
594}
595
596static int
597barsort(const void *a, const void *b)
598{
599 return (*(const struct resource_list_entry **)b)->count -
600 (*(const struct resource_list_entry **)a)->count;
601}
602
603static int
604cardbus_alloc_resources(device_t cbdev, device_t child)
605{
606 struct cardbus_devinfo *dinfo = device_get_ivars(child);
607 int count;
608 struct resource_list_entry *rle;
609 struct resource_list_entry **barlist;
610 int tmp;
611 u_int32_t mem_psize = 0, mem_nsize = 0, io_size = 0;
612 struct resource *res;
613 u_int32_t start,end;
614 int rid, flags;
615
616 count = 0;
617 SLIST_FOREACH(rle, &dinfo->resources, link) {
618 count++;
619 }
620 if (count == 0)
621 return 0;
622 barlist = malloc(sizeof(struct resource_list_entry*) * count, M_DEVBUF,
623 M_WAITOK);
624 count = 0;
625 SLIST_FOREACH(rle, &dinfo->resources, link) {
626 barlist[count] = rle;
627 if (rle->type == SYS_RES_IOPORT) {
628 io_size += rle->count;
629 } else if (rle->type == SYS_RES_MEMORY) {
630 if (dinfo->mprefetchable & BARBIT(rle->rid))
631 mem_psize += rle->count;
632 else
633 mem_nsize += rle->count;
634 }
635 count++;
636 }
637
638 /*
639 * We want to allocate the largest resource first, so that our
640 * allocated memory is packed.
641 */
642 qsort(barlist, count, sizeof(struct resource_list_entry*), barsort);
643
644 /* Allocate prefetchable memory */
645 flags = 0;
646 for (tmp = 0; tmp < count; tmp++) {
647 if (barlist[tmp]->res == NULL &&
648 barlist[tmp]->type == SYS_RES_MEMORY &&
649 dinfo->mprefetchable & BARBIT(barlist[tmp]->rid)) {
650 flags = rman_make_alignment_flags(barlist[tmp]->count);
651 break;
652 }
653 }
654 if (flags > 0) { /* If any prefetchable memory is requested... */
655 /*
656 * First we allocate one big space for all resources of this
657 * type. We do this because our parent, pccbb, needs to open
658 * a window to forward all addresses within the window, and
659 * it would be best if nobody else has resources allocated
660 * within the window.
661 * (XXX: Perhaps there might be a better way to do this?)
662 */
663 rid = 0;
664 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, &rid, 0,
665 (dinfo->mprefetchable & dinfo->mbelow1mb)?0xFFFFF:~0UL,
666 mem_psize, flags);
667 start = rman_get_start(res);
668 end = rman_get_end(res);
669 DEVPRINTF((cbdev, "Prefetchable memory at %x-%x\n", start, end));
670 /*
671 * Now that we know the region is free, release it and hand it
672 * out piece by piece.
673 */
674 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
675 for (tmp = 0; tmp < count; tmp++) {
676 if (barlist[tmp]->res == NULL &&
677 barlist[tmp]->type == SYS_RES_MEMORY &&
678 dinfo->mprefetchable & BARBIT(barlist[tmp]->rid)) {
679 barlist[tmp]->res = bus_alloc_resource(cbdev,
680 barlist[tmp]->type,
681 &barlist[tmp]->rid, start, end,
682 barlist[tmp]->count,
683 rman_make_alignment_flags(
684 barlist[tmp]->count));
685 if (barlist[tmp]->res == NULL) {
686 mem_nsize += barlist[tmp]->count;
687 dinfo->mprefetchable &=
688 ~BARBIT(barlist[tmp]->rid);
689 DEVPRINTF((cbdev, "Cannot pre-allocate "
690 "prefetchable memory, will try as "
691 "non-prefetchable.\n"));
692 } else {
693 barlist[tmp]->start =
694 rman_get_start(barlist[tmp]->res);
695 barlist[tmp]->end =
696 rman_get_end(barlist[tmp]->res);
697 pci_write_config(child,
698 barlist[tmp]->rid,
699 barlist[tmp]->start, 4);
700 DEVPRINTF((cbdev, "Prefetchable memory "
701 "rid=%x at %lx-%lx\n",
702 barlist[tmp]->rid,
703 barlist[tmp]->start,
704 barlist[tmp]->end));
705 }
706 }
707 }
708 }
709
710 /* Allocate non-prefetchable memory */
711 flags = 0;
712 for (tmp = 0; tmp < count; tmp++) {
713 if (barlist[tmp]->res == NULL &&
714 barlist[tmp]->type == SYS_RES_MEMORY) {
715 flags = rman_make_alignment_flags(barlist[tmp]->count);
716 break;
717 }
718 }
719 if (flags > 0) { /* If any non-prefetchable memory is requested... */
720 /*
721 * First we allocate one big space for all resources of this
722 * type. We do this because our parent, pccbb, needs to open
723 * a window to forward all addresses within the window, and
724 * it would be best if nobody else has resources allocated
725 * within the window.
726 * (XXX: Perhaps there might be a better way to do this?)
727 */
728 rid = 0;
729 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, &rid, 0,
730 ((~dinfo->mprefetchable) & dinfo->mbelow1mb)?0xFFFFF:~0UL,
731 mem_nsize, flags);
732 start = rman_get_start(res);
733 end = rman_get_end(res);
734 DEVPRINTF((cbdev, "Non-prefetchable memory at %x-%x\n",
735 start, end));
736 /*
737 * Now that we know the region is free, release it and hand it
738 * out piece by piece.
739 */
740 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
741 for (tmp = 0; tmp < count; tmp++) {
742 if (barlist[tmp]->res == NULL &&
743 barlist[tmp]->type == SYS_RES_MEMORY) {
744 barlist[tmp]->res = bus_alloc_resource(cbdev,
745 barlist[tmp]->type, &barlist[tmp]->rid,
746 start, end, barlist[tmp]->count,
747 rman_make_alignment_flags(
748 barlist[tmp]->count));
749 if (barlist[tmp]->res == NULL) {
750 DEVPRINTF((cbdev, "Cannot pre-allocate "
751 "memory for cardbus device\n"));
752 return ENOMEM;
753 }
754 barlist[tmp]->start =
755 rman_get_start(barlist[tmp]->res);
756 barlist[tmp]->end = rman_get_end(
757 barlist[tmp]->res);
758 pci_write_config(child, barlist[tmp]->rid,
759 barlist[tmp]->start, 4);
760 DEVPRINTF((cbdev, "Non-prefetchable memory "
761 "rid=%x at %lx-%lx (%lx)\n",
762 barlist[tmp]->rid, barlist[tmp]->start,
763 barlist[tmp]->end, barlist[tmp]->count));
764 }
765 }
766 }
767
768 /* Allocate IO ports */
769 flags = 0;
770 for (tmp = 0; tmp < count; tmp++) {
771 if (barlist[tmp]->res == NULL &&
772 barlist[tmp]->type == SYS_RES_IOPORT) {
773 flags = rman_make_alignment_flags(barlist[tmp]->count);
774 break;
775 }
776 }
777 if (flags > 0) { /* If any IO port is requested... */
778 /*
779 * First we allocate one big space for all resources of this
780 * type. We do this because our parent, pccbb, needs to open
781 * a window to forward all addresses within the window, and
782 * it would be best if nobody else has resources allocated
783 * within the window.
784 * (XXX: Perhaps there might be a better way to do this?)
785 */
786 rid = 0;
787 res = bus_alloc_resource(cbdev, SYS_RES_IOPORT, &rid, 0,
788 (dinfo->ibelow1mb)?0xFFFFF:~0UL, io_size, flags);
789 start = rman_get_start(res);
790 end = rman_get_end(res);
791 DEVPRINTF((cbdev, "IO port at %x-%x\n", start, end));
792 /*
793 * Now that we know the region is free, release it and hand it
794 * out piece by piece.
795 */
796 bus_release_resource(cbdev, SYS_RES_IOPORT, rid, res);
797 for (tmp = 0; tmp < count; tmp++) {
798 if (barlist[tmp]->res == NULL &&
799 barlist[tmp]->type == SYS_RES_IOPORT) {
800 barlist[tmp]->res = bus_alloc_resource(cbdev,
801 barlist[tmp]->type, &barlist[tmp]->rid,
802 start, end, barlist[tmp]->count,
803 rman_make_alignment_flags(
804 barlist[tmp]->count));
805 if (barlist[tmp]->res == NULL) {
806 DEVPRINTF((cbdev, "Cannot pre-allocate "
807 "IO port for cardbus device\n"));
808 return ENOMEM;
809 }
810 barlist[tmp]->start =
811 rman_get_start(barlist[tmp]->res);
812 barlist[tmp]->end =
813 rman_get_end(barlist[tmp]->res);
814 pci_write_config(child, barlist[tmp]->rid,
815 barlist[tmp]->start, 4);
816 DEVPRINTF((cbdev, "IO port rid=%x at %lx-%lx\n",
817 barlist[tmp]->rid, barlist[tmp]->start,
818 barlist[tmp]->end));
819 }
820 }
821 }
822
823 /* Allocate IRQ */
824 /* XXX: Search CIS for IRQ description */
825 rid = 0;
826 res = bus_alloc_resource(cbdev, SYS_RES_IRQ, &rid, 0, ~0UL, 1,
827 RF_SHAREABLE);
828 resource_list_add(&dinfo->resources, SYS_RES_IRQ, rid,
829 rman_get_start(res), rman_get_end(res), 1);
830 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, rid);
831 rle->res = res;
832 dinfo->cfg.intline = rman_get_start(res);
833 pci_write_config(child, PCIR_INTLINE, rman_get_start(res), 1);
834
835 return 0;
836}
837
838/*
839 * Adding a memory/io resource (sans CIS)
840 */
841
842static void
843cardbus_add_map(device_t cbdev, device_t child, int reg)
844{
845 struct cardbus_devinfo *dinfo = device_get_ivars(child);
846 struct resource_list_entry *rle;
847 u_int32_t size;
848 u_int32_t testval;
849 int type;
850
851 SLIST_FOREACH(rle, &dinfo->resources, link) {
852 if (rle->rid == reg)
853 return;
854 }
855
856 if (reg == CARDBUS_ROM_REG)
857 testval = CARDBUS_ROM_ADDRMASK;
858 else
859 testval = ~0;
860
861 pci_write_config(child, reg, testval, 4);
862 testval = pci_read_config(child, reg, 4);
863
864 if (testval == ~0 || testval == 0)
865 return;
866
867 if ((testval & 1) == 0)
868 type = SYS_RES_MEMORY;
869 else
870 type = SYS_RES_IOPORT;
871
872 size = CARDBUS_MAPREG_MEM_SIZE(testval);
873 device_printf(cbdev, "Resource not specified in CIS: id=%x, size=%x\n",
874 reg, size);
875 resource_list_add(&dinfo->resources, type, reg, 0UL, ~0UL, size);
876}
877
878static void
879cardbus_pickup_maps(device_t cbdev, device_t child)
880{
881 struct cardbus_devinfo *dinfo = device_get_ivars(child);
882 struct cardbus_quirk *q;
883 int reg;
884
885 /*
886 * Try to pick up any resources that was not specified in CIS.
887 * Some devices (eg, 3c656) does not list all resources required by
888 * the driver in its CIS.
889 * XXX: should we do this or use quirks?
890 */
891 for (reg = 0; reg < dinfo->cfg.nummaps; reg++) {
892 cardbus_add_map(cbdev, child, PCIR_MAPS + reg * 4);
893 }
894
895 for (q = &cardbus_quirks[0]; q->devid; q++) {
896 if (q->devid == ((dinfo->cfg.device << 16) | dinfo->cfg.vendor)
897 && q->type == CARDBUS_QUIRK_MAP_REG) {
898 cardbus_add_map(cbdev, child, q->arg1);
899 }
900 }
901}
902
512int
513cardbus_cis_read(device_t cbdev, device_t child, u_int8_t id,
514 struct cis_tupleinfo **buff, int *nret)
515{
516 struct tuple_callbacks cisread_callbacks[] = {
517 MAKETUPLE(NULL, nothing),
518 /* first entry will be overwritten */
519 MAKETUPLE(NULL, nothing),

--- 46 unchanged lines hidden (view full) ---

566 ret = cardbus_parse_cis(cbdev, child, cisread_callbacks);
567
568 *buff = cisread_buf;
569 *nret = ncisread_buf;
570 return ret;
571}
572
573void
903int
904cardbus_cis_read(device_t cbdev, device_t child, u_int8_t id,
905 struct cis_tupleinfo **buff, int *nret)
906{
907 struct tuple_callbacks cisread_callbacks[] = {
908 MAKETUPLE(NULL, nothing),
909 /* first entry will be overwritten */
910 MAKETUPLE(NULL, nothing),

--- 46 unchanged lines hidden (view full) ---

957 ret = cardbus_parse_cis(cbdev, child, cisread_callbacks);
958
959 *buff = cisread_buf;
960 *nret = ncisread_buf;
961 return ret;
962}
963
964void
574cardbus_cis_free(device_t cbdev, struct cis_tupleinfo *buff, int* nret)
965cardbus_cis_free(device_t cbdev, struct cis_tupleinfo *buff, int *nret)
575{
576 int i;
577 for (i = 0; i < *nret; i++)
578 free(buff[i].data, M_DEVBUF);
579 if (*nret > 0)
580 free(buff, M_DEVBUF);
581}
582
583int
584cardbus_do_cis(device_t cbdev, device_t child)
585{
966{
967 int i;
968 for (i = 0; i < *nret; i++)
969 free(buff[i].data, M_DEVBUF);
970 if (*nret > 0)
971 free(buff, M_DEVBUF);
972}
973
974int
975cardbus_do_cis(device_t cbdev, device_t child)
976{
977 int ret;
586 struct tuple_callbacks init_callbacks[] = {
587 MAKETUPLE(NULL, generic),
588 MAKETUPLE(DEVICE, generic),
589 MAKETUPLE(LONG_LINK_CB, unhandled),
590 MAKETUPLE(INDIRECT, unhandled),
591 MAKETUPLE(CONFIG_CB, generic),
592 MAKETUPLE(CFTABLE_ENTRY_CB, generic),
593 MAKETUPLE(LONGLINK_MFC, unhandled),

--- 25 unchanged lines hidden (view full) ---

619 MAKETUPLE(GEOMETRY, generic),
620 MAKETUPLE(BYTEORDER, generic),
621 MAKETUPLE(DATE, generic),
622 MAKETUPLE(BATTERY, generic),
623 MAKETUPLE(ORG, generic),
624 MAKETUPLE(END, end),
625 MAKETUPLE(GENERIC, generic),
626 };
978 struct tuple_callbacks init_callbacks[] = {
979 MAKETUPLE(NULL, generic),
980 MAKETUPLE(DEVICE, generic),
981 MAKETUPLE(LONG_LINK_CB, unhandled),
982 MAKETUPLE(INDIRECT, unhandled),
983 MAKETUPLE(CONFIG_CB, generic),
984 MAKETUPLE(CFTABLE_ENTRY_CB, generic),
985 MAKETUPLE(LONGLINK_MFC, unhandled),

--- 25 unchanged lines hidden (view full) ---

1011 MAKETUPLE(GEOMETRY, generic),
1012 MAKETUPLE(BYTEORDER, generic),
1013 MAKETUPLE(DATE, generic),
1014 MAKETUPLE(BATTERY, generic),
1015 MAKETUPLE(ORG, generic),
1016 MAKETUPLE(END, end),
1017 MAKETUPLE(GENERIC, generic),
1018 };
627 return cardbus_parse_cis(cbdev, child, init_callbacks);
1019
1020 ret = cardbus_parse_cis(cbdev, child, init_callbacks);
1021 if (ret < 0)
1022 return ret;
1023 cardbus_pickup_maps(cbdev, child);
1024 return cardbus_alloc_resources(cbdev, child);
628}
1025}