Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/cardbus/cardbus_cis.c
39507 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2000,2001 Jonathan Chen All rights reserved.
5
* Copyright (c) 2005-2008 M. Warner Losh <[email protected]>
6
*
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
#include <sys/cdefs.h>
31
/*
32
* CIS Handling for the Cardbus Bus
33
*/
34
35
#include <sys/param.h>
36
#include <sys/systm.h>
37
#include <sys/kernel.h>
38
#include <sys/malloc.h>
39
40
#include <sys/bus.h>
41
#include <machine/bus.h>
42
#include <machine/resource.h>
43
#include <sys/rman.h>
44
#include <sys/endian.h>
45
46
#include <sys/pciio.h>
47
#include <dev/pci/pcivar.h>
48
#include <dev/pci/pcireg.h>
49
50
#include <dev/pccard/pccardvar.h>
51
#include <dev/pccard/pccard_cis.h>
52
53
#include <dev/cardbus/cardbusreg.h>
54
#include <dev/cardbus/cardbusvar.h>
55
#include <dev/cardbus/cardbus_cis.h>
56
57
extern int cardbus_cis_debug;
58
59
#define DPRINTF(a) if (cardbus_cis_debug) printf a
60
#define DEVPRINTF(x) if (cardbus_cis_debug) device_printf x
61
62
#define CIS_CONFIG_SPACE (struct resource *)~0UL
63
64
static int decode_tuple_generic(device_t cbdev, device_t child, int id,
65
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
66
struct tuple_callbacks *info, void *);
67
static int decode_tuple_linktarget(device_t cbdev, device_t child, int id,
68
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
69
struct tuple_callbacks *info, void *);
70
static int decode_tuple_vers_1(device_t cbdev, device_t child, int id,
71
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
72
struct tuple_callbacks *info, void *);
73
static int decode_tuple_funcid(device_t cbdev, device_t child, int id,
74
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
75
struct tuple_callbacks *info, void *);
76
static int decode_tuple_manfid(device_t cbdev, device_t child, int id,
77
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
78
struct tuple_callbacks *info, void *);
79
static int decode_tuple_funce(device_t cbdev, device_t child, int id,
80
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
81
struct tuple_callbacks *info, void *);
82
static int decode_tuple_bar(device_t cbdev, device_t child, int id,
83
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
84
struct tuple_callbacks *info, void *);
85
static int decode_tuple_unhandled(device_t cbdev, device_t child, int id,
86
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
87
struct tuple_callbacks *info, void *);
88
static int decode_tuple_end(device_t cbdev, device_t child, int id,
89
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
90
struct tuple_callbacks *info, void *);
91
92
static int cardbus_read_tuple_conf(device_t cbdev, device_t child,
93
uint32_t start, uint32_t *off, int *tupleid, int *len,
94
uint8_t *tupledata);
95
static int cardbus_read_tuple_mem(device_t cbdev, struct resource *res,
96
uint32_t start, uint32_t *off, int *tupleid, int *len,
97
uint8_t *tupledata);
98
static int cardbus_read_tuple(device_t cbdev, device_t child,
99
struct resource *res, uint32_t start, uint32_t *off,
100
int *tupleid, int *len, uint8_t *tupledata);
101
static void cardbus_read_tuple_finish(device_t cbdev, device_t child,
102
int rid, struct resource *res);
103
static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child,
104
uint32_t *start, int *rid);
105
static int decode_tuple(device_t cbdev, device_t child, int tupleid,
106
int len, uint8_t *tupledata, uint32_t start,
107
uint32_t *off, struct tuple_callbacks *callbacks,
108
void *);
109
#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
110
111
static char *funcnames[] = {
112
"Multi-Functioned",
113
"Memory",
114
"Serial Port",
115
"Parallel Port",
116
"Fixed Disk",
117
"Video Adaptor",
118
"Network Adaptor",
119
"AIMS",
120
"SCSI",
121
"Security"
122
};
123
124
/*
125
* Handler functions for various CIS tuples
126
*/
127
128
static int
129
decode_tuple_generic(device_t cbdev, device_t child, int id,
130
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
131
struct tuple_callbacks *info, void *argp)
132
{
133
int i;
134
135
if (cardbus_cis_debug) {
136
if (info)
137
printf("TUPLE: %s [%d]:", info->name, len);
138
else
139
printf("TUPLE: Unknown(0x%02x) [%d]:", id, len);
140
141
for (i = 0; i < len; i++) {
142
if (i % 0x10 == 0 && len > 0x10)
143
printf("\n 0x%02x:", i);
144
printf(" %02x", tupledata[i]);
145
}
146
printf("\n");
147
}
148
return (0);
149
}
150
151
static int
152
decode_tuple_linktarget(device_t cbdev, device_t child, int id,
153
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
154
struct tuple_callbacks *info, void *argp)
155
{
156
int i;
157
158
if (cardbus_cis_debug) {
159
printf("TUPLE: %s [%d]:", info->name, len);
160
161
for (i = 0; i < len; i++) {
162
if (i % 0x10 == 0 && len > 0x10)
163
printf("\n 0x%02x:", i);
164
printf(" %02x", tupledata[i]);
165
}
166
printf("\n");
167
}
168
if (len != 3 || tupledata[0] != 'C' || tupledata[1] != 'I' ||
169
tupledata[2] != 'S') {
170
printf("Invalid data for CIS Link Target!\n");
171
decode_tuple_generic(cbdev, child, id, len, tupledata,
172
start, off, info, argp);
173
return (EINVAL);
174
}
175
return (0);
176
}
177
178
static int
179
decode_tuple_vers_1(device_t cbdev, device_t child, int id,
180
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
181
struct tuple_callbacks *info, void *argp)
182
{
183
int i;
184
185
if (cardbus_cis_debug) {
186
printf("Product version: %d.%d\n", tupledata[0], tupledata[1]);
187
printf("Product name: ");
188
for (i = 2; i < len; i++) {
189
if (tupledata[i] == '\0')
190
printf(" | ");
191
else if (tupledata[i] == 0xff)
192
break;
193
else
194
printf("%c", tupledata[i]);
195
}
196
printf("\n");
197
}
198
return (0);
199
}
200
201
static int
202
decode_tuple_funcid(device_t cbdev, device_t child, int id,
203
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
204
struct tuple_callbacks *info, void *argp)
205
{
206
struct cardbus_devinfo *dinfo = device_get_ivars(child);
207
int numnames = nitems(funcnames);
208
int i;
209
210
if (cardbus_cis_debug) {
211
printf("Functions: ");
212
for (i = 0; i < len; i++) {
213
if (tupledata[i] < numnames)
214
printf("%s", funcnames[tupledata[i]]);
215
else
216
printf("Unknown(%d)", tupledata[i]);
217
if (i < len - 1)
218
printf(", ");
219
}
220
printf("\n");
221
}
222
if (len > 0)
223
dinfo->funcid = tupledata[0]; /* use first in list */
224
return (0);
225
}
226
227
static int
228
decode_tuple_manfid(device_t cbdev, device_t child, int id,
229
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
230
struct tuple_callbacks *info, void *argp)
231
{
232
struct cardbus_devinfo *dinfo = device_get_ivars(child);
233
int i;
234
235
if (cardbus_cis_debug) {
236
printf("Manufacturer ID: ");
237
for (i = 0; i < len; i++)
238
printf("%02x", tupledata[i]);
239
printf("\n");
240
}
241
242
if (len == 5) {
243
dinfo->mfrid = tupledata[1] | (tupledata[2] << 8);
244
dinfo->prodid = tupledata[3] | (tupledata[4] << 8);
245
}
246
return (0);
247
}
248
249
static int
250
decode_tuple_funce(device_t cbdev, device_t child, int id,
251
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
252
struct tuple_callbacks *info, void *argp)
253
{
254
struct cardbus_devinfo *dinfo = device_get_ivars(child);
255
int type, i;
256
257
if (cardbus_cis_debug) {
258
printf("Function Extension: ");
259
for (i = 0; i < len; i++)
260
printf("%02x", tupledata[i]);
261
printf("\n");
262
}
263
if (len < 2) /* too short */
264
return (0);
265
type = tupledata[0]; /* XXX <32 always? */
266
switch (dinfo->funcid) {
267
case PCCARD_FUNCTION_NETWORK:
268
switch (type) {
269
case PCCARD_TPLFE_TYPE_LAN_NID:
270
if (tupledata[1] > sizeof(dinfo->funce.lan.nid)) {
271
/* ignore, warning? */
272
return (0);
273
}
274
bcopy(tupledata + 2, dinfo->funce.lan.nid,
275
tupledata[1]);
276
break;
277
}
278
dinfo->fepresent |= 1<<type;
279
break;
280
}
281
return (0);
282
}
283
284
static int
285
decode_tuple_bar(device_t cbdev, device_t child, int id,
286
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
287
struct tuple_callbacks *info, void *argp)
288
{
289
struct cardbus_devinfo *dinfo = device_get_ivars(child);
290
int type;
291
uint8_t reg;
292
uint32_t bar;
293
294
if (len != 6) {
295
device_printf(cbdev, "CIS BAR length not 6 (%d)\n", len);
296
return (EINVAL);
297
}
298
299
reg = *tupledata;
300
len = le32toh(*(uint32_t*)(tupledata + 2));
301
if (reg & TPL_BAR_REG_AS)
302
type = SYS_RES_IOPORT;
303
else
304
type = SYS_RES_MEMORY;
305
306
bar = reg & TPL_BAR_REG_ASI_MASK;
307
if (bar == 0) {
308
device_printf(cbdev, "Invalid BAR type 0 in CIS\n");
309
return (EINVAL); /* XXX Return an error? */
310
} else if (bar == 7) {
311
/* XXX Should we try to map in Option ROMs? */
312
return (0);
313
}
314
315
/* Convert from BAR type to BAR offset */
316
bar = PCIR_BAR(bar - 1);
317
318
if (type == SYS_RES_MEMORY) {
319
if (reg & TPL_BAR_REG_PREFETCHABLE)
320
dinfo->mprefetchable |= (1 << PCI_RID2BAR(bar));
321
/*
322
* The PC Card spec says we're only supposed to honor this
323
* hint when the cardbus bridge is a child of pci0 (the main
324
* bus). The PC Card spec seems to indicate that this should
325
* only be done on x86 based machines, which suggests that on
326
* non-x86 machines the addresses can be anywhere. Since the
327
* hardware can do it on non-x86 machines, it should be able
328
* to do it on x86 machines too. Therefore, we can and should
329
* ignore this hint. Furthermore, the PC Card spec recommends
330
* always allocating memory above 1MB, contradicting the other
331
* part of the PC Card spec, it seems. We make note of it,
332
* but otherwise don't use this information.
333
*
334
* Some Realtek cards have this set in their CIS, but fail
335
* to actually work when mapped this way, and experience
336
* has shown ignoring this big to be a wise choice.
337
*
338
* XXX We should cite chapter and verse for standard refs.
339
*/
340
if (reg & TPL_BAR_REG_BELOW1MB)
341
dinfo->mbelow1mb |= (1 << PCI_RID2BAR(bar));
342
}
343
344
return (0);
345
}
346
347
static int
348
decode_tuple_unhandled(device_t cbdev, device_t child, int id,
349
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
350
struct tuple_callbacks *info, void *argp)
351
{
352
/* Make this message suck less XXX */
353
printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
354
return (EINVAL);
355
}
356
357
static int
358
decode_tuple_end(device_t cbdev, device_t child, int id,
359
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
360
struct tuple_callbacks *info, void *argp)
361
{
362
if (cardbus_cis_debug)
363
printf("CIS reading done\n");
364
return (0);
365
}
366
367
/*
368
* Functions to read the a tuple from the card
369
*/
370
371
/*
372
* Read CIS bytes out of the config space. We have to read it 4 bytes at a
373
* time and do the usual mask and shift to return the bytes. The standard
374
* defines the byte order to be little endian. pci_read_config converts it to
375
* host byte order. This is why we have no endian conversion functions: the
376
* shifts wind up being endian neutral. This is also why we avoid the obvious
377
* memcpy optimization.
378
*/
379
static int
380
cardbus_read_tuple_conf(device_t cbdev, device_t child, uint32_t start,
381
uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
382
{
383
int i, j;
384
uint32_t e;
385
uint32_t loc;
386
387
loc = start + *off;
388
389
e = pci_read_config(child, loc & ~0x3, 4);
390
e >>= 8 * (loc & 0x3);
391
*len = 0;
392
for (i = loc, j = -2; j < *len; j++, i++) {
393
if ((i & 0x3) == 0)
394
e = pci_read_config(child, i, 4);
395
if (j == -2)
396
*tupleid = 0xff & e;
397
else if (j == -1)
398
*len = 0xff & e;
399
else
400
tupledata[j] = 0xff & e;
401
e >>= 8;
402
}
403
*off += *len + 2;
404
return (0);
405
}
406
407
/*
408
* Read the CIS data out of memory. We indirect through the bus space
409
* routines to ensure proper byte ordering conversions when necessary.
410
*/
411
static int
412
cardbus_read_tuple_mem(device_t cbdev, struct resource *res, uint32_t start,
413
uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
414
{
415
int ret;
416
417
*tupleid = bus_read_1(res, start + *off);
418
*len = bus_read_1(res, start + *off + 1);
419
bus_read_region_1(res, *off + start + 2, tupledata, *len);
420
ret = 0;
421
*off += *len + 2;
422
return (ret);
423
}
424
425
static int
426
cardbus_read_tuple(device_t cbdev, device_t child, struct resource *res,
427
uint32_t start, uint32_t *off, int *tupleid, int *len,
428
uint8_t *tupledata)
429
{
430
if (res == CIS_CONFIG_SPACE)
431
return (cardbus_read_tuple_conf(cbdev, child, start, off,
432
tupleid, len, tupledata));
433
return (cardbus_read_tuple_mem(cbdev, res, start, off, tupleid, len,
434
tupledata));
435
}
436
437
static void
438
cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
439
struct resource *res)
440
{
441
if (res != CIS_CONFIG_SPACE) {
442
bus_release_resource(child, SYS_RES_MEMORY, rid, res);
443
bus_delete_resource(child, SYS_RES_MEMORY, rid);
444
}
445
}
446
447
static struct resource *
448
cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
449
int *rid)
450
{
451
struct resource *res;
452
uint32_t space;
453
454
space = *start & PCIM_CIS_ASI_MASK;
455
switch (space) {
456
case PCIM_CIS_ASI_CONFIG:
457
DEVPRINTF((cbdev, "CIS in PCI config space\n"));
458
/* CIS in PCI config space need no initialization */
459
return (CIS_CONFIG_SPACE);
460
case PCIM_CIS_ASI_BAR0:
461
case PCIM_CIS_ASI_BAR1:
462
case PCIM_CIS_ASI_BAR2:
463
case PCIM_CIS_ASI_BAR3:
464
case PCIM_CIS_ASI_BAR4:
465
case PCIM_CIS_ASI_BAR5:
466
*rid = PCIR_BAR(space - PCIM_CIS_ASI_BAR0);
467
DEVPRINTF((cbdev, "CIS in BAR %#x\n", *rid));
468
break;
469
case PCIM_CIS_ASI_ROM:
470
*rid = PCIR_BIOS;
471
DEVPRINTF((cbdev, "CIS in option rom\n"));
472
break;
473
default:
474
device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
475
space);
476
return (NULL);
477
}
478
479
/* allocate the memory space to read CIS */
480
res = bus_alloc_resource_any(child, SYS_RES_MEMORY, rid,
481
rman_make_alignment_flags(4096) | RF_ACTIVE);
482
if (res == NULL) {
483
device_printf(cbdev, "Unable to allocate resource "
484
"to read CIS.\n");
485
return (NULL);
486
}
487
DEVPRINTF((cbdev, "CIS Mapped to %#jx\n",
488
rman_get_start(res)));
489
490
/* Flip to the right ROM image if CIS is in ROM */
491
if (space == PCIM_CIS_ASI_ROM) {
492
uint32_t imagesize;
493
uint32_t imagebase = 0;
494
uint32_t pcidata;
495
uint16_t romsig;
496
int romnum = 0;
497
int imagenum;
498
499
imagenum = (*start & PCIM_CIS_ROM_MASK) >> 28;
500
for (romnum = 0;; romnum++) {
501
romsig = bus_read_2(res,
502
imagebase + CARDBUS_EXROM_SIGNATURE);
503
if (romsig != 0xaa55) {
504
device_printf(cbdev, "Bad header in rom %d: "
505
"[%x] %04x\n", romnum, imagebase +
506
CARDBUS_EXROM_SIGNATURE, romsig);
507
cardbus_read_tuple_finish(cbdev, child, *rid,
508
res);
509
*rid = 0;
510
return (NULL);
511
}
512
513
/*
514
* If this was the Option ROM image that we were
515
* looking for, then we are done.
516
*/
517
if (romnum == imagenum)
518
break;
519
520
/* Find out where the next Option ROM image is */
521
pcidata = imagebase + bus_read_2(res,
522
imagebase + CARDBUS_EXROM_DATA_PTR);
523
imagesize = bus_read_2(res,
524
pcidata + CARDBUS_EXROM_DATA_IMAGE_LENGTH);
525
526
if (imagesize == 0) {
527
/*
528
* XXX some ROMs seem to have this as zero,
529
* can we assume this means 1 block?
530
*/
531
device_printf(cbdev, "Warning, size of Option "
532
"ROM image %d is 0 bytes, assuming 512 "
533
"bytes.\n", romnum);
534
imagesize = 1;
535
}
536
537
/* Image size is in 512 byte units */
538
imagesize <<= 9;
539
540
if ((bus_read_1(res, pcidata +
541
CARDBUS_EXROM_DATA_INDICATOR) & 0x80) != 0) {
542
device_printf(cbdev, "Cannot find CIS in "
543
"Option ROM\n");
544
cardbus_read_tuple_finish(cbdev, child, *rid,
545
res);
546
*rid = 0;
547
return (NULL);
548
}
549
imagebase += imagesize;
550
}
551
*start = imagebase + (*start & PCIM_CIS_ADDR_MASK);
552
} else {
553
*start = *start & PCIM_CIS_ADDR_MASK;
554
}
555
DEVPRINTF((cbdev, "CIS offset is %#x\n", *start));
556
557
return (res);
558
}
559
560
/*
561
* Dispatch the right handler function per tuple
562
*/
563
564
static int
565
decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
566
uint8_t *tupledata, uint32_t start, uint32_t *off,
567
struct tuple_callbacks *callbacks, void *argp)
568
{
569
int i;
570
for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
571
if (tupleid == callbacks[i].id)
572
return (callbacks[i].func(cbdev, child, tupleid, len,
573
tupledata, start, off, &callbacks[i], argp));
574
}
575
return (callbacks[i].func(cbdev, child, tupleid, len,
576
tupledata, start, off, NULL, argp));
577
}
578
579
int
580
cardbus_parse_cis(device_t cbdev, device_t child,
581
struct tuple_callbacks *callbacks, void *argp)
582
{
583
uint8_t *tupledata;
584
int tupleid = CISTPL_NULL;
585
int len;
586
int expect_linktarget;
587
uint32_t start, off;
588
struct resource *res;
589
int rid;
590
591
tupledata = malloc(MAXTUPLESIZE, M_DEVBUF, M_WAITOK | M_ZERO);
592
expect_linktarget = TRUE;
593
if ((start = pci_read_config(child, PCIR_CIS, 4)) == 0) {
594
DEVPRINTF((cbdev, "Warning: CIS pointer is 0: (no CIS)\n"));
595
free(tupledata, M_DEVBUF);
596
return (0);
597
}
598
DEVPRINTF((cbdev, "CIS pointer is %#x\n", start));
599
off = 0;
600
res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
601
if (res == NULL) {
602
device_printf(cbdev, "Unable to allocate resources for CIS\n");
603
free(tupledata, M_DEVBUF);
604
return (ENXIO);
605
}
606
607
do {
608
if (cardbus_read_tuple(cbdev, child, res, start, &off,
609
&tupleid, &len, tupledata) != 0) {
610
device_printf(cbdev, "Failed to read CIS.\n");
611
cardbus_read_tuple_finish(cbdev, child, rid, res);
612
free(tupledata, M_DEVBUF);
613
return (ENXIO);
614
}
615
616
if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
617
device_printf(cbdev, "Expecting link target, got 0x%x\n",
618
tupleid);
619
cardbus_read_tuple_finish(cbdev, child, rid, res);
620
free(tupledata, M_DEVBUF);
621
return (EINVAL);
622
}
623
expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
624
tupledata, start, &off, callbacks, argp);
625
if (expect_linktarget != 0) {
626
device_printf(cbdev, "Parsing failed with %d\n",
627
expect_linktarget);
628
cardbus_read_tuple_finish(cbdev, child, rid, res);
629
free(tupledata, M_DEVBUF);
630
return (expect_linktarget);
631
}
632
} while (tupleid != CISTPL_END);
633
cardbus_read_tuple_finish(cbdev, child, rid, res);
634
free(tupledata, M_DEVBUF);
635
return (0);
636
}
637
638
int
639
cardbus_do_cis(device_t cbdev, device_t child)
640
{
641
struct tuple_callbacks init_callbacks[] = {
642
MAKETUPLE(LONGLINK_CB, unhandled),
643
MAKETUPLE(INDIRECT, unhandled),
644
MAKETUPLE(LONGLINK_MFC, unhandled),
645
MAKETUPLE(BAR, bar),
646
MAKETUPLE(LONGLINK_A, unhandled),
647
MAKETUPLE(LONGLINK_C, unhandled),
648
MAKETUPLE(LINKTARGET, linktarget),
649
MAKETUPLE(VERS_1, vers_1),
650
MAKETUPLE(MANFID, manfid),
651
MAKETUPLE(FUNCID, funcid),
652
MAKETUPLE(FUNCE, funce),
653
MAKETUPLE(END, end),
654
MAKETUPLE(GENERIC, generic),
655
};
656
657
return (cardbus_parse_cis(cbdev, child, init_callbacks, NULL));
658
}
659
660