diff options
Diffstat (limited to 'drivers/mtd/maps')
-rw-r--r-- | drivers/mtd/maps/pcmciamtd.c | 115 |
1 files changed, 48 insertions, 67 deletions
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 8bbc751a6021..d27f4129afd3 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
@@ -54,7 +54,7 @@ static const int debug = 0; | |||
54 | #define MAX_PCMCIA_ADDR 0x4000000 | 54 | #define MAX_PCMCIA_ADDR 0x4000000 |
55 | 55 | ||
56 | struct pcmciamtd_dev { | 56 | struct pcmciamtd_dev { |
57 | dev_link_t link; /* PCMCIA link */ | 57 | struct pcmcia_device *p_dev; |
58 | dev_node_t node; /* device node */ | 58 | dev_node_t node; /* device node */ |
59 | caddr_t win_base; /* ioremapped address of PCMCIA window */ | 59 | caddr_t win_base; /* ioremapped address of PCMCIA window */ |
60 | unsigned int win_size; /* size of window */ | 60 | unsigned int win_size; /* size of window */ |
@@ -111,8 +111,8 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) | |||
111 | memreq_t mrq; | 111 | memreq_t mrq; |
112 | int ret; | 112 | int ret; |
113 | 113 | ||
114 | if(!(dev->link.state & DEV_PRESENT)) { | 114 | if (!pcmcia_dev_present(dev->p_dev)) { |
115 | DEBUG(1, "device removed state = 0x%4.4X", dev->link.state); | 115 | DEBUG(1, "device removed"); |
116 | return 0; | 116 | return 0; |
117 | } | 117 | } |
118 | 118 | ||
@@ -122,7 +122,7 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) | |||
122 | dev->offset, mrq.CardOffset); | 122 | dev->offset, mrq.CardOffset); |
123 | mrq.Page = 0; | 123 | mrq.Page = 0; |
124 | if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) { | 124 | if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) { |
125 | cs_error(dev->link.handle, MapMemPage, ret); | 125 | cs_error(dev->p_dev, MapMemPage, ret); |
126 | return NULL; | 126 | return NULL; |
127 | } | 127 | } |
128 | dev->offset = mrq.CardOffset; | 128 | dev->offset = mrq.CardOffset; |
@@ -238,7 +238,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v | |||
238 | 238 | ||
239 | /* read/write{8,16} copy_{from,to} routines with direct access */ | 239 | /* read/write{8,16} copy_{from,to} routines with direct access */ |
240 | 240 | ||
241 | #define DEV_REMOVED(x) (!(*(u_int *)x->map_priv_1 & DEV_PRESENT)) | 241 | #define DEV_REMOVED(x) (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev))) |
242 | 242 | ||
243 | static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) | 243 | static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) |
244 | { | 244 | { |
@@ -319,7 +319,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f | |||
319 | static void pcmciamtd_set_vpp(struct map_info *map, int on) | 319 | static void pcmciamtd_set_vpp(struct map_info *map, int on) |
320 | { | 320 | { |
321 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; | 321 | struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; |
322 | dev_link_t *link = &dev->link; | 322 | struct pcmcia_device *link = dev->p_dev; |
323 | modconf_t mod; | 323 | modconf_t mod; |
324 | int ret; | 324 | int ret; |
325 | 325 | ||
@@ -328,9 +328,9 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) | |||
328 | mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0; | 328 | mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0; |
329 | 329 | ||
330 | DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); | 330 | DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); |
331 | ret = pcmcia_modify_configuration(link->handle, &mod); | 331 | ret = pcmcia_modify_configuration(link, &mod); |
332 | if(ret != CS_SUCCESS) { | 332 | if(ret != CS_SUCCESS) { |
333 | cs_error(link->handle, ModifyConfiguration, ret); | 333 | cs_error(link, ModifyConfiguration, ret); |
334 | } | 334 | } |
335 | } | 335 | } |
336 | 336 | ||
@@ -340,7 +340,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) | |||
340 | * still open, this will be postponed until it is closed. | 340 | * still open, this will be postponed until it is closed. |
341 | */ | 341 | */ |
342 | 342 | ||
343 | static void pcmciamtd_release(dev_link_t *link) | 343 | static void pcmciamtd_release(struct pcmcia_device *link) |
344 | { | 344 | { |
345 | struct pcmciamtd_dev *dev = link->priv; | 345 | struct pcmciamtd_dev *dev = link->priv; |
346 | 346 | ||
@@ -353,12 +353,11 @@ static void pcmciamtd_release(dev_link_t *link) | |||
353 | } | 353 | } |
354 | pcmcia_release_window(link->win); | 354 | pcmcia_release_window(link->win); |
355 | } | 355 | } |
356 | pcmcia_release_configuration(link->handle); | 356 | pcmcia_disable_device(link); |
357 | link->state &= ~DEV_CONFIG; | ||
358 | } | 357 | } |
359 | 358 | ||
360 | 359 | ||
361 | static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name) | 360 | static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name) |
362 | { | 361 | { |
363 | int rc; | 362 | int rc; |
364 | tuple_t tuple; | 363 | tuple_t tuple; |
@@ -371,16 +370,16 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ | |||
371 | tuple.TupleOffset = 0; | 370 | tuple.TupleOffset = 0; |
372 | tuple.DesiredTuple = RETURN_FIRST_TUPLE; | 371 | tuple.DesiredTuple = RETURN_FIRST_TUPLE; |
373 | 372 | ||
374 | rc = pcmcia_get_first_tuple(link->handle, &tuple); | 373 | rc = pcmcia_get_first_tuple(link, &tuple); |
375 | while(rc == CS_SUCCESS) { | 374 | while(rc == CS_SUCCESS) { |
376 | rc = pcmcia_get_tuple_data(link->handle, &tuple); | 375 | rc = pcmcia_get_tuple_data(link, &tuple); |
377 | if(rc != CS_SUCCESS) { | 376 | if(rc != CS_SUCCESS) { |
378 | cs_error(link->handle, GetTupleData, rc); | 377 | cs_error(link, GetTupleData, rc); |
379 | break; | 378 | break; |
380 | } | 379 | } |
381 | rc = pcmcia_parse_tuple(link->handle, &tuple, &parse); | 380 | rc = pcmcia_parse_tuple(link, &tuple, &parse); |
382 | if(rc != CS_SUCCESS) { | 381 | if(rc != CS_SUCCESS) { |
383 | cs_error(link->handle, ParseTuple, rc); | 382 | cs_error(link, ParseTuple, rc); |
384 | break; | 383 | break; |
385 | } | 384 | } |
386 | 385 | ||
@@ -451,7 +450,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ | |||
451 | DEBUG(2, "Unknown tuple code %d", tuple.TupleCode); | 450 | DEBUG(2, "Unknown tuple code %d", tuple.TupleCode); |
452 | } | 451 | } |
453 | 452 | ||
454 | rc = pcmcia_get_next_tuple(link->handle, &tuple); | 453 | rc = pcmcia_get_next_tuple(link, &tuple); |
455 | } | 454 | } |
456 | if(!dev->pcmcia_map.size) | 455 | if(!dev->pcmcia_map.size) |
457 | dev->pcmcia_map.size = MAX_PCMCIA_ADDR; | 456 | dev->pcmcia_map.size = MAX_PCMCIA_ADDR; |
@@ -488,7 +487,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ | |||
488 | #define CS_CHECK(fn, ret) \ | 487 | #define CS_CHECK(fn, ret) \ |
489 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 488 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
490 | 489 | ||
491 | static void pcmciamtd_config(dev_link_t *link) | 490 | static int pcmciamtd_config(struct pcmcia_device *link) |
492 | { | 491 | { |
493 | struct pcmciamtd_dev *dev = link->priv; | 492 | struct pcmciamtd_dev *dev = link->priv; |
494 | struct mtd_info *mtd = NULL; | 493 | struct mtd_info *mtd = NULL; |
@@ -504,13 +503,10 @@ static void pcmciamtd_config(dev_link_t *link) | |||
504 | 503 | ||
505 | DEBUG(3, "link=0x%p", link); | 504 | DEBUG(3, "link=0x%p", link); |
506 | 505 | ||
507 | /* Configure card */ | ||
508 | link->state |= DEV_CONFIG; | ||
509 | |||
510 | DEBUG(2, "Validating CIS"); | 506 | DEBUG(2, "Validating CIS"); |
511 | ret = pcmcia_validate_cis(link->handle, &cisinfo); | 507 | ret = pcmcia_validate_cis(link, &cisinfo); |
512 | if(ret != CS_SUCCESS) { | 508 | if(ret != CS_SUCCESS) { |
513 | cs_error(link->handle, GetTupleData, ret); | 509 | cs_error(link, GetTupleData, ret); |
514 | } else { | 510 | } else { |
515 | DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains); | 511 | DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains); |
516 | } | 512 | } |
@@ -538,7 +534,7 @@ static void pcmciamtd_config(dev_link_t *link) | |||
538 | req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; | 534 | req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; |
539 | req.Base = 0; | 535 | req.Base = 0; |
540 | req.AccessSpeed = mem_speed; | 536 | req.AccessSpeed = mem_speed; |
541 | link->win = (window_handle_t)link->handle; | 537 | link->win = (window_handle_t)link; |
542 | req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR; | 538 | req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR; |
543 | dev->win_size = 0; | 539 | dev->win_size = 0; |
544 | 540 | ||
@@ -546,7 +542,7 @@ static void pcmciamtd_config(dev_link_t *link) | |||
546 | int ret; | 542 | int ret; |
547 | DEBUG(2, "requesting window with size = %dKiB memspeed = %d", | 543 | DEBUG(2, "requesting window with size = %dKiB memspeed = %d", |
548 | req.Size >> 10, req.AccessSpeed); | 544 | req.Size >> 10, req.AccessSpeed); |
549 | ret = pcmcia_request_window(&link->handle, &req, &link->win); | 545 | ret = pcmcia_request_window(&link, &req, &link->win); |
550 | DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); | 546 | DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); |
551 | if(ret) { | 547 | if(ret) { |
552 | req.Size >>= 1; | 548 | req.Size >>= 1; |
@@ -562,19 +558,19 @@ static void pcmciamtd_config(dev_link_t *link) | |||
562 | if(!dev->win_size) { | 558 | if(!dev->win_size) { |
563 | err("Cant allocate memory window"); | 559 | err("Cant allocate memory window"); |
564 | pcmciamtd_release(link); | 560 | pcmciamtd_release(link); |
565 | return; | 561 | return -ENODEV; |
566 | } | 562 | } |
567 | DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); | 563 | DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); |
568 | 564 | ||
569 | /* Get write protect status */ | 565 | /* Get write protect status */ |
570 | CS_CHECK(GetStatus, pcmcia_get_status(link->handle, &status)); | 566 | CS_CHECK(GetStatus, pcmcia_get_status(link, &status)); |
571 | DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx", | 567 | DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx", |
572 | status.CardState, (unsigned long)link->win); | 568 | status.CardState, (unsigned long)link->win); |
573 | dev->win_base = ioremap(req.Base, req.Size); | 569 | dev->win_base = ioremap(req.Base, req.Size); |
574 | if(!dev->win_base) { | 570 | if(!dev->win_base) { |
575 | err("ioremap(%lu, %u) failed", req.Base, req.Size); | 571 | err("ioremap(%lu, %u) failed", req.Base, req.Size); |
576 | pcmciamtd_release(link); | 572 | pcmciamtd_release(link); |
577 | return; | 573 | return -ENODEV; |
578 | } | 574 | } |
579 | DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x", | 575 | DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x", |
580 | dev, req.Base, dev->win_base, req.Size); | 576 | dev, req.Base, dev->win_base, req.Size); |
@@ -584,17 +580,14 @@ static void pcmciamtd_config(dev_link_t *link) | |||
584 | dev->pcmcia_map.map_priv_2 = (unsigned long)link->win; | 580 | dev->pcmcia_map.map_priv_2 = (unsigned long)link->win; |
585 | 581 | ||
586 | DEBUG(2, "Getting configuration"); | 582 | DEBUG(2, "Getting configuration"); |
587 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link->handle, &t)); | 583 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &t)); |
588 | DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2); | 584 | DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2); |
589 | dev->vpp = (vpp) ? vpp : t.Vpp1; | 585 | dev->vpp = (vpp) ? vpp : t.Vpp1; |
590 | link->conf.Attributes = 0; | 586 | link->conf.Attributes = 0; |
591 | link->conf.Vcc = t.Vcc; | ||
592 | if(setvpp == 2) { | 587 | if(setvpp == 2) { |
593 | link->conf.Vpp1 = dev->vpp; | 588 | link->conf.Vpp = dev->vpp; |
594 | link->conf.Vpp2 = dev->vpp; | ||
595 | } else { | 589 | } else { |
596 | link->conf.Vpp1 = 0; | 590 | link->conf.Vpp = 0; |
597 | link->conf.Vpp2 = 0; | ||
598 | } | 591 | } |
599 | 592 | ||
600 | link->conf.IntType = INT_MEMORY; | 593 | link->conf.IntType = INT_MEMORY; |
@@ -606,9 +599,10 @@ static void pcmciamtd_config(dev_link_t *link) | |||
606 | link->conf.ConfigIndex = 0; | 599 | link->conf.ConfigIndex = 0; |
607 | link->conf.Present = t.Present; | 600 | link->conf.Present = t.Present; |
608 | DEBUG(2, "Setting Configuration"); | 601 | DEBUG(2, "Setting Configuration"); |
609 | ret = pcmcia_request_configuration(link->handle, &link->conf); | 602 | ret = pcmcia_request_configuration(link, &link->conf); |
610 | if(ret != CS_SUCCESS) { | 603 | if(ret != CS_SUCCESS) { |
611 | cs_error(link->handle, RequestConfiguration, ret); | 604 | cs_error(link, RequestConfiguration, ret); |
605 | return -ENODEV; | ||
612 | } | 606 | } |
613 | 607 | ||
614 | if(mem_type == 1) { | 608 | if(mem_type == 1) { |
@@ -629,7 +623,7 @@ static void pcmciamtd_config(dev_link_t *link) | |||
629 | if(!mtd) { | 623 | if(!mtd) { |
630 | DEBUG(1, "Cant find an MTD"); | 624 | DEBUG(1, "Cant find an MTD"); |
631 | pcmciamtd_release(link); | 625 | pcmciamtd_release(link); |
632 | return; | 626 | return -ENODEV; |
633 | } | 627 | } |
634 | 628 | ||
635 | dev->mtd_info = mtd; | 629 | dev->mtd_info = mtd; |
@@ -654,7 +648,6 @@ static void pcmciamtd_config(dev_link_t *link) | |||
654 | use the faster non-remapping read/write functions */ | 648 | use the faster non-remapping read/write functions */ |
655 | if(mtd->size <= dev->win_size) { | 649 | if(mtd->size <= dev->win_size) { |
656 | DEBUG(1, "Using non remapping memory functions"); | 650 | DEBUG(1, "Using non remapping memory functions"); |
657 | dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state); | ||
658 | dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base; | 651 | dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base; |
659 | if (dev->pcmcia_map.bankwidth == 1) { | 652 | if (dev->pcmcia_map.bankwidth == 1) { |
660 | dev->pcmcia_map.read = pcmcia_read8; | 653 | dev->pcmcia_map.read = pcmcia_read8; |
@@ -672,19 +665,18 @@ static void pcmciamtd_config(dev_link_t *link) | |||
672 | dev->mtd_info = NULL; | 665 | dev->mtd_info = NULL; |
673 | err("Couldnt register MTD device"); | 666 | err("Couldnt register MTD device"); |
674 | pcmciamtd_release(link); | 667 | pcmciamtd_release(link); |
675 | return; | 668 | return -ENODEV; |
676 | } | 669 | } |
677 | snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index); | 670 | snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index); |
678 | info("mtd%d: %s", mtd->index, mtd->name); | 671 | info("mtd%d: %s", mtd->index, mtd->name); |
679 | link->state &= ~DEV_CONFIG_PENDING; | 672 | link->dev_node = &dev->node; |
680 | link->dev = &dev->node; | 673 | return 0; |
681 | return; | ||
682 | 674 | ||
683 | cs_failed: | 675 | cs_failed: |
684 | cs_error(link->handle, last_fn, last_ret); | 676 | cs_error(link, last_fn, last_ret); |
685 | err("CS Error, exiting"); | 677 | err("CS Error, exiting"); |
686 | pcmciamtd_release(link); | 678 | pcmciamtd_release(link); |
687 | return; | 679 | return -ENODEV; |
688 | } | 680 | } |
689 | 681 | ||
690 | 682 | ||
@@ -713,21 +705,18 @@ static int pcmciamtd_resume(struct pcmcia_device *dev) | |||
713 | * when the device is released. | 705 | * when the device is released. |
714 | */ | 706 | */ |
715 | 707 | ||
716 | static void pcmciamtd_detach(struct pcmcia_device *p_dev) | 708 | static void pcmciamtd_detach(struct pcmcia_device *link) |
717 | { | 709 | { |
718 | dev_link_t *link = dev_to_instance(p_dev); | 710 | struct pcmciamtd_dev *dev = link->priv; |
719 | 711 | ||
720 | DEBUG(3, "link=0x%p", link); | 712 | DEBUG(3, "link=0x%p", link); |
721 | 713 | ||
722 | if(link->state & DEV_CONFIG) { | 714 | if(dev->mtd_info) { |
723 | struct pcmciamtd_dev *dev = link->priv; | 715 | del_mtd_device(dev->mtd_info); |
724 | if(dev->mtd_info) { | 716 | info("mtd%d: Removed", dev->mtd_info->index); |
725 | del_mtd_device(dev->mtd_info); | ||
726 | info("mtd%d: Removed", dev->mtd_info->index); | ||
727 | } | ||
728 | |||
729 | pcmciamtd_release(link); | ||
730 | } | 717 | } |
718 | |||
719 | pcmciamtd_release(link); | ||
731 | } | 720 | } |
732 | 721 | ||
733 | 722 | ||
@@ -736,10 +725,9 @@ static void pcmciamtd_detach(struct pcmcia_device *p_dev) | |||
736 | * with Card Services. | 725 | * with Card Services. |
737 | */ | 726 | */ |
738 | 727 | ||
739 | static int pcmciamtd_attach(struct pcmcia_device *p_dev) | 728 | static int pcmciamtd_probe(struct pcmcia_device *link) |
740 | { | 729 | { |
741 | struct pcmciamtd_dev *dev; | 730 | struct pcmciamtd_dev *dev; |
742 | dev_link_t *link; | ||
743 | 731 | ||
744 | /* Create new memory card device */ | 732 | /* Create new memory card device */ |
745 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); | 733 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); |
@@ -747,20 +735,13 @@ static int pcmciamtd_attach(struct pcmcia_device *p_dev) | |||
747 | DEBUG(1, "dev=0x%p", dev); | 735 | DEBUG(1, "dev=0x%p", dev); |
748 | 736 | ||
749 | memset(dev, 0, sizeof(*dev)); | 737 | memset(dev, 0, sizeof(*dev)); |
750 | link = &dev->link; | 738 | dev->p_dev = link; |
751 | link->priv = dev; | 739 | link->priv = dev; |
752 | 740 | ||
753 | link->conf.Attributes = 0; | 741 | link->conf.Attributes = 0; |
754 | link->conf.IntType = INT_MEMORY; | 742 | link->conf.IntType = INT_MEMORY; |
755 | 743 | ||
756 | link->next = NULL; | 744 | return pcmciamtd_config(link); |
757 | link->handle = p_dev; | ||
758 | p_dev->instance = link; | ||
759 | |||
760 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
761 | pcmciamtd_config(link); | ||
762 | |||
763 | return 0; | ||
764 | } | 745 | } |
765 | 746 | ||
766 | static struct pcmcia_device_id pcmciamtd_ids[] = { | 747 | static struct pcmcia_device_id pcmciamtd_ids[] = { |
@@ -794,7 +775,7 @@ static struct pcmcia_driver pcmciamtd_driver = { | |||
794 | .drv = { | 775 | .drv = { |
795 | .name = "pcmciamtd" | 776 | .name = "pcmciamtd" |
796 | }, | 777 | }, |
797 | .probe = pcmciamtd_attach, | 778 | .probe = pcmciamtd_probe, |
798 | .remove = pcmciamtd_detach, | 779 | .remove = pcmciamtd_detach, |
799 | .owner = THIS_MODULE, | 780 | .owner = THIS_MODULE, |
800 | .id_table = pcmciamtd_ids, | 781 | .id_table = pcmciamtd_ids, |