diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2005-06-27 19:28:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-27 21:03:06 -0400 |
commit | 1ad275e3e7d253d44f03868e85977c908e334fed (patch) | |
tree | 82f0a1fc070f32c015be14596c50c681d90d4c1a | |
parent | 3ee13937525f6044d769b1a84d5db5669ac1959e (diff) |
[PATCH] pcmcia: device and driver matching
The actual matching of pcmcia drivers and pcmcia devices. The original
version of this was written by David Woodhouse.
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/pcmcia/ds.c | 123 | ||||
-rw-r--r-- | include/linux/mod_devicetable.h | 33 | ||||
-rw-r--r-- | include/pcmcia/device_id.h | 175 | ||||
-rw-r--r-- | include/pcmcia/ds.h | 7 |
4 files changed, 336 insertions, 2 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 35d479b0df64..5701b93b2ddb 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -101,6 +101,9 @@ struct pcmcia_bus_socket { | |||
101 | u8 device_count; /* the number of devices, used | 101 | u8 device_count; /* the number of devices, used |
102 | * only internally and subject | 102 | * only internally and subject |
103 | * to incorrectness and change */ | 103 | * to incorrectness and change */ |
104 | |||
105 | u8 device_add_pending; | ||
106 | struct work_struct device_add; | ||
104 | }; | 107 | }; |
105 | static spinlock_t pcmcia_dev_list_lock; | 108 | static spinlock_t pcmcia_dev_list_lock; |
106 | 109 | ||
@@ -512,6 +515,10 @@ static struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, uns | |||
512 | 515 | ||
513 | down(&device_add_lock); | 516 | down(&device_add_lock); |
514 | 517 | ||
518 | /* max of 2 devices per card */ | ||
519 | if (s->device_count == 2) | ||
520 | goto err_put; | ||
521 | |||
515 | p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL); | 522 | p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL); |
516 | if (!p_dev) | 523 | if (!p_dev) |
517 | goto err_put; | 524 | goto err_put; |
@@ -537,6 +544,8 @@ static struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, uns | |||
537 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); | 544 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); |
538 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 545 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
539 | 546 | ||
547 | pcmcia_device_query(p_dev); | ||
548 | |||
540 | if (device_register(&p_dev->dev)) { | 549 | if (device_register(&p_dev->dev)) { |
541 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 550 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
542 | list_del(&p_dev->socket_device_list); | 551 | list_del(&p_dev->socket_device_list); |
@@ -591,14 +600,123 @@ static int pcmcia_card_add(struct pcmcia_socket *s) | |||
591 | } | 600 | } |
592 | 601 | ||
593 | 602 | ||
603 | static void pcmcia_delayed_add_pseudo_device(void *data) | ||
604 | { | ||
605 | struct pcmcia_bus_socket *s = data; | ||
606 | pcmcia_device_add(s, 0); | ||
607 | s->device_add_pending = 0; | ||
608 | } | ||
609 | |||
610 | static inline void pcmcia_add_pseudo_device(struct pcmcia_bus_socket *s) | ||
611 | { | ||
612 | if (!s->device_add_pending) { | ||
613 | schedule_work(&s->device_add); | ||
614 | s->device_add_pending = 1; | ||
615 | } | ||
616 | return; | ||
617 | } | ||
618 | |||
619 | |||
620 | static inline int pcmcia_devmatch(struct pcmcia_device *dev, | ||
621 | struct pcmcia_device_id *did) | ||
622 | { | ||
623 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID) { | ||
624 | if ((!dev->has_manf_id) || (dev->manf_id != did->manf_id)) | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID) { | ||
629 | if ((!dev->has_card_id) || (dev->card_id != did->card_id)) | ||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION) { | ||
634 | if (dev->func != did->function) | ||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1) { | ||
639 | if (!dev->prod_id[0]) | ||
640 | return 0; | ||
641 | if (strcmp(did->prod_id[0], dev->prod_id[0])) | ||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2) { | ||
646 | if (!dev->prod_id[1]) | ||
647 | return 0; | ||
648 | if (strcmp(did->prod_id[1], dev->prod_id[1])) | ||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3) { | ||
653 | if (!dev->prod_id[2]) | ||
654 | return 0; | ||
655 | if (strcmp(did->prod_id[2], dev->prod_id[2])) | ||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4) { | ||
660 | if (!dev->prod_id[3]) | ||
661 | return 0; | ||
662 | if (strcmp(did->prod_id[3], dev->prod_id[3])) | ||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { | ||
667 | /* handle pseudo multifunction devices: | ||
668 | * there are at most two pseudo multifunction devices. | ||
669 | * if we're matching against the first, schedule a | ||
670 | * call which will then check whether there are two | ||
671 | * pseudo devices, and if not, add the second one. | ||
672 | */ | ||
673 | if (dev->device_no == 0) | ||
674 | pcmcia_add_pseudo_device(dev->socket->pcmcia); | ||
675 | |||
676 | if (dev->device_no != did->device_no) | ||
677 | return 0; | ||
678 | } | ||
679 | |||
680 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { | ||
681 | if ((!dev->has_func_id) || (dev->func_id != did->func_id)) | ||
682 | return 0; | ||
683 | |||
684 | /* if this is a pseudo-multi-function device, | ||
685 | * we need explicit matches */ | ||
686 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) | ||
687 | return 0; | ||
688 | if (dev->device_no) | ||
689 | return 0; | ||
690 | |||
691 | /* also, FUNC_ID matching needs to be activated by userspace | ||
692 | * after it has re-checked that there is no possible module | ||
693 | * with a prod_id/manf_id/card_id match. | ||
694 | */ | ||
695 | if (!dev->allow_func_id_match) | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | dev->dev.driver_data = (void *) did; | ||
700 | |||
701 | return 1; | ||
702 | } | ||
703 | |||
704 | |||
594 | static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { | 705 | static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { |
595 | struct pcmcia_device * p_dev = to_pcmcia_dev(dev); | 706 | struct pcmcia_device * p_dev = to_pcmcia_dev(dev); |
596 | struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); | 707 | struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); |
708 | struct pcmcia_device_id *did = p_drv->id_table; | ||
597 | 709 | ||
598 | /* matching by cardmgr */ | 710 | /* matching by cardmgr */ |
599 | if (p_dev->cardmgr == p_drv) | 711 | if (p_dev->cardmgr == p_drv) |
600 | return 1; | 712 | return 1; |
601 | 713 | ||
714 | while (did && did->match_flags) { | ||
715 | if (pcmcia_devmatch(p_dev, did)) | ||
716 | return 1; | ||
717 | did++; | ||
718 | } | ||
719 | |||
602 | return 0; | 720 | return 0; |
603 | } | 721 | } |
604 | 722 | ||
@@ -922,7 +1040,9 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) | |||
922 | rescan: | 1040 | rescan: |
923 | p_dev->cardmgr = p_drv; | 1041 | p_dev->cardmgr = p_drv; |
924 | 1042 | ||
925 | pcmcia_device_query(p_dev); | 1043 | /* if a driver is already running, we can abort */ |
1044 | if (p_dev->dev.driver) | ||
1045 | goto err_put_module; | ||
926 | 1046 | ||
927 | /* | 1047 | /* |
928 | * Prevent this racing with a card insertion. | 1048 | * Prevent this racing with a card insertion. |
@@ -1595,6 +1715,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) | |||
1595 | 1715 | ||
1596 | init_waitqueue_head(&s->queue); | 1716 | init_waitqueue_head(&s->queue); |
1597 | INIT_LIST_HEAD(&s->devices_list); | 1717 | INIT_LIST_HEAD(&s->devices_list); |
1718 | INIT_WORK(&s->device_add, pcmcia_delayed_add_pseudo_device, s); | ||
1598 | 1719 | ||
1599 | /* Set up hotline to Card Services */ | 1720 | /* Set up hotline to Card Services */ |
1600 | s->callback.owner = THIS_MODULE; | 1721 | s->callback.owner = THIS_MODULE; |
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index d6eb7b2efc04..e9651cd8310c 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
@@ -175,4 +175,37 @@ struct serio_device_id { | |||
175 | }; | 175 | }; |
176 | 176 | ||
177 | 177 | ||
178 | /* PCMCIA */ | ||
179 | |||
180 | struct pcmcia_device_id { | ||
181 | __u16 match_flags; | ||
182 | |||
183 | __u16 manf_id; | ||
184 | __u16 card_id; | ||
185 | |||
186 | __u8 func_id; | ||
187 | |||
188 | /* for real multi-function devices */ | ||
189 | __u8 function; | ||
190 | |||
191 | /* for pseude multi-function devices */ | ||
192 | __u8 device_no; | ||
193 | |||
194 | const char * prod_id[4]; | ||
195 | __u32 prod_id_hash[4]; | ||
196 | |||
197 | /* not matched against */ | ||
198 | kernel_ulong_t driver_info; | ||
199 | }; | ||
200 | |||
201 | #define PCMCIA_DEV_ID_MATCH_MANF_ID 0x0001 | ||
202 | #define PCMCIA_DEV_ID_MATCH_CARD_ID 0x0002 | ||
203 | #define PCMCIA_DEV_ID_MATCH_FUNC_ID 0x0004 | ||
204 | #define PCMCIA_DEV_ID_MATCH_FUNCTION 0x0008 | ||
205 | #define PCMCIA_DEV_ID_MATCH_PROD_ID1 0x0010 | ||
206 | #define PCMCIA_DEV_ID_MATCH_PROD_ID2 0x0020 | ||
207 | #define PCMCIA_DEV_ID_MATCH_PROD_ID3 0x0040 | ||
208 | #define PCMCIA_DEV_ID_MATCH_PROD_ID4 0x0080 | ||
209 | #define PCMCIA_DEV_ID_MATCH_DEVICE_NO 0x0100 | ||
210 | |||
178 | #endif /* LINUX_MOD_DEVICETABLE_H */ | 211 | #endif /* LINUX_MOD_DEVICETABLE_H */ |
diff --git a/include/pcmcia/device_id.h b/include/pcmcia/device_id.h new file mode 100644 index 000000000000..acf68656de3c --- /dev/null +++ b/include/pcmcia/device_id.h | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | * Copyright (2003-2004) Dominik Brodowski <linux@brodo.de> | ||
3 | * David Woodhouse | ||
4 | * | ||
5 | * License: GPL v2 | ||
6 | */ | ||
7 | |||
8 | #define PCMCIA_DEVICE_MANF_CARD(manf, card) { \ | ||
9 | .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \ | ||
10 | PCMCIA_DEV_ID_MATCH_CARD_ID, \ | ||
11 | .manf_id = (manf), \ | ||
12 | .card_id = (card), } | ||
13 | |||
14 | #define PCMCIA_DEVICE_FUNC_ID(func) { \ | ||
15 | .match_flags = PCMCIA_DEV_ID_MATCH_FUNC_ID, \ | ||
16 | .func_id = (func), } | ||
17 | |||
18 | #define PCMCIA_DEVICE_PROD_ID1(v1, vh1) { \ | ||
19 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1, \ | ||
20 | .prod_id = { (v1), NULL, NULL, NULL }, \ | ||
21 | .prod_id_hash = { (vh1), 0, 0, 0 }, } | ||
22 | |||
23 | #define PCMCIA_DEVICE_PROD_ID2(v2, vh2) { \ | ||
24 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID2, \ | ||
25 | .prod_id = { NULL, (v2), NULL, NULL }, \ | ||
26 | .prod_id_hash = { 0, (vh2), 0, 0 }, } | ||
27 | |||
28 | #define PCMCIA_DEVICE_PROD_ID12(v1, v2, vh1, vh2) { \ | ||
29 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
30 | PCMCIA_DEV_ID_MATCH_PROD_ID2, \ | ||
31 | .prod_id = { (v1), (v2), NULL, NULL }, \ | ||
32 | .prod_id_hash = { (vh1), (vh2), 0, 0 }, } | ||
33 | |||
34 | #define PCMCIA_DEVICE_PROD_ID13(v1, v3, vh1, vh3) { \ | ||
35 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
36 | PCMCIA_DEV_ID_MATCH_PROD_ID3, \ | ||
37 | .prod_id = { (v1), NULL, (v3), NULL }, \ | ||
38 | .prod_id_hash = { (vh1), 0, (vh3), 0 }, } | ||
39 | |||
40 | #define PCMCIA_DEVICE_PROD_ID14(v1, v4, vh1, vh4) { \ | ||
41 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
42 | PCMCIA_DEV_ID_MATCH_PROD_ID4, \ | ||
43 | .prod_id = { (v1), NULL, NULL, (v4) }, \ | ||
44 | .prod_id_hash = { (vh1), 0, 0, (vh4) }, } | ||
45 | |||
46 | #define PCMCIA_DEVICE_PROD_ID123(v1, v2, v3, vh1, vh2, vh3) { \ | ||
47 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
48 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
49 | PCMCIA_DEV_ID_MATCH_PROD_ID3, \ | ||
50 | .prod_id = { (v1), (v2), (v3), NULL },\ | ||
51 | .prod_id_hash = { (vh1), (vh2), (vh3), 0 }, } | ||
52 | |||
53 | #define PCMCIA_DEVICE_PROD_ID124(v1, v2, v4, vh1, vh2, vh4) { \ | ||
54 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
55 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
56 | PCMCIA_DEV_ID_MATCH_PROD_ID4, \ | ||
57 | .prod_id = { (v1), (v2), NULL, (v4) }, \ | ||
58 | .prod_id_hash = { (vh1), (vh2), 0, (vh4) }, } | ||
59 | |||
60 | #define PCMCIA_DEVICE_PROD_ID134(v1, v3, v4, vh1, vh3, vh4) { \ | ||
61 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
62 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
63 | PCMCIA_DEV_ID_MATCH_PROD_ID4, \ | ||
64 | .prod_id = { (v1), NULL, (v3), (v4) }, \ | ||
65 | .prod_id_hash = { (vh1), 0, (vh3), (vh4) }, } | ||
66 | |||
67 | #define PCMCIA_DEVICE_PROD_ID1234(v1, v2, v3, v4, vh1, vh2, vh3, vh4) { \ | ||
68 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
69 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
70 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
71 | PCMCIA_DEV_ID_MATCH_PROD_ID4, \ | ||
72 | .prod_id = { (v1), (v2), (v3), (v4) }, \ | ||
73 | .prod_id_hash = { (vh1), (vh2), (vh3), (vh4) }, } | ||
74 | |||
75 | |||
76 | /* multi-function devices */ | ||
77 | |||
78 | #define PCMCIA_MFC_DEVICE_MANF_CARD(mfc, manf, card) { \ | ||
79 | .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \ | ||
80 | PCMCIA_DEV_ID_MATCH_CARD_ID| \ | ||
81 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
82 | .manf_id = (manf), \ | ||
83 | .card_id = (card), \ | ||
84 | .function = (mfc), } | ||
85 | |||
86 | #define PCMCIA_MFC_DEVICE_PROD_ID1(mfc, v1, vh1) { \ | ||
87 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
88 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
89 | .prod_id = { (v1), NULL, NULL, NULL }, \ | ||
90 | .prod_id_hash = { (vh1), 0, 0, 0 }, \ | ||
91 | .function = (mfc), } | ||
92 | |||
93 | #define PCMCIA_MFC_DEVICE_PROD_ID2(mfc, v2, vh2) { \ | ||
94 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
95 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
96 | .prod_id = { NULL, (v2), NULL, NULL }, \ | ||
97 | .prod_id_hash = { 0, (vh2), 0, 0 }, \ | ||
98 | .function = (mfc), } | ||
99 | |||
100 | #define PCMCIA_MFC_DEVICE_PROD_ID12(mfc, v1, v2, vh1, vh2) { \ | ||
101 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
102 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
103 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
104 | .prod_id = { (v1), (v2), NULL, NULL }, \ | ||
105 | .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ | ||
106 | .function = (mfc), } | ||
107 | |||
108 | #define PCMCIA_MFC_DEVICE_PROD_ID13(mfc, v1, v3, vh1, vh3) { \ | ||
109 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
110 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
111 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
112 | .prod_id = { (v1), NULL, (v3), NULL }, \ | ||
113 | .prod_id_hash = { (vh1), 0, (vh3), 0 }, \ | ||
114 | .function = (mfc), } | ||
115 | |||
116 | #define PCMCIA_MFC_DEVICE_PROD_ID123(mfc, v1, v2, v3, vh1, vh2, vh3) { \ | ||
117 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
118 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
119 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
120 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
121 | .prod_id = { (v1), (v2), (v3), NULL },\ | ||
122 | .prod_id_hash = { (vh1), (vh2), (vh3), 0 }, \ | ||
123 | .function = (mfc), } | ||
124 | |||
125 | /* pseudo multi-function devices */ | ||
126 | |||
127 | #define PCMCIA_PFC_DEVICE_MANF_CARD(mfc, manf, card) { \ | ||
128 | .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \ | ||
129 | PCMCIA_DEV_ID_MATCH_CARD_ID| \ | ||
130 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
131 | .manf_id = (manf), \ | ||
132 | .card_id = (card), \ | ||
133 | .device_no = (mfc), } | ||
134 | |||
135 | #define PCMCIA_PFC_DEVICE_PROD_ID1(mfc, v1, vh1) { \ | ||
136 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
137 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
138 | .prod_id = { (v1), NULL, NULL, NULL }, \ | ||
139 | .prod_id_hash = { (vh1), 0, 0, 0 }, \ | ||
140 | .device_no = (mfc), } | ||
141 | |||
142 | #define PCMCIA_PFC_DEVICE_PROD_ID2(mfc, v2, vh2) { \ | ||
143 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
144 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
145 | .prod_id = { NULL, (v2), NULL, NULL }, \ | ||
146 | .prod_id_hash = { 0, (vh2), 0, 0 }, \ | ||
147 | .device_no = (mfc), } | ||
148 | |||
149 | #define PCMCIA_PFC_DEVICE_PROD_ID12(mfc, v1, v2, vh1, vh2) { \ | ||
150 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
151 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
152 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
153 | .prod_id = { (v1), (v2), NULL, NULL }, \ | ||
154 | .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ | ||
155 | .device_no = (mfc), } | ||
156 | |||
157 | #define PCMCIA_PFC_DEVICE_PROD_ID13(mfc, v1, v3, vh1, vh3) { \ | ||
158 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
159 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
160 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
161 | .prod_id = { (v1), NULL, (v3), NULL }, \ | ||
162 | .prod_id_hash = { (vh1), 0, (vh3), 0 }, \ | ||
163 | .device_no = (mfc), } | ||
164 | |||
165 | #define PCMCIA_PFC_DEVICE_PROD_ID123(mfc, v1, v2, v3, vh1, vh2, vh3) { \ | ||
166 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
167 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
168 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
169 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
170 | .prod_id = { (v1), (v2), (v3), NULL },\ | ||
171 | .prod_id_hash = { (vh1), (vh2), (vh3), 0 }, \ | ||
172 | .device_no = (mfc), } | ||
173 | |||
174 | |||
175 | #define PCMCIA_DEVICE_NULL { .match_flags = 0, } | ||
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index 312fd958c901..c267edde9d0c 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h | |||
@@ -18,6 +18,8 @@ | |||
18 | 18 | ||
19 | #include <pcmcia/bulkmem.h> | 19 | #include <pcmcia/bulkmem.h> |
20 | #include <pcmcia/cs_types.h> | 20 | #include <pcmcia/cs_types.h> |
21 | #include <pcmcia/device_id.h> | ||
22 | #include <linux/mod_devicetable.h> | ||
21 | 23 | ||
22 | typedef struct tuple_parse_t { | 24 | typedef struct tuple_parse_t { |
23 | tuple_t tuple; | 25 | tuple_t tuple; |
@@ -135,6 +137,7 @@ struct pcmcia_driver { | |||
135 | dev_link_t *(*attach)(void); | 137 | dev_link_t *(*attach)(void); |
136 | void (*detach)(dev_link_t *); | 138 | void (*detach)(dev_link_t *); |
137 | struct module *owner; | 139 | struct module *owner; |
140 | struct pcmcia_device_id *id_table; | ||
138 | struct device_driver drv; | 141 | struct device_driver drv; |
139 | }; | 142 | }; |
140 | 143 | ||
@@ -173,7 +176,9 @@ struct pcmcia_device { | |||
173 | u8 has_manf_id:1; | 176 | u8 has_manf_id:1; |
174 | u8 has_card_id:1; | 177 | u8 has_card_id:1; |
175 | u8 has_func_id:1; | 178 | u8 has_func_id:1; |
176 | u8 reserved:5; | 179 | |
180 | u8 allow_func_id_match:1; | ||
181 | u8 reserved:4; | ||
177 | 182 | ||
178 | u8 func_id; | 183 | u8 func_id; |
179 | u16 manf_id; | 184 | u16 manf_id; |