diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2009-10-18 17:54:24 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2009-11-08 12:23:05 -0500 |
commit | dddfbd824b96a25da0b2f1cf35c0be33ef2422fe (patch) | |
tree | 0f48f2883bd00ec5f15d8d32a3c826a3184f47ba /drivers | |
parent | 91284224da5b15ec6c2b45e10fa5eccd1c92a204 (diff) |
pcmcia: convert net pcmcia drivers to use new CIS helpers
Use the new CIS helpers in net pcmcia drivers, which allows for
a few code cleanups.
This revision does not remove the phys_addr assignment in
3c589_cs.c -- a bug noted by Komuro <komurojun-mbn@nifty.com>
CC: David S. Miller <davem@davemloft.net>
CC: netdev@vger.kernel.org
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/pcmcia/3c574_cs.c | 18 | ||||
-rw-r--r-- | drivers/net/pcmcia/3c589_cs.c | 21 | ||||
-rw-r--r-- | drivers/net/pcmcia/fmvj18x_cs.c | 50 | ||||
-rw-r--r-- | drivers/net/pcmcia/nmclan_cs.c | 19 | ||||
-rw-r--r-- | drivers/net/pcmcia/smc91c92_cs.c | 238 | ||||
-rw-r--r-- | drivers/net/pcmcia/xirc2ps_cs.c | 147 |
6 files changed, 171 insertions, 322 deletions
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index b58965a2b3ae..6449290c62ff 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c | |||
@@ -344,13 +344,13 @@ static int tc574_config(struct pcmcia_device *link) | |||
344 | { | 344 | { |
345 | struct net_device *dev = link->priv; | 345 | struct net_device *dev = link->priv; |
346 | struct el3_private *lp = netdev_priv(dev); | 346 | struct el3_private *lp = netdev_priv(dev); |
347 | tuple_t tuple; | ||
348 | __le16 buf[32]; | ||
349 | int last_fn, last_ret, i, j; | 347 | int last_fn, last_ret, i, j; |
350 | unsigned int ioaddr; | 348 | unsigned int ioaddr; |
351 | __be16 *phys_addr; | 349 | __be16 *phys_addr; |
352 | char *cardname; | 350 | char *cardname; |
353 | __u32 config; | 351 | __u32 config; |
352 | u8 *buf; | ||
353 | size_t len; | ||
354 | 354 | ||
355 | phys_addr = (__be16 *)dev->dev_addr; | 355 | phys_addr = (__be16 *)dev->dev_addr; |
356 | 356 | ||
@@ -378,16 +378,14 @@ static int tc574_config(struct pcmcia_device *link) | |||
378 | /* The 3c574 normally uses an EEPROM for configuration info, including | 378 | /* The 3c574 normally uses an EEPROM for configuration info, including |
379 | the hardware address. The future products may include a modem chip | 379 | the hardware address. The future products may include a modem chip |
380 | and put the address in the CIS. */ | 380 | and put the address in the CIS. */ |
381 | tuple.Attributes = 0; | 381 | |
382 | tuple.TupleData = (cisdata_t *)buf; | 382 | len = pcmcia_get_tuple(link, 0x88, &buf); |
383 | tuple.TupleDataMax = 64; | 383 | if (buf && len >= 6) { |
384 | tuple.TupleOffset = 0; | ||
385 | tuple.DesiredTuple = 0x88; | ||
386 | if (pcmcia_get_first_tuple(link, &tuple) == 0) { | ||
387 | pcmcia_get_tuple_data(link, &tuple); | ||
388 | for (i = 0; i < 3; i++) | 384 | for (i = 0; i < 3; i++) |
389 | phys_addr[i] = htons(le16_to_cpu(buf[i])); | 385 | phys_addr[i] = htons(le16_to_cpu(buf[i * 2])); |
386 | kfree(buf); | ||
390 | } else { | 387 | } else { |
388 | kfree(buf); /* 0 < len < 6 */ | ||
391 | EL3WINDOW(0); | 389 | EL3WINDOW(0); |
392 | for (i = 0; i < 3; i++) | 390 | for (i = 0; i < 3; i++) |
393 | phys_addr[i] = htons(read_eeprom(ioaddr, i + 10)); | 391 | phys_addr[i] = htons(read_eeprom(ioaddr, i + 10)); |
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 569fb06793cf..fc6123ea6fa7 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c | |||
@@ -256,22 +256,16 @@ static int tc589_config(struct pcmcia_device *link) | |||
256 | { | 256 | { |
257 | struct net_device *dev = link->priv; | 257 | struct net_device *dev = link->priv; |
258 | struct el3_private *lp = netdev_priv(dev); | 258 | struct el3_private *lp = netdev_priv(dev); |
259 | tuple_t tuple; | ||
260 | __le16 buf[32]; | ||
261 | __be16 *phys_addr; | 259 | __be16 *phys_addr; |
262 | int last_fn, last_ret, i, j, multi = 0, fifo; | 260 | int last_fn, last_ret, i, j, multi = 0, fifo; |
263 | unsigned int ioaddr; | 261 | unsigned int ioaddr; |
264 | char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; | 262 | char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; |
263 | u8 *buf; | ||
264 | size_t len; | ||
265 | 265 | ||
266 | DEBUG(0, "3c589_config(0x%p)\n", link); | 266 | DEBUG(0, "3c589_config(0x%p)\n", link); |
267 | 267 | ||
268 | phys_addr = (__be16 *)dev->dev_addr; | 268 | phys_addr = (__be16 *)dev->dev_addr; |
269 | tuple.Attributes = 0; | ||
270 | tuple.TupleData = (cisdata_t *)buf; | ||
271 | tuple.TupleDataMax = sizeof(buf); | ||
272 | tuple.TupleOffset = 0; | ||
273 | tuple.Attributes = TUPLE_RETURN_COMMON; | ||
274 | |||
275 | /* Is this a 3c562? */ | 269 | /* Is this a 3c562? */ |
276 | if (link->manf_id != MANFID_3COM) | 270 | if (link->manf_id != MANFID_3COM) |
277 | printk(KERN_INFO "3c589_cs: hmmm, is this really a " | 271 | printk(KERN_INFO "3c589_cs: hmmm, is this really a " |
@@ -301,12 +295,13 @@ static int tc589_config(struct pcmcia_device *link) | |||
301 | 295 | ||
302 | /* The 3c589 has an extra EEPROM for configuration info, including | 296 | /* The 3c589 has an extra EEPROM for configuration info, including |
303 | the hardware address. The 3c562 puts the address in the CIS. */ | 297 | the hardware address. The 3c562 puts the address in the CIS. */ |
304 | tuple.DesiredTuple = 0x88; | 298 | len = pcmcia_get_tuple(link, 0x88, &buf); |
305 | if (pcmcia_get_first_tuple(link, &tuple) == 0) { | 299 | if (buf && len >= 6) { |
306 | pcmcia_get_tuple_data(link, &tuple); | 300 | for (i = 0; i < 3; i++) |
307 | for (i = 0; i < 3; i++) | 301 | phys_addr[i] = htons(le16_to_cpu(buf[i*2])); |
308 | phys_addr[i] = htons(le16_to_cpu(buf[i])); | 302 | kfree(buf); |
309 | } else { | 303 | } else { |
304 | kfree(buf); /* 0 < len < 6 */ | ||
310 | for (i = 0; i < 3; i++) | 305 | for (i = 0; i < 3; i++) |
311 | phys_addr[i] = htons(read_eeprom(ioaddr, i)); | 306 | phys_addr[i] = htons(read_eeprom(ioaddr, i)); |
312 | if (phys_addr[0] == htons(0x6060)) { | 307 | if (phys_addr[0] == htons(0x6060)) { |
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index c7a2bbfaf821..5b73b11411c8 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c | |||
@@ -350,32 +350,29 @@ static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, | |||
350 | return 0; /* strange, but that's what the code did already before... */ | 350 | return 0; /* strange, but that's what the code did already before... */ |
351 | } | 351 | } |
352 | 352 | ||
353 | |||
354 | static int fmvj18x_config(struct pcmcia_device *link) | 353 | static int fmvj18x_config(struct pcmcia_device *link) |
355 | { | 354 | { |
356 | struct net_device *dev = link->priv; | 355 | struct net_device *dev = link->priv; |
357 | local_info_t *lp = netdev_priv(dev); | 356 | local_info_t *lp = netdev_priv(dev); |
358 | tuple_t tuple; | ||
359 | u_short buf[32]; | ||
360 | int i, last_fn = RequestIO, last_ret = 0, ret; | 357 | int i, last_fn = RequestIO, last_ret = 0, ret; |
361 | unsigned int ioaddr; | 358 | unsigned int ioaddr; |
362 | cardtype_t cardtype; | 359 | cardtype_t cardtype; |
363 | char *card_name = "unknown"; | 360 | char *card_name = "unknown"; |
364 | u_char *node_id; | 361 | u8 *buf; |
362 | size_t len; | ||
363 | u_char buggybuf[32]; | ||
365 | 364 | ||
366 | DEBUG(0, "fmvj18x_config(0x%p)\n", link); | 365 | DEBUG(0, "fmvj18x_config(0x%p)\n", link); |
367 | 366 | ||
368 | tuple.TupleData = (u_char *)buf; | 367 | len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf); |
369 | tuple.TupleDataMax = 64; | 368 | kfree(buf); |
370 | tuple.TupleOffset = 0; | 369 | |
371 | tuple.DesiredTuple = CISTPL_FUNCE; | 370 | if (len) { |
372 | tuple.TupleOffset = 0; | 371 | /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ |
373 | if (pcmcia_get_first_tuple(link, &tuple) == 0) { | ||
374 | last_ret = pcmcia_loop_config(link, fmvj18x_ioprobe, NULL); | 372 | last_ret = pcmcia_loop_config(link, fmvj18x_ioprobe, NULL); |
375 | if (last_ret != 0) | 373 | if (last_ret != 0) |
376 | goto cs_failed; | 374 | goto cs_failed; |
377 | 375 | ||
378 | /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ | ||
379 | switch (link->manf_id) { | 376 | switch (link->manf_id) { |
380 | case MANFID_TDK: | 377 | case MANFID_TDK: |
381 | cardtype = TDK; | 378 | cardtype = TDK; |
@@ -482,21 +479,21 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
482 | case CONTEC: | 479 | case CONTEC: |
483 | case NEC: | 480 | case NEC: |
484 | case KME: | 481 | case KME: |
485 | tuple.DesiredTuple = CISTPL_FUNCE; | ||
486 | tuple.TupleOffset = 0; | ||
487 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
488 | tuple.TupleOffset = 0; | ||
489 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
490 | if (cardtype == MBH10304) { | 482 | if (cardtype == MBH10304) { |
491 | /* MBH10304's CIS_FUNCE is corrupted */ | ||
492 | node_id = &(tuple.TupleData[5]); | ||
493 | card_name = "FMV-J182"; | 483 | card_name = "FMV-J182"; |
494 | } else { | 484 | |
495 | while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) { | 485 | len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf); |
496 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); | 486 | if (len < 11) { |
497 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | 487 | kfree(buf); |
488 | goto failed; | ||
498 | } | 489 | } |
499 | node_id = &(tuple.TupleData[2]); | 490 | /* Read MACID from CIS */ |
491 | for (i = 5; i < 11; i++) | ||
492 | dev->dev_addr[i] = buf[i]; | ||
493 | kfree(buf); | ||
494 | } else { | ||
495 | if (pcmcia_get_mac_from_cis(link, dev)) | ||
496 | goto failed; | ||
500 | if( cardtype == TDK ) { | 497 | if( cardtype == TDK ) { |
501 | card_name = "TDK LAK-CD021"; | 498 | card_name = "TDK LAK-CD021"; |
502 | } else if( cardtype == LA501 ) { | 499 | } else if( cardtype == LA501 ) { |
@@ -509,9 +506,6 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
509 | card_name = "C-NET(PC)C"; | 506 | card_name = "C-NET(PC)C"; |
510 | } | 507 | } |
511 | } | 508 | } |
512 | /* Read MACID from CIS */ | ||
513 | for (i = 0; i < 6; i++) | ||
514 | dev->dev_addr[i] = node_id[i]; | ||
515 | break; | 509 | break; |
516 | case UNGERMANN: | 510 | case UNGERMANN: |
517 | /* Read MACID from register */ | 511 | /* Read MACID from register */ |
@@ -521,12 +515,12 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
521 | break; | 515 | break; |
522 | case XXX10304: | 516 | case XXX10304: |
523 | /* Read MACID from Buggy CIS */ | 517 | /* Read MACID from Buggy CIS */ |
524 | if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) { | 518 | if (fmvj18x_get_hwinfo(link, buggybuf) == -1) { |
525 | printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n"); | 519 | printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n"); |
526 | goto failed; | 520 | goto failed; |
527 | } | 521 | } |
528 | for (i = 0 ; i < 6; i++) { | 522 | for (i = 0 ; i < 6; i++) { |
529 | dev->dev_addr[i] = tuple.TupleData[i]; | 523 | dev->dev_addr[i] = buggybuf[i]; |
530 | } | 524 | } |
531 | card_name = "FMV-J182"; | 525 | card_name = "FMV-J182"; |
532 | break; | 526 | break; |
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 5ed6339c52bc..4b96b356d979 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c | |||
@@ -661,8 +661,8 @@ static int nmclan_config(struct pcmcia_device *link) | |||
661 | { | 661 | { |
662 | struct net_device *dev = link->priv; | 662 | struct net_device *dev = link->priv; |
663 | mace_private *lp = netdev_priv(dev); | 663 | mace_private *lp = netdev_priv(dev); |
664 | tuple_t tuple; | 664 | u8 *buf; |
665 | u_char buf[64]; | 665 | size_t len; |
666 | int i, last_ret, last_fn; | 666 | int i, last_ret, last_fn; |
667 | unsigned int ioaddr; | 667 | unsigned int ioaddr; |
668 | 668 | ||
@@ -677,14 +677,13 @@ static int nmclan_config(struct pcmcia_device *link) | |||
677 | ioaddr = dev->base_addr; | 677 | ioaddr = dev->base_addr; |
678 | 678 | ||
679 | /* Read the ethernet address from the CIS. */ | 679 | /* Read the ethernet address from the CIS. */ |
680 | tuple.DesiredTuple = 0x80 /* CISTPL_CFTABLE_ENTRY_MISC */; | 680 | len = pcmcia_get_tuple(link, 0x80, &buf); |
681 | tuple.TupleData = buf; | 681 | if (!buf || len < ETHER_ADDR_LEN) { |
682 | tuple.TupleDataMax = 64; | 682 | kfree(buf); |
683 | tuple.TupleOffset = 0; | 683 | goto failed; |
684 | tuple.Attributes = 0; | 684 | } |
685 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 685 | memcpy(dev->dev_addr, buf, ETHER_ADDR_LEN); |
686 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | 686 | kfree(buf); |
687 | memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN); | ||
688 | 687 | ||
689 | /* Verify configuration by reading the MACE ID. */ | 688 | /* Verify configuration by reading the MACE ID. */ |
690 | { | 689 | { |
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index af03759d186d..df92bcde9bcf 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
@@ -126,12 +126,6 @@ struct smc_private { | |||
126 | int rx_ovrn; | 126 | int rx_ovrn; |
127 | }; | 127 | }; |
128 | 128 | ||
129 | struct smc_cfg_mem { | ||
130 | tuple_t tuple; | ||
131 | cisparse_t parse; | ||
132 | u_char buf[255]; | ||
133 | }; | ||
134 | |||
135 | /* Special definitions for Megahertz multifunction cards */ | 129 | /* Special definitions for Megahertz multifunction cards */ |
136 | #define MEGAHERTZ_ISR 0x0380 | 130 | #define MEGAHERTZ_ISR 0x0380 |
137 | 131 | ||
@@ -408,34 +402,7 @@ static int cvt_ascii_address(struct net_device *dev, char *s) | |||
408 | return 0; | 402 | return 0; |
409 | } | 403 | } |
410 | 404 | ||
411 | /*====================================================================*/ | 405 | /*==================================================================== |
412 | |||
413 | static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, | ||
414 | cisparse_t *parse) | ||
415 | { | ||
416 | int i; | ||
417 | |||
418 | i = pcmcia_get_first_tuple(handle, tuple); | ||
419 | if (i != 0) | ||
420 | return i; | ||
421 | i = pcmcia_get_tuple_data(handle, tuple); | ||
422 | if (i != 0) | ||
423 | return i; | ||
424 | return pcmcia_parse_tuple(tuple, parse); | ||
425 | } | ||
426 | |||
427 | static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, | ||
428 | cisparse_t *parse) | ||
429 | { | ||
430 | int i; | ||
431 | |||
432 | if ((i = pcmcia_get_next_tuple(handle, tuple)) != 0 || | ||
433 | (i = pcmcia_get_tuple_data(handle, tuple)) != 0) | ||
434 | return i; | ||
435 | return pcmcia_parse_tuple(tuple, parse); | ||
436 | } | ||
437 | |||
438 | /*====================================================================== | ||
439 | 406 | ||
440 | Configuration stuff for Megahertz cards | 407 | Configuration stuff for Megahertz cards |
441 | 408 | ||
@@ -490,15 +457,10 @@ static int mhz_mfc_config(struct pcmcia_device *link) | |||
490 | { | 457 | { |
491 | struct net_device *dev = link->priv; | 458 | struct net_device *dev = link->priv; |
492 | struct smc_private *smc = netdev_priv(dev); | 459 | struct smc_private *smc = netdev_priv(dev); |
493 | struct smc_cfg_mem *cfg_mem; | ||
494 | win_req_t req; | 460 | win_req_t req; |
495 | memreq_t mem; | 461 | memreq_t mem; |
496 | int i; | 462 | int i; |
497 | 463 | ||
498 | cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); | ||
499 | if (!cfg_mem) | ||
500 | return -ENOMEM; | ||
501 | |||
502 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 464 | link->conf.Attributes |= CONF_ENABLE_SPKR; |
503 | link->conf.Status = CCSR_AUDIO_ENA; | 465 | link->conf.Status = CCSR_AUDIO_ENA; |
504 | link->irq.Attributes = | 466 | link->irq.Attributes = |
@@ -510,7 +472,8 @@ static int mhz_mfc_config(struct pcmcia_device *link) | |||
510 | /* The Megahertz combo cards have modem-like CIS entries, so | 472 | /* The Megahertz combo cards have modem-like CIS entries, so |
511 | we have to explicitly try a bunch of port combinations. */ | 473 | we have to explicitly try a bunch of port combinations. */ |
512 | if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL)) | 474 | if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL)) |
513 | goto free_cfg_mem; | 475 | return -ENODEV; |
476 | |||
514 | dev->base_addr = link->io.BasePort1; | 477 | dev->base_addr = link->io.BasePort1; |
515 | 478 | ||
516 | /* Allocate a memory window, for accessing the ISR */ | 479 | /* Allocate a memory window, for accessing the ISR */ |
@@ -519,7 +482,8 @@ static int mhz_mfc_config(struct pcmcia_device *link) | |||
519 | req.AccessSpeed = 0; | 482 | req.AccessSpeed = 0; |
520 | i = pcmcia_request_window(&link, &req, &link->win); | 483 | i = pcmcia_request_window(&link, &req, &link->win); |
521 | if (i != 0) | 484 | if (i != 0) |
522 | goto free_cfg_mem; | 485 | return -ENODEV; |
486 | |||
523 | smc->base = ioremap(req.Base, req.Size); | 487 | smc->base = ioremap(req.Base, req.Size); |
524 | mem.CardOffset = mem.Page = 0; | 488 | mem.CardOffset = mem.Page = 0; |
525 | if (smc->manfid == MANFID_MOTOROLA) | 489 | if (smc->manfid == MANFID_MOTOROLA) |
@@ -531,18 +495,32 @@ static int mhz_mfc_config(struct pcmcia_device *link) | |||
531 | && (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | 495 | && (smc->cardid == PRODID_MEGAHERTZ_EM3288)) |
532 | mhz_3288_power(link); | 496 | mhz_3288_power(link); |
533 | 497 | ||
534 | free_cfg_mem: | 498 | return 0; |
535 | kfree(cfg_mem); | ||
536 | return -ENODEV; | ||
537 | } | 499 | } |
538 | 500 | ||
501 | static int pcmcia_get_versmac(struct pcmcia_device *p_dev, | ||
502 | tuple_t *tuple, | ||
503 | void *priv) | ||
504 | { | ||
505 | struct net_device *dev = priv; | ||
506 | cisparse_t parse; | ||
507 | |||
508 | if (pcmcia_parse_tuple(tuple, &parse)) | ||
509 | return -EINVAL; | ||
510 | |||
511 | if ((parse.version_1.ns > 3) && | ||
512 | (cvt_ascii_address(dev, | ||
513 | (parse.version_1.str + parse.version_1.ofs[3])))) | ||
514 | return 0; | ||
515 | |||
516 | return -EINVAL; | ||
517 | }; | ||
518 | |||
539 | static int mhz_setup(struct pcmcia_device *link) | 519 | static int mhz_setup(struct pcmcia_device *link) |
540 | { | 520 | { |
541 | struct net_device *dev = link->priv; | 521 | struct net_device *dev = link->priv; |
542 | struct smc_cfg_mem *cfg_mem; | 522 | size_t len; |
543 | tuple_t *tuple; | 523 | u8 *buf; |
544 | cisparse_t *parse; | ||
545 | u_char *buf, *station_addr; | ||
546 | int rc; | 524 | int rc; |
547 | 525 | ||
548 | /* Read the station address from the CIS. It is stored as the last | 526 | /* Read the station address from the CIS. It is stored as the last |
@@ -552,56 +530,22 @@ static int mhz_setup(struct pcmcia_device *link) | |||
552 | return 0; | 530 | return 0; |
553 | 531 | ||
554 | /* Workarounds for broken cards start here. */ | 532 | /* Workarounds for broken cards start here. */ |
555 | |||
556 | cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); | ||
557 | if (!cfg_mem) | ||
558 | return -1; | ||
559 | |||
560 | tuple = &cfg_mem->tuple; | ||
561 | parse = &cfg_mem->parse; | ||
562 | buf = cfg_mem->buf; | ||
563 | |||
564 | tuple->Attributes = tuple->TupleOffset = 0; | ||
565 | tuple->TupleData = (cisdata_t *)buf; | ||
566 | tuple->TupleDataMax = 255; | ||
567 | |||
568 | /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ | 533 | /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ |
569 | tuple->DesiredTuple = CISTPL_VERS_1; | 534 | if (!pcmcia_loop_tuple(link, CISTPL_VERS_1, pcmcia_get_versmac, dev)) |
570 | if (first_tuple(link, tuple, parse) != 0) { | 535 | return 0; |
571 | rc = -1; | ||
572 | goto free_cfg_mem; | ||
573 | } | ||
574 | /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ | ||
575 | if (next_tuple(link, tuple, parse) != 0) | ||
576 | first_tuple(link, tuple, parse); | ||
577 | if (parse->version_1.ns > 3) { | ||
578 | station_addr = parse->version_1.str + parse->version_1.ofs[3]; | ||
579 | if (cvt_ascii_address(dev, station_addr) == 0) { | ||
580 | rc = 0; | ||
581 | goto free_cfg_mem; | ||
582 | } | ||
583 | } | ||
584 | 536 | ||
585 | /* Another possibility: for the EM3288, in a special tuple */ | 537 | /* Another possibility: for the EM3288, in a special tuple */ |
586 | tuple->DesiredTuple = 0x81; | ||
587 | if (pcmcia_get_first_tuple(link, tuple) != 0) { | ||
588 | rc = -1; | ||
589 | goto free_cfg_mem; | ||
590 | } | ||
591 | if (pcmcia_get_tuple_data(link, tuple) != 0) { | ||
592 | rc = -1; | ||
593 | goto free_cfg_mem; | ||
594 | } | ||
595 | buf[12] = '\0'; | ||
596 | if (cvt_ascii_address(dev, buf) == 0) { | ||
597 | rc = 0; | ||
598 | goto free_cfg_mem; | ||
599 | } | ||
600 | rc = -1; | 538 | rc = -1; |
601 | free_cfg_mem: | 539 | len = pcmcia_get_tuple(link, 0x81, &buf); |
602 | kfree(cfg_mem); | 540 | if (buf && len >= 13) { |
603 | return rc; | 541 | buf[12] = '\0'; |
604 | } | 542 | if (cvt_ascii_address(dev, buf)) |
543 | rc = 0; | ||
544 | } | ||
545 | kfree(buf); | ||
546 | |||
547 | return rc; | ||
548 | }; | ||
605 | 549 | ||
606 | /*====================================================================== | 550 | /*====================================================================== |
607 | 551 | ||
@@ -691,58 +635,21 @@ static int smc_config(struct pcmcia_device *link) | |||
691 | return i; | 635 | return i; |
692 | } | 636 | } |
693 | 637 | ||
638 | |||
694 | static int smc_setup(struct pcmcia_device *link) | 639 | static int smc_setup(struct pcmcia_device *link) |
695 | { | 640 | { |
696 | struct net_device *dev = link->priv; | 641 | struct net_device *dev = link->priv; |
697 | struct smc_cfg_mem *cfg_mem; | ||
698 | tuple_t *tuple; | ||
699 | cisparse_t *parse; | ||
700 | cistpl_lan_node_id_t *node_id; | ||
701 | u_char *buf, *station_addr; | ||
702 | int i, rc; | ||
703 | |||
704 | cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); | ||
705 | if (!cfg_mem) | ||
706 | return -ENOMEM; | ||
707 | |||
708 | tuple = &cfg_mem->tuple; | ||
709 | parse = &cfg_mem->parse; | ||
710 | buf = cfg_mem->buf; | ||
711 | |||
712 | tuple->Attributes = tuple->TupleOffset = 0; | ||
713 | tuple->TupleData = (cisdata_t *)buf; | ||
714 | tuple->TupleDataMax = 255; | ||
715 | 642 | ||
716 | /* Check for a LAN function extension tuple */ | 643 | /* Check for a LAN function extension tuple */ |
717 | tuple->DesiredTuple = CISTPL_FUNCE; | 644 | if (!pcmcia_get_mac_from_cis(link, dev)) |
718 | i = first_tuple(link, tuple, parse); | 645 | return 0; |
719 | while (i == 0) { | 646 | |
720 | if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID) | ||
721 | break; | ||
722 | i = next_tuple(link, tuple, parse); | ||
723 | } | ||
724 | if (i == 0) { | ||
725 | node_id = (cistpl_lan_node_id_t *)parse->funce.data; | ||
726 | if (node_id->nb == 6) { | ||
727 | for (i = 0; i < 6; i++) | ||
728 | dev->dev_addr[i] = node_id->id[i]; | ||
729 | rc = 0; | ||
730 | goto free_cfg_mem; | ||
731 | } | ||
732 | } | ||
733 | /* Try the third string in the Version 1 Version/ID tuple. */ | 647 | /* Try the third string in the Version 1 Version/ID tuple. */ |
734 | if (link->prod_id[2]) { | 648 | if (link->prod_id[2]) { |
735 | station_addr = link->prod_id[2]; | 649 | if (cvt_ascii_address(dev, link->prod_id[2]) == 0) |
736 | if (cvt_ascii_address(dev, station_addr) == 0) { | 650 | return 0; |
737 | rc = 0; | ||
738 | goto free_cfg_mem; | ||
739 | } | ||
740 | } | 651 | } |
741 | 652 | return -1; | |
742 | rc = -1; | ||
743 | free_cfg_mem: | ||
744 | kfree(cfg_mem); | ||
745 | return rc; | ||
746 | } | 653 | } |
747 | 654 | ||
748 | /*====================================================================*/ | 655 | /*====================================================================*/ |
@@ -801,41 +708,31 @@ static int osi_load_firmware(struct pcmcia_device *link) | |||
801 | return err; | 708 | return err; |
802 | } | 709 | } |
803 | 710 | ||
804 | static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid) | 711 | static int pcmcia_osi_mac(struct pcmcia_device *p_dev, |
712 | tuple_t *tuple, | ||
713 | void *priv) | ||
805 | { | 714 | { |
806 | struct net_device *dev = link->priv; | 715 | struct net_device *dev = priv; |
807 | struct smc_cfg_mem *cfg_mem; | 716 | int i; |
808 | tuple_t *tuple; | ||
809 | u_char *buf; | ||
810 | int i, rc; | ||
811 | 717 | ||
812 | cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); | 718 | if (tuple->TupleDataLen < 8) |
813 | if (!cfg_mem) | 719 | return -EINVAL; |
814 | return -1; | 720 | if (tuple->TupleData[0] != 0x04) |
721 | return -EINVAL; | ||
722 | for (i = 0; i < 6; i++) | ||
723 | dev->dev_addr[i] = tuple->TupleData[i+2]; | ||
724 | return 0; | ||
725 | }; | ||
815 | 726 | ||
816 | tuple = &cfg_mem->tuple; | ||
817 | buf = cfg_mem->buf; | ||
818 | 727 | ||
819 | tuple->Attributes = TUPLE_RETURN_COMMON; | 728 | static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid) |
820 | tuple->TupleData = (cisdata_t *)buf; | 729 | { |
821 | tuple->TupleDataMax = 255; | 730 | struct net_device *dev = link->priv; |
822 | tuple->TupleOffset = 0; | 731 | int rc; |
823 | 732 | ||
824 | /* Read the station address from tuple 0x90, subtuple 0x04 */ | 733 | /* Read the station address from tuple 0x90, subtuple 0x04 */ |
825 | tuple->DesiredTuple = 0x90; | 734 | if (pcmcia_loop_tuple(link, 0x90, pcmcia_osi_mac, dev)) |
826 | i = pcmcia_get_first_tuple(link, tuple); | 735 | return -1; |
827 | while (i == 0) { | ||
828 | i = pcmcia_get_tuple_data(link, tuple); | ||
829 | if ((i != 0) || (buf[0] == 0x04)) | ||
830 | break; | ||
831 | i = pcmcia_get_next_tuple(link, tuple); | ||
832 | } | ||
833 | if (i != 0) { | ||
834 | rc = -1; | ||
835 | goto free_cfg_mem; | ||
836 | } | ||
837 | for (i = 0; i < 6; i++) | ||
838 | dev->dev_addr[i] = buf[i+2]; | ||
839 | 736 | ||
840 | if (((manfid == MANFID_OSITECH) && | 737 | if (((manfid == MANFID_OSITECH) && |
841 | (cardid == PRODID_OSITECH_SEVEN)) || | 738 | (cardid == PRODID_OSITECH_SEVEN)) || |
@@ -843,7 +740,7 @@ static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid) | |||
843 | (cardid == PRODID_PSION_NET100))) { | 740 | (cardid == PRODID_PSION_NET100))) { |
844 | rc = osi_load_firmware(link); | 741 | rc = osi_load_firmware(link); |
845 | if (rc) | 742 | if (rc) |
846 | goto free_cfg_mem; | 743 | return rc; |
847 | } else if (manfid == MANFID_OSITECH) { | 744 | } else if (manfid == MANFID_OSITECH) { |
848 | /* Make sure both functions are powered up */ | 745 | /* Make sure both functions are powered up */ |
849 | set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR); | 746 | set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR); |
@@ -853,10 +750,7 @@ static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid) | |||
853 | inw(link->io.BasePort1 + OSITECH_AUI_PWR), | 750 | inw(link->io.BasePort1 + OSITECH_AUI_PWR), |
854 | inw(link->io.BasePort1 + OSITECH_RESET_ISR)); | 751 | inw(link->io.BasePort1 + OSITECH_RESET_ISR)); |
855 | } | 752 | } |
856 | rc = 0; | 753 | return 0; |
857 | free_cfg_mem: | ||
858 | kfree(cfg_mem); | ||
859 | return rc; | ||
860 | } | 754 | } |
861 | 755 | ||
862 | static int smc91c92_suspend(struct pcmcia_device *link) | 756 | static int smc91c92_suspend(struct pcmcia_device *link) |
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 5e203230144f..925e85096629 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c | |||
@@ -359,7 +359,7 @@ static void xirc_tx_timeout(struct net_device *dev); | |||
359 | static void xirc2ps_tx_timeout_task(struct work_struct *work); | 359 | static void xirc2ps_tx_timeout_task(struct work_struct *work); |
360 | static void set_addresses(struct net_device *dev); | 360 | static void set_addresses(struct net_device *dev); |
361 | static void set_multicast_list(struct net_device *dev); | 361 | static void set_multicast_list(struct net_device *dev); |
362 | static int set_card_type(struct pcmcia_device *link, const void *s); | 362 | static int set_card_type(struct pcmcia_device *link); |
363 | static int do_config(struct net_device *dev, struct ifmap *map); | 363 | static int do_config(struct net_device *dev, struct ifmap *map); |
364 | static int do_open(struct net_device *dev); | 364 | static int do_open(struct net_device *dev); |
365 | static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 365 | static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
@@ -371,28 +371,6 @@ static void do_powerdown(struct net_device *dev); | |||
371 | static int do_stop(struct net_device *dev); | 371 | static int do_stop(struct net_device *dev); |
372 | 372 | ||
373 | /*=============== Helper functions =========================*/ | 373 | /*=============== Helper functions =========================*/ |
374 | static int | ||
375 | first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) | ||
376 | { | ||
377 | int err; | ||
378 | |||
379 | if ((err = pcmcia_get_first_tuple(handle, tuple)) == 0 && | ||
380 | (err = pcmcia_get_tuple_data(handle, tuple)) == 0) | ||
381 | err = pcmcia_parse_tuple(tuple, parse); | ||
382 | return err; | ||
383 | } | ||
384 | |||
385 | static int | ||
386 | next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) | ||
387 | { | ||
388 | int err; | ||
389 | |||
390 | if ((err = pcmcia_get_next_tuple(handle, tuple)) == 0 && | ||
391 | (err = pcmcia_get_tuple_data(handle, tuple)) == 0) | ||
392 | err = pcmcia_parse_tuple(tuple, parse); | ||
393 | return err; | ||
394 | } | ||
395 | |||
396 | #define SelectPage(pgnr) outb((pgnr), ioaddr + XIRCREG_PR) | 374 | #define SelectPage(pgnr) outb((pgnr), ioaddr + XIRCREG_PR) |
397 | #define GetByte(reg) ((unsigned)inb(ioaddr + (reg))) | 375 | #define GetByte(reg) ((unsigned)inb(ioaddr + (reg))) |
398 | #define GetWord(reg) ((unsigned)inw(ioaddr + (reg))) | 376 | #define GetWord(reg) ((unsigned)inw(ioaddr + (reg))) |
@@ -644,15 +622,23 @@ xirc2ps_detach(struct pcmcia_device *link) | |||
644 | * | 622 | * |
645 | */ | 623 | */ |
646 | static int | 624 | static int |
647 | set_card_type(struct pcmcia_device *link, const void *s) | 625 | set_card_type(struct pcmcia_device *link) |
648 | { | 626 | { |
649 | struct net_device *dev = link->priv; | 627 | struct net_device *dev = link->priv; |
650 | local_info_t *local = netdev_priv(dev); | 628 | local_info_t *local = netdev_priv(dev); |
651 | #ifdef PCMCIA_DEBUG | 629 | u8 *buf; |
652 | unsigned cisrev = ((const unsigned char *)s)[2]; | 630 | unsigned int cisrev, mediaid, prodid; |
653 | #endif | 631 | size_t len; |
654 | unsigned mediaid= ((const unsigned char *)s)[3]; | 632 | |
655 | unsigned prodid = ((const unsigned char *)s)[4]; | 633 | len = pcmcia_get_tuple(link, CISTPL_MANFID, &buf); |
634 | if (len < 5) { | ||
635 | dev_err(&link->dev, "invalid CIS -- sorry\n"); | ||
636 | return 0; | ||
637 | } | ||
638 | |||
639 | cisrev = buf[2]; | ||
640 | mediaid = buf[3]; | ||
641 | prodid = buf[4]; | ||
656 | 642 | ||
657 | DEBUG(0, "cisrev=%02x mediaid=%02x prodid=%02x\n", | 643 | DEBUG(0, "cisrev=%02x mediaid=%02x prodid=%02x\n", |
658 | cisrev, mediaid, prodid); | 644 | cisrev, mediaid, prodid); |
@@ -761,6 +747,26 @@ xirc2ps_config_check(struct pcmcia_device *p_dev, | |||
761 | 747 | ||
762 | } | 748 | } |
763 | 749 | ||
750 | |||
751 | static int pcmcia_get_mac_ce(struct pcmcia_device *p_dev, | ||
752 | tuple_t *tuple, | ||
753 | void *priv) | ||
754 | { | ||
755 | struct net_device *dev = priv; | ||
756 | int i; | ||
757 | |||
758 | if (tuple->TupleDataLen != 13) | ||
759 | return -EINVAL; | ||
760 | if ((tuple->TupleData[0] != 2) || (tuple->TupleData[1] != 1) || | ||
761 | (tuple->TupleData[2] != 6)) | ||
762 | return -EINVAL; | ||
763 | /* another try (James Lehmer's CE2 version 4.1)*/ | ||
764 | for (i = 2; i < 6; i++) | ||
765 | dev->dev_addr[i] = tuple->TupleData[i+2]; | ||
766 | return 0; | ||
767 | }; | ||
768 | |||
769 | |||
764 | /**************** | 770 | /**************** |
765 | * xirc2ps_config() is scheduled to run after a CARD_INSERTION event | 771 | * xirc2ps_config() is scheduled to run after a CARD_INSERTION event |
766 | * is received, to configure the PCMCIA socket, and to make the | 772 | * is received, to configure the PCMCIA socket, and to make the |
@@ -772,25 +778,14 @@ xirc2ps_config(struct pcmcia_device * link) | |||
772 | struct net_device *dev = link->priv; | 778 | struct net_device *dev = link->priv; |
773 | local_info_t *local = netdev_priv(dev); | 779 | local_info_t *local = netdev_priv(dev); |
774 | unsigned int ioaddr; | 780 | unsigned int ioaddr; |
775 | tuple_t tuple; | 781 | int err; |
776 | cisparse_t parse; | 782 | u8 *buf; |
777 | int err, i; | 783 | size_t len; |
778 | u_char buf[64]; | ||
779 | cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data; | ||
780 | 784 | ||
781 | local->dingo_ccr = NULL; | 785 | local->dingo_ccr = NULL; |
782 | 786 | ||
783 | DEBUG(0, "config(0x%p)\n", link); | 787 | DEBUG(0, "config(0x%p)\n", link); |
784 | 788 | ||
785 | /* | ||
786 | * This reads the card's CONFIG tuple to find its configuration | ||
787 | * registers. | ||
788 | */ | ||
789 | tuple.Attributes = 0; | ||
790 | tuple.TupleData = buf; | ||
791 | tuple.TupleDataMax = 64; | ||
792 | tuple.TupleOffset = 0; | ||
793 | |||
794 | /* Is this a valid card */ | 789 | /* Is this a valid card */ |
795 | if (link->has_manf_id == 0) { | 790 | if (link->has_manf_id == 0) { |
796 | printk(KNOT_XIRC "manfid not found in CIS\n"); | 791 | printk(KNOT_XIRC "manfid not found in CIS\n"); |
@@ -816,67 +811,41 @@ xirc2ps_config(struct pcmcia_device * link) | |||
816 | break; | 811 | break; |
817 | default: | 812 | default: |
818 | printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n", | 813 | printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n", |
819 | (unsigned)parse.manfid.manf); | 814 | (unsigned)link->manf_id); |
820 | goto failure; | 815 | goto failure; |
821 | } | 816 | } |
822 | DEBUG(0, "found %s card\n", local->manf_str); | 817 | DEBUG(0, "found %s card\n", local->manf_str); |
823 | 818 | ||
824 | /* needed for the additional fields to be parsed by set_card_type() */ | 819 | if (!set_card_type(link)) { |
825 | tuple.DesiredTuple = CISTPL_MANFID; | ||
826 | err = first_tuple(link, &tuple, &parse) | ||
827 | if (err) { | ||
828 | printk(KNOT_XIRC "manfid not found in CIS\n"); | ||
829 | goto failure; | ||
830 | } | ||
831 | if (!set_card_type(link, buf)) { | ||
832 | printk(KNOT_XIRC "this card is not supported\n"); | 820 | printk(KNOT_XIRC "this card is not supported\n"); |
833 | goto failure; | 821 | goto failure; |
834 | } | 822 | } |
835 | 823 | ||
836 | /* get the ethernet address from the CIS */ | 824 | /* get the ethernet address from the CIS */ |
837 | tuple.DesiredTuple = CISTPL_FUNCE; | 825 | err = pcmcia_get_mac_from_cis(link, dev); |
838 | for (err = first_tuple(link, &tuple, &parse); !err; | 826 | |
839 | err = next_tuple(link, &tuple, &parse)) { | 827 | /* not found: try to get the node-id from tuple 0x89 */ |
840 | /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries: | 828 | if (err) { |
841 | * the first one with a length of zero the second correct - | 829 | len = pcmcia_get_tuple(link, 0x89, &buf); |
842 | * so I skip all entries with length 0 */ | 830 | /* data layout looks like tuple 0x22 */ |
843 | if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID | 831 | if (buf && len == 8) { |
844 | && ((cistpl_lan_node_id_t *)parse.funce.data)->nb) | 832 | if (*buf == CISTPL_FUNCE_LAN_NODE_ID) { |
845 | break; | 833 | int i; |
846 | } | 834 | for (i = 2; i < 6; i++) |
847 | if (err) { /* not found: try to get the node-id from tuple 0x89 */ | 835 | dev->dev_addr[i] = buf[i+2]; |
848 | tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */ | 836 | } else |
849 | if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 && | 837 | err = -1; |
850 | (err = pcmcia_get_tuple_data(link, &tuple)) == 0) { | ||
851 | if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID) | ||
852 | memcpy(&parse, buf, 8); | ||
853 | else | ||
854 | err = -1; | ||
855 | } | ||
856 | } | ||
857 | if (err) { /* another try (James Lehmer's CE2 version 4.1)*/ | ||
858 | tuple.DesiredTuple = CISTPL_FUNCE; | ||
859 | for (err = first_tuple(link, &tuple, &parse); !err; | ||
860 | err = next_tuple(link, &tuple, &parse)) { | ||
861 | if (parse.funce.type == 0x02 && parse.funce.data[0] == 1 | ||
862 | && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) { | ||
863 | buf[1] = 4; | ||
864 | memcpy(&parse, buf+1, 8); | ||
865 | break; | ||
866 | } | 838 | } |
867 | } | 839 | kfree(buf); |
868 | } | 840 | } |
841 | |||
842 | if (err) | ||
843 | err = pcmcia_loop_tuple(link, CISTPL_FUNCE, pcmcia_get_mac_ce, dev); | ||
844 | |||
869 | if (err) { | 845 | if (err) { |
870 | printk(KNOT_XIRC "node-id not found in CIS\n"); | 846 | printk(KNOT_XIRC "node-id not found in CIS\n"); |
871 | goto failure; | 847 | goto failure; |
872 | } | 848 | } |
873 | node_id = (cistpl_lan_node_id_t *)parse.funce.data; | ||
874 | if (node_id->nb != 6) { | ||
875 | printk(KNOT_XIRC "malformed node-id in CIS\n"); | ||
876 | goto failure; | ||
877 | } | ||
878 | for (i=0; i < 6; i++) | ||
879 | dev->dev_addr[i] = node_id->id[i]; | ||
880 | 849 | ||
881 | link->io.IOAddrLines =10; | 850 | link->io.IOAddrLines =10; |
882 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | 851 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; |