]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/staging/wlan-ng/prism2_cs.c
63ce5659f21a8657434fdff41db727a2f8821249
[mirror_ubuntu-artful-kernel.git] / drivers / staging / wlan-ng / prism2_cs.c
1 #define WLAN_HOSTIF WLAN_PCMCIA
2 #include "hfa384x.c"
3 #include "prism2mgmt.c"
4 #include "prism2mib.c"
5 #include "prism2sta.c"
6
7 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21) )
8 #if (WLAN_CPU_FAMILY == WLAN_Ix86)
9 #ifndef CONFIG_ISA
10 #warning "You may need to enable ISA support in your kernel."
11 #endif
12 #endif
13 #endif
14
15 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
16 static u_int irq_mask = 0xdeb8; /* Interrupt mask */
17 static int irq_list[4] = { -1 }; /* Interrupt list */
18 #endif
19 static u_int prism2_ignorevcc=1; /* Boolean, if set, we
20 * ignore what the Vcc
21 * is set to and what the CIS
22 * says.
23 */
24 module_param( prism2_ignorevcc, int, 0644);
25
26 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
27 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9))
28 static int numlist = 4;
29 module_param_array(irq_list, int, numlist, 0444);
30 #else
31 module_param_array(irq_list, int, NULL, 0444);
32 #endif
33 module_param( irq_mask, int, 0644);
34 #endif
35
36 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
37 static int prism2_cs_suspend(struct pcmcia_device *pdev);
38 static int prism2_cs_resume(struct pcmcia_device *pdev);
39 static void prism2_cs_remove(struct pcmcia_device *pdev);
40 static int prism2_cs_probe(struct pcmcia_device *pdev);
41 #else
42 dev_link_t *prism2sta_attach(void);
43 static void prism2sta_detach(dev_link_t *link);
44 static void prism2sta_config(dev_link_t *link);
45 static void prism2sta_release(u_long arg);
46 static int prism2sta_event (event_t event, int priority, event_callback_args_t *args);
47
48 static dev_link_t *dev_list = NULL; /* head of instance list */
49 #endif
50
51 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
52 /*----------------------------------------------------------------
53 * cs_error
54 *
55 * Utility function to print card services error messages.
56 *
57 * Arguments:
58 * handle client handle identifying this CS client
59 * func CS function number that generated the error
60 * ret CS function return code
61 *
62 * Returns:
63 * nothing
64 * Side effects:
65 *
66 * Call context:
67 * process thread
68 * interrupt
69 ----------------------------------------------------------------*/
70 static void cs_error(client_handle_t handle, int func, int ret)
71 {
72 #if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911))
73 CardServices(ReportError, dev_info, (void *)func, (void *)ret);
74 #else
75 error_info_t err = { func, ret };
76 pcmcia_report_error(handle, &err);
77 #endif
78 }
79 #else // kernel_version
80
81 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12)
82 static struct pcmcia_device_id prism2_cs_ids[] = {
83 PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), // Intersil PRISM2 Reference Design 11Mb/s 802.11b WLAN Card
84 PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), // Compaq WL100/200 11Mb/s 802.11b WLAN Card
85 PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), // Compaq iPaq HNW-100 11Mb/s 802.11b WLAN Card
86 PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), // Samsung SWL2000-N 11Mb/s 802.11b WLAN Card
87 PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), // Z-Com XI300 11Mb/s 802.11b WLAN Card
88 PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), // ZoomAir 4100 11Mb/s 802.11b WLAN Card
89 PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), // Linksys WPC11 11Mbps 802.11b WLAN Card
90 PCMCIA_DEVICE_PROD_ID123("Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", 0xe6ec52ce, 0x8649af2, 0x4b74baa0), // Addtron AWP-100 11Mbps 802.11b WLAN Card
91 PCMCIA_DEVICE_PROD_ID123("D", "Link DWL-650 11Mbps WLAN Card", "Version 01.02", 0x71b18589, 0xb6f1b0ab, 0x4b74baa0), // D-Link DWL-650 11Mbps 802.11b WLAN Card
92 PCMCIA_DEVICE_PROD_ID123("SMC", "SMC2632W", "Version 01.02", 0xc4f8b18b, 0x474a1f2a, 0x4b74baa0), // SMC 2632W 11Mbps 802.11b WLAN Card
93 PCMCIA_DEVICE_PROD_ID1234("Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P", "Eval-RevA", 0x4b801a17, 0x6345a0bf, 0xc9049a39, 0xc23adc0e), // BroMax Freeport 11Mbps 802.11b WLAN Card (Prism 2.5)
94 PCMCIA_DEVICE_PROD_ID123("U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", 0xc7b8df9d, 0x1700d087, 0x4b74baa0), // U.S. Robotics IEEE 802.11b PC-CARD
95 PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146), // Level-One WPC-0100
96 PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), // Bromax OEM 11Mbps 802.11b WLAN Card (Prism 2.5)
97 PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), // Bromax OEM 11Mbps 802.11b WLAN Card (Prism 3)
98 PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), // corega K.K. Wireless LAN PCC-11
99 PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), // corega K.K. Wireless LAN PCCA-11
100 PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), // CONTEC FLEXSCAN/FX-DDS110-PCC
101 PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), // PLANEX GeoWave/GW-NS110
102 PCMCIA_DEVICE_PROD_ID123("OEM", "PRISM2 IEEE 802.11 PC-Card", "Version 01.02", 0xfea54c90, 0x48f2bdd6, 0x4b74baa0), // Ambicom WL1100 11Mbps 802.11b WLAN Card
103 PCMCIA_DEVICE_PROD_ID123("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", "Version 01.02", 0x7e3b326a, 0x49893e92, 0x4b74baa0), // LeArtery SYNCBYAIR 11Mbps 802.11b WLAN Card
104 PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), // Intermec MobileLAN 11Mbps 802.11b WLAN Card
105 PCMCIA_DEVICE_PROD_ID123("NETGEAR MA401 Wireless PC", "Card", "Version 01.00", 0xa37434e9, 0x9762e8f1, 0xa57adb8c), // NETGEAR MA401 11Mbps 802.11 WLAN Card
106 PCMCIA_DEVICE_PROD_ID1234("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", "Eval-RevA", 0x4b801a17, 0xf222ec2d, 0x630d52b2, 0xc23adc0e), // Intersil PRISM Freedom 11mbps 802.11 WLAN Card
107 PCMCIA_DEVICE_PROD_ID123("OTC", "Wireless AirEZY 2411-PCC WLAN Card", "Version 01.02", 0x4ac44287, 0x235a6bed, 0x4b74baa0), // OTC Wireless AirEZY 2411-PCC 11Mbps 802.11 WLAN Card
108 PCMCIA_DEVICE_PROD_ID1234("802.11", "11Mbps Wireless LAN Card", "v08C1", "" , 0xb67a610e, 0x655aa7b7, 0x264b451a, 0x0), // Dynalink L11HDT 11Mbps 802.11 WLAN Card
109 PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), // Dynalink L11HDT 11Mbps 802.11 WLAN Card
110 PCMCIA_DEVICE_PROD_ID12("PROXIM", "RangeLAN-DS/LAN PC CARD", 0xc6536a5e, 0x3f35797d), // PROXIM RangeLAN-DS/LAN PC CARD
111 PCMCIA_DEVICE_PROD_ID1234("ACTIONTEC", "PRISM Wireless LAN PC Card", "0381", "RevA", 0x393089da, 0xa71e69d5, 0x90471fa9, 0x57a66194), // ACTIONTEC PRISM Wireless LAN PC Card
112 PCMCIA_DEVICE_MANF_CARD(0x1668, 0x0101), // ACTIONTEC PRISM Wireless LAN PC Card
113 PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), // 3Com AirConnect 3CRWE737A
114 PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE777A AirConnect Wireless LAN PCI Card" , 0x41240e5b, 0xafc7c33e), // 3Com AirConnect 3CRWE777A
115 PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), // ASUS WL-100 802.11b WLAN PC Card
116 PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), // ASUS WL-110 802.11b WLAN CF Card
117 PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), // BUFFALO WLI-CF-S11G 802.11b WLAN Card
118 PCMCIA_DEVICE_PROD_ID1234("The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", "RevA", 0xa5f472c2, 0x9c05598d, 0xc9049a39, 0x57a66194), // Linksys WCF11 11Mbps 802.11b WLAN Card (Prism 2.5)
119 PCMCIA_DEVICE_PROD_ID1234("Linksys", "Wireless CompactFlash Card", "", "", 0x733cc81, 0xc52f395, 0x0, 0x0), // Linksys WCF12 11Mbps 802.11b WLAN Card (Prism 3)
120 PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), // Linksys WCF12 11Mbps 802.11b WLAN Card (Prism 3)
121 PCMCIA_DEVICE_PROD_ID1234("NETGEAR MA401RA Wireless PC", "Card", "ISL37300P", "Eval-RevA", 0x306467f, 0x9762e8f1, 0xc9049a39, 0xc23adc0e), // NETGEAR MA401RA 11Mbps 802.11 WLAN Card
122 PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), // D-Link DCF-660W 11Mbps 802.11b WLAN Card
123 PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001), // Microsoft Wireless Notebook Adapter MN-520
124 PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), // AnyPoint(TM) Wireless II PC Card
125 PCMCIA_DEVICE_PROD_ID1234("D", "Link DRC-650 11Mbps WLAN Card", "Version 01.02", "" , 0x71b18589, 0xf144e3ac, 0x4b74baa0, 0x0), // D-Link DRC-650 802.11b WLAN Card
126 PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), // Adaptec AWN-8030
127 PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7110), // D-Link DWL-650 rev P 802.11b WLAN card
128 // PCMCIA_DEVICE_PROD_ID1234("D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10", "A3", 0x1a424a1c, 0x6ea57632, 0xdd97a26b, 0x56b21f52), // D-Link DWL-650 rev P 802.11b WLAN card
129 PCMCIA_DEVICE_PROD_ID123("INTERSIL", "I-GATE 11M PC Card / PC Card plus", "Version 01.02", 0x74c5e40d, 0x8304ff77, 0x4b74baa0), // I-Gate 11M PC Card
130 PCMCIA_DEVICE_PROD_ID1234("BENQ", "AWL100 PCMCIA ADAPTER", "ISL37300P", "Eval-RevA", 0x35dadc74, 0x1f7fedb, 0xc9049a39, 0xc23adc0e), // benQ AWL100 802.11b WLAN Card
131 PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), // benQ AWL100 802.11b WLAN Card
132 // PCMCIA_DEVICE_PROD_ID1("INTERSIL", 0x74c5e40d), // Intersil Prism 2 card
133 // PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), // Intersil Prism 2 card
134
135 PCMCIA_DEVICE_NULL
136 };
137
138 MODULE_DEVICE_TABLE(pcmcia, prism2_cs_ids);
139 #endif
140
141 static struct pcmcia_driver prism2_cs_driver = {
142 .drv = {
143 .name = "prism2_cs",
144 },
145 .owner = THIS_MODULE,
146 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
147 .suspend = prism2_cs_suspend,
148 .resume = prism2_cs_resume,
149 .remove = prism2_cs_remove,
150 .probe = prism2_cs_probe,
151 .id_table = prism2_cs_ids,
152 #else
153 .attach = prism2sta_attach,
154 .detach = prism2sta_detach,
155 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12)
156 .id_table = prism2_cs_ids,
157 .event = prism2sta_event,
158 #endif // > 2.6.12
159 #endif // <= 2.6.15
160 };
161 #endif /* kernel_version */
162
163 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
164 #define CS_CHECK(fn, ret) \
165 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
166
167 #define CFG_CHECK(fn, retf) \
168 do { int ret = (retf); \
169 if (ret != 0) { \
170 WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
171 cs_error(pdev, fn, ret); \
172 goto next_entry; \
173 } \
174 } while (0)
175
176 static void prism2_cs_remove(struct pcmcia_device *pdev)
177 {
178 struct wlandevice *wlandev;
179
180 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
181 dev_link_t *link = dev_to_instance(pdev);
182 #endif
183
184 DBFENTER;
185
186 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
187 wlandev = pdev->priv;
188 #else
189 wlandev = link->priv;
190 #endif
191
192 if (wlandev) {
193 p80211netdev_hwremoved(wlandev);
194 unregister_wlandev(wlandev);
195 wlan_unsetup(wlandev);
196 if (wlandev->priv) {
197 hfa384x_t *hw = wlandev->priv;
198 wlandev->priv = NULL;
199 if (hw) {
200 hfa384x_destroy(hw);
201 kfree(hw);
202 }
203 }
204 kfree(wlandev);
205 }
206
207 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
208 pdev->priv = NULL;
209 pcmcia_disable_device(pdev);
210 #else
211 if (link->state & DEV_CONFIG) {
212 if (link->win)
213 pcmcia_release_window(link->win);
214 pcmcia_release_configuration(link->handle);
215 if (link->io.NumPorts1)
216 pcmcia_release_io(link->handle, &link->io);
217 if (link->irq.AssignedIRQ)
218 pcmcia_release_irq(link->handle, &link->irq);
219
220 link->state &= ~DEV_CONFIG;
221 }
222
223 link->priv = NULL;
224 kfree(link);
225 #endif
226
227 DBFEXIT;
228 return;
229 }
230
231 static int prism2_cs_suspend(struct pcmcia_device *pdev)
232 {
233 struct wlandevice *wlandev;
234
235 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
236 dev_link_t *link = dev_to_instance(pdev);
237 #endif
238
239 DBFENTER;
240
241 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
242 wlandev = pdev->priv;
243 prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
244 #else
245 wlandev = link->priv;
246
247 link->state |= DEV_SUSPEND;
248 if (link->state & DEV_CONFIG) {
249 prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
250 pcmcia_release_configuration(link->handle);
251 }
252 #endif
253
254 DBFEXIT;
255
256 return 0;
257 }
258
259 static int prism2_cs_resume(struct pcmcia_device *pdev)
260 {
261 struct wlandevice *wlandev;
262
263 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
264 dev_link_t *link = dev_to_instance(pdev);
265 #endif
266
267 DBFENTER;
268
269 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
270 wlandev = pdev->priv;
271 // XXX do something here?
272 #else
273 wlandev = link->priv;
274 link->state &= ~DEV_SUSPEND;
275 if (link->state & DEV_CONFIG) {
276 pcmcia_request_configuration(link->handle, &link->conf);
277 // XXX do something here?
278 }
279 #endif
280
281
282 DBFEXIT;
283
284 return 0;
285 }
286
287 static int prism2_cs_probe(struct pcmcia_device *pdev)
288 {
289 int rval = 0;
290 struct wlandevice *wlandev = NULL;
291 hfa384x_t *hw = NULL;
292
293 config_info_t socketconf;
294 cisparse_t *parse = NULL;
295 tuple_t tuple;
296 uint8_t buf[64];
297 int last_fn, last_ret;
298 cistpl_cftable_entry_t dflt = { 0 };
299
300 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
301 dev_link_t *link;
302 #endif
303
304 DBFENTER;
305
306 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
307 /* Set up interrupt type */
308 pdev->conf.IntType = INT_MEMORY_AND_IO;
309 #else
310 link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
311 if (link == NULL)
312 return -ENOMEM;
313 memset(link, 0, sizeof(dev_link_t));
314
315 link->conf.Vcc = 33;
316 link->conf.IntType = INT_MEMORY_AND_IO;
317
318 link->handle = pdev;
319 pdev->instance = link;
320 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
321
322 #endif
323
324 // VCC crap?
325 parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);
326
327 wlandev = create_wlan();
328 if (!wlandev || !parse) {
329 WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
330 rval = -EIO;
331 goto failed;
332 }
333 hw = wlandev->priv;
334
335 if ( wlan_setup(wlandev) != 0 ) {
336 WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
337 rval = -EIO;
338 goto failed;
339 }
340
341 /* Initialize the hw struct for now */
342 hfa384x_create(hw, 0, 0, NULL);
343 hw->wlandev = wlandev;
344
345 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
346 hw->pdev = pdev;
347 pdev->priv = wlandev;
348 #else
349 hw->link = link;
350 link->priv = wlandev;
351 #endif
352
353 tuple.DesiredTuple = CISTPL_CONFIG;
354 tuple.Attributes = 0;
355 tuple.TupleData = buf;
356 tuple.TupleDataMax = sizeof(buf);
357 tuple.TupleOffset = 0;
358 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
359 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple));
360 CS_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, parse));
361 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
362 pdev->conf.ConfigBase = parse->config.base;
363 pdev->conf.Present = parse->config.rmask[0];
364 #else
365 link->conf.ConfigBase = parse->config.base;
366 link->conf.Present = parse->config.rmask[0];
367
368 link->conf.Vcc = socketconf.Vcc;
369 #endif
370 CS_CHECK(GetConfigurationInfo,
371 pcmcia_get_configuration_info(pdev, &socketconf));
372
373 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
374 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
375 for (;;) {
376 cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
377 CFG_CHECK(GetTupleData,
378 pcmcia_get_tuple_data(pdev, &tuple));
379 CFG_CHECK(ParseTuple,
380 pcmcia_parse_tuple(pdev, &tuple, parse));
381
382 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
383 dflt = *cfg;
384 if (cfg->index == 0)
385 goto next_entry;
386 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
387 pdev->conf.ConfigIndex = cfg->index;
388 #else
389 link->conf.ConfigIndex = cfg->index;
390 #endif
391
392 /* Does this card need audio output? */
393 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
394 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
395 pdev->conf.Attributes |= CONF_ENABLE_SPKR;
396 pdev->conf.Status = CCSR_AUDIO_ENA;
397 #else
398 link->conf.Attributes |= CONF_ENABLE_SPKR;
399 link->conf.Status = CCSR_AUDIO_ENA;
400 #endif
401 }
402
403 /* Use power settings for Vcc and Vpp if present */
404 /* Note that the CIS values need to be rescaled */
405 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
406 if (socketconf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
407 10000 && !prism2_ignorevcc) {
408 WLAN_LOG_DEBUG(1, " Vcc mismatch - skipping"
409 " this entry\n");
410 goto next_entry;
411 }
412 } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
413 if (socketconf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] /
414 10000 && !prism2_ignorevcc) {
415 WLAN_LOG_DEBUG(1, " Vcc (default) mismatch "
416 "- skipping this entry\n");
417 goto next_entry;
418 }
419 }
420
421 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
422 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
423 pdev->conf.Vpp =
424 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
425 #else
426 link->conf.Vpp1 = link->conf.Vpp2 =
427 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
428 #endif
429 } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
430 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
431 pdev->conf.Vpp =
432 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
433 #else
434 link->conf.Vpp1 = link->conf.Vpp2 =
435 dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
436 #endif
437 }
438
439 /* Do we need to allocate an interrupt? */
440 /* HACK: due to a bad CIS....we ALWAYS need an interrupt */
441 /* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */
442 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
443 pdev->conf.Attributes |= CONF_ENABLE_IRQ;
444 #else
445 link->conf.Attributes |= CONF_ENABLE_IRQ;
446 #endif
447
448 /* IO window settings */
449 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
450 pdev->io.NumPorts1 = pdev->io.NumPorts2 = 0;
451 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
452 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
453 pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
454 if (!(io->flags & CISTPL_IO_8BIT))
455 pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
456 if (!(io->flags & CISTPL_IO_16BIT))
457 pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
458 pdev->io.BasePort1 = io->win[0].base;
459 if ( pdev->io.BasePort1 != 0 ) {
460 WLAN_LOG_WARNING(
461 "Brain damaged CIS: hard coded iobase="
462 "0x%x, try letting pcmcia_cs decide...\n",
463 pdev->io.BasePort1 );
464 pdev->io.BasePort1 = 0;
465 }
466 pdev->io.NumPorts1 = io->win[0].len;
467 if (io->nwin > 1) {
468 pdev->io.Attributes2 = pdev->io.Attributes1;
469 pdev->io.BasePort2 = io->win[1].base;
470 pdev->io.NumPorts2 = io->win[1].len;
471 }
472 }
473 /* This reserves IO space but doesn't actually enable it */
474 CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &pdev->io));
475 #else
476 link->io.NumPorts1 = link->io.NumPorts2 = 0;
477 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
478 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
479 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
480 if (!(io->flags & CISTPL_IO_8BIT))
481 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
482 if (!(io->flags & CISTPL_IO_16BIT))
483 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
484 link->io.BasePort1 = io->win[0].base;
485 if ( link->io.BasePort1 != 0 ) {
486 WLAN_LOG_WARNING(
487 "Brain damaged CIS: hard coded iobase="
488 "0x%x, try letting pcmcia_cs decide...\n",
489 link->io.BasePort1 );
490 link->io.BasePort1 = 0;
491 }
492 link->io.NumPorts1 = io->win[0].len;
493 if (io->nwin > 1) {
494 link->io.Attributes2 = link->io.Attributes1;
495 link->io.BasePort2 = io->win[1].base;
496 link->io.NumPorts2 = io->win[1].len;
497 }
498 }
499 /* This reserves IO space but doesn't actually enable it */
500 CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &link->io));
501 #endif
502 /* If we got this far, we're cool! */
503 break;
504
505 next_entry:
506 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
507 dflt = *cfg;
508 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(pdev, &tuple));
509
510 }
511
512 /* Let pcmcia know the device name */
513 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
514 pdev->dev_node = &hw->node;
515 #else
516 link->dev = &hw->node;
517 #endif
518
519 /* Register the network device and get assigned a name */
520 SET_MODULE_OWNER(wlandev->netdev);
521 SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(pdev));
522 if (register_wlandev(wlandev) != 0) {
523 WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n");
524 goto failed;
525 }
526
527 strcpy(hw->node.dev_name, wlandev->name);
528
529 /* Allocate an interrupt line. Note that this does not assign a */
530 /* handler to the interrupt, unless the 'Handler' member of the */
531 /* irq structure is initialized. */
532 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
533 if (pdev->conf.Attributes & CONF_ENABLE_IRQ) {
534 pdev->irq.IRQInfo1 = IRQ_LEVEL_ID;
535 pdev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
536 pdev->irq.Handler = hfa384x_interrupt;
537 pdev->irq.Instance = wlandev;
538 CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq));
539 }
540 #else
541 if (link->conf.Attributes & CONF_ENABLE_IRQ) {
542 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
543 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
544 link->irq.Handler = hfa384x_interrupt;
545 link->irq.Instance = wlandev;
546 CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &link->irq));
547 }
548 #endif
549
550 /* This actually configures the PCMCIA socket -- setting up */
551 /* the I/O windows and the interrupt mapping, and putting the */
552 /* card and host interface into "Memory and IO" mode. */
553 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
554 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf));
555 #else
556 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &link->conf));
557 #endif
558
559 /* Fill the netdevice with this info */
560 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
561 wlandev->netdev->irq = pdev->irq.AssignedIRQ;
562 wlandev->netdev->base_addr = pdev->io.BasePort1;
563 #else
564 wlandev->netdev->irq = link->irq.AssignedIRQ;
565 wlandev->netdev->base_addr = link->io.BasePort1;
566 #endif
567
568 /* And the rest of the hw structure */
569 hw->irq = wlandev->netdev->irq;
570 hw->iobase = wlandev->netdev->base_addr;
571
572 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
573 link->state |= DEV_CONFIG;
574 link->state &= ~DEV_CONFIG_PENDING;
575 #endif
576
577 /* And now we're done! */
578 wlandev->msdstate = WLAN_MSD_HWPRESENT;
579
580 goto done;
581
582 cs_failed:
583 cs_error(pdev, last_fn, last_ret);
584
585 failed:
586 // wlandev, hw, etc etc..
587 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
588 pdev->priv = NULL;
589 #else
590 pdev->instance = NULL;
591 if (link) {
592 link->priv = NULL;
593 kfree(link);
594 }
595 #endif
596 if (wlandev) {
597 wlan_unsetup(wlandev);
598 if (wlandev->priv) {
599 hw = wlandev->priv;
600 wlandev->priv = NULL;
601 if (hw) {
602 hfa384x_destroy(hw);
603 kfree(hw);
604 }
605 }
606 kfree(wlandev);
607 }
608
609 done:
610 if (parse) kfree(parse);
611
612 DBFEXIT;
613 return rval;
614 }
615 #else // <= 2.6.15
616 #define CS_CHECK(fn, ret) \
617 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
618
619 #define CFG_CHECK(fn, retf) \
620 do { int ret = (retf); \
621 if (ret != 0) { \
622 WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
623 cs_error(link->handle, fn, ret); \
624 goto next_entry; \
625 } \
626 } while (0)
627
628 /*----------------------------------------------------------------
629 * prism2sta_attach
630 *
631 * Half of the attach/detach pair. Creates and registers a device
632 * instance with Card Services. In this case, it also creates the
633 * wlandev structure and device private structure. These are
634 * linked to the device instance via its priv member.
635 *
636 * Arguments:
637 * none
638 *
639 * Returns:
640 * A valid ptr to dev_link_t on success, NULL otherwise
641 *
642 * Side effects:
643 *
644 *
645 * Call context:
646 * process thread (insmod/init_module/register_pccard_driver)
647 ----------------------------------------------------------------*/
648 dev_link_t *prism2sta_attach(void)
649 {
650 client_reg_t client_reg;
651 int result;
652 dev_link_t *link = NULL;
653 wlandevice_t *wlandev = NULL;
654 hfa384x_t *hw = NULL;
655
656 DBFENTER;
657
658 /* Alloc our structures */
659 link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
660
661 if (!link || ((wlandev = create_wlan()) == NULL)) {
662 WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
663 result = -EIO;
664 goto failed;
665 }
666 hw = wlandev->priv;
667
668 /* Clear all the structs */
669 memset(link, 0, sizeof(struct dev_link_t));
670
671 if ( wlan_setup(wlandev) != 0 ) {
672 WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
673 result = -EIO;
674 goto failed;
675 }
676
677 /* Initialize the hw struct for now */
678 hfa384x_create(hw, 0, 0, NULL);
679 hw->wlandev = wlandev;
680
681 /* Initialize the PC card device object. */
682 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
683 init_timer(&link->release);
684 link->release.function = &prism2sta_release;
685 link->release.data = (u_long)link;
686 #endif
687 link->conf.IntType = INT_MEMORY_AND_IO;
688 link->priv = wlandev;
689 #if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911))
690 link->irq.Instance = wlandev;
691 #endif
692
693 /* Link in to the list of devices managed by this driver */
694 link->next = dev_list;
695 dev_list = link;
696
697 /* Register with Card Services */
698 client_reg.dev_info = &dev_info;
699 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
700 client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
701 #endif
702
703 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) )
704 client_reg.EventMask =
705 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
706 CS_EVENT_RESET_REQUEST |
707 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
708 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
709 client_reg.event_handler = &prism2sta_event;
710 #endif
711
712 client_reg.Version = 0x0210;
713 client_reg.event_callback_args.client_data = link;
714
715 result = pcmcia_register_client(&link->handle, &client_reg);
716 if (result != 0) {
717 cs_error(link->handle, RegisterClient, result);
718 prism2sta_detach(link);
719 return NULL;
720 }
721
722 goto done;
723
724 failed:
725 if (link) kfree(link);
726 if (wlandev) kfree(wlandev);
727 if (hw) kfree(hw);
728 link = NULL;
729
730 done:
731 DBFEXIT;
732 return link;
733 }
734
735
736 /*----------------------------------------------------------------
737 * prism2sta_detach
738 *
739 * Remove one of the device instances managed by this driver.
740 * Search the list for the given instance,
741 * check our flags for a waiting timer'd release call
742 * call release
743 * Deregister the instance with Card Services
744 * (netdevice) unregister the network device.
745 * unlink the instance from the list
746 * free the link, priv, and priv->priv memory
747 * Note: the dev_list variable is a driver scoped static used to
748 * maintain a list of device instances managed by this
749 * driver.
750 *
751 * Arguments:
752 * link ptr to the instance to detach
753 *
754 * Returns:
755 * nothing
756 *
757 * Side effects:
758 * the link structure is gone, the netdevice is gone
759 *
760 * Call context:
761 * Might be interrupt, don't block.
762 ----------------------------------------------------------------*/
763 void prism2sta_detach(dev_link_t *link)
764 {
765 dev_link_t **linkp;
766 wlandevice_t *wlandev;
767 hfa384x_t *hw;
768
769 DBFENTER;
770
771 /* Locate prev device structure */
772 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
773 if (*linkp == link) break;
774 }
775
776 if (*linkp != NULL) {
777 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
778 unsigned long flags;
779 /* Get rid of any timer'd release call */
780 save_flags(flags);
781 cli();
782 #endif
783
784 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
785 if (link->state & DEV_RELEASE_PENDING) {
786 del_timer_sync(&link->release);
787 link->state &= ~DEV_RELEASE_PENDING;
788 }
789 #endif
790
791 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
792 restore_flags(flags);
793 #endif
794
795 /* If link says we're still config'd, call release */
796 if (link->state & DEV_CONFIG) {
797 prism2sta_release((u_long)link);
798 if (link->state & DEV_STALE_CONFIG) {
799 link->state |= DEV_STALE_LINK;
800 return;
801 }
802 }
803
804 /* Tell Card Services we're not around any more */
805 if (link->handle) {
806 pcmcia_deregister_client(link->handle);
807 }
808
809 /* Unlink device structure, free bits */
810 *linkp = link->next;
811 if ( link->priv != NULL ) {
812 wlandev = (wlandevice_t*)link->priv;
813 p80211netdev_hwremoved(wlandev);
814 if (link->dev != NULL) {
815 unregister_wlandev(wlandev);
816 }
817 wlan_unsetup(wlandev);
818 if (wlandev->priv) {
819 hw = wlandev->priv;
820 wlandev->priv = NULL;
821 if (hw) {
822 hfa384x_destroy(hw);
823 kfree(hw);
824 }
825 }
826 link->priv = NULL;
827 kfree(wlandev);
828 }
829 kfree(link);
830 }
831
832 DBFEXIT;
833 return;
834 }
835
836 /*----------------------------------------------------------------
837 * prism2sta_config
838 *
839 * Half of the config/release pair. Usually called in response to
840 * a card insertion event. At this point, we _know_ there's some
841 * physical device present. That means we can start poking around
842 * at the CIS and at any device specific config data we want.
843 *
844 * Note the gotos and the macros. I recoded this once without
845 * them, and it got incredibly ugly. It's actually simpler with
846 * them.
847 *
848 * Arguments:
849 * link the dev_link_t structure created in attach that
850 * represents this device instance.
851 *
852 * Returns:
853 * nothing
854 *
855 * Side effects:
856 * Resources (irq, io, mem) are allocated
857 * The pcmcia dev_link->node->name is set
858 * (For netcards) The device structure is finished and,
859 * most importantly, registered. This means that there
860 * is now a _named_ device that can be configured from
861 * userland.
862 *
863 * Call context:
864 * May be called from a timer. Don't block!
865 ----------------------------------------------------------------*/
866 #define CS_CHECK(fn, ret) \
867 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
868
869 #define CFG_CHECK(fn, retf) \
870 do { int ret = (retf); \
871 if (ret != 0) { \
872 WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
873 cs_error(link->handle, fn, ret); \
874 goto next_entry; \
875 } \
876 } while (0)
877
878 void prism2sta_config(dev_link_t *link)
879 {
880 client_handle_t handle;
881 wlandevice_t *wlandev;
882 hfa384x_t *hw;
883 int last_fn;
884 int last_ret;
885 tuple_t tuple;
886 cisparse_t parse;
887 config_info_t socketconf;
888 UINT8 buf[64];
889 int minVcc = 0;
890 int maxVcc = 0;
891 cistpl_cftable_entry_t dflt = { 0 };
892
893 DBFENTER;
894
895 handle = link->handle;
896 wlandev = (wlandevice_t*)link->priv;
897 hw = wlandev->priv;
898
899 /* Collect the config register info */
900 tuple.DesiredTuple = CISTPL_CONFIG;
901 tuple.Attributes = 0;
902 tuple.TupleData = buf;
903 tuple.TupleDataMax = sizeof(buf);
904 tuple.TupleOffset = 0;
905 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
906 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
907 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
908
909 link->conf.ConfigBase = parse.config.base;
910 link->conf.Present = parse.config.rmask[0];
911
912 /* Configure card */
913 link->state |= DEV_CONFIG;
914
915 /* Acquire the current socket config (need Vcc setting) */
916 CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &socketconf));
917
918 /* Loop through the config table entries until we find one that works */
919 /* Assumes a complete and valid CIS */
920 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
921 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
922 while (1) {
923 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
924 CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
925 CFG_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
926
927 if (cfg->index == 0) goto next_entry;
928 link->conf.ConfigIndex = cfg->index;
929
930 /* Lets print out the Vcc that the controller+pcmcia-cs set
931 * for us, cause that's what we're going to use.
932 */
933 WLAN_LOG_DEBUG(1,"Initial Vcc=%d/10v\n", socketconf.Vcc);
934 if (prism2_ignorevcc) {
935 link->conf.Vcc = socketconf.Vcc;
936 goto skipvcc;
937 }
938
939 /* Use power settings for Vcc and Vpp if present */
940 /* Note that the CIS values need to be rescaled */
941 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
942 WLAN_LOG_DEBUG(1, "Vcc obtained from curtupl.VNOM\n");
943 minVcc = maxVcc =
944 cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
945 } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
946 WLAN_LOG_DEBUG(1, "Vcc set from dflt.VNOM\n");
947 minVcc = maxVcc =
948 dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
949 } else if ((cfg->vcc.present & (1<<CISTPL_POWER_VMAX)) &&
950 (cfg->vcc.present & (1<<CISTPL_POWER_VMIN)) ) {
951 WLAN_LOG_DEBUG(1, "Vcc set from curtupl(VMIN,VMAX)\n"); minVcc = cfg->vcc.param[CISTPL_POWER_VMIN]/10000;
952 maxVcc = cfg->vcc.param[CISTPL_POWER_VMAX]/10000;
953 } else if ((dflt.vcc.present & (1<<CISTPL_POWER_VMAX)) &&
954 (dflt.vcc.present & (1<<CISTPL_POWER_VMIN)) ) {
955 WLAN_LOG_DEBUG(1, "Vcc set from dflt(VMIN,VMAX)\n");
956 minVcc = dflt.vcc.param[CISTPL_POWER_VMIN]/10000;
957 maxVcc = dflt.vcc.param[CISTPL_POWER_VMAX]/10000;
958 }
959
960 if ( socketconf.Vcc >= minVcc && socketconf.Vcc <= maxVcc) {
961 link->conf.Vcc = socketconf.Vcc;
962 } else {
963 /* [MSM]: Note that I've given up trying to change
964 * the Vcc if a change is indicated. It seems the
965 * system&socketcontroller&card vendors can't seem
966 * to get it right, so I'm tired of trying to hack
967 * my way around it. pcmcia-cs does its best using
968 * the voltage sense pins but sometimes the controller
969 * lies. Then, even if we have a good read on the VS
970 * pins, some system designs will silently ignore our
971 * requests to set the voltage. Additionally, some
972 * vendors have 3.3v indicated on their sense pins,
973 * but 5v specified in the CIS or vice-versa. I've
974 * had it. My only recommendation is "let the buyer
975 * beware". Your system might supply 5v to a 3v card
976 * (possibly causing damage) or a 3v capable system
977 * might supply 5v to a 3v capable card (wasting
978 * precious battery life).
979 * My only recommendation (if you care) is to get
980 * yourself an extender card (I don't know where, I
981 * have only one myself) and a meter and test it for
982 * yourself.
983 */
984 goto next_entry;
985 }
986 skipvcc:
987 WLAN_LOG_DEBUG(1, "link->conf.Vcc=%d\n", link->conf.Vcc);
988
989 /* Do we need to allocate an interrupt? */
990 /* HACK: due to a bad CIS....we ALWAYS need an interrupt */
991 /* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */
992 link->conf.Attributes |= CONF_ENABLE_IRQ;
993
994 /* IO window settings */
995 link->io.NumPorts1 = link->io.NumPorts2 = 0;
996 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
997 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
998 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
999 if (!(io->flags & CISTPL_IO_8BIT))
1000 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
1001 if (!(io->flags & CISTPL_IO_16BIT))
1002 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
1003 link->io.BasePort1 = io->win[0].base;
1004 if ( link->io.BasePort1 != 0 ) {
1005 WLAN_LOG_WARNING(
1006 "Brain damaged CIS: hard coded iobase="
1007 "0x%x, try letting pcmcia_cs decide...\n",
1008 link->io.BasePort1 );
1009 link->io.BasePort1 = 0;
1010 }
1011 link->io.NumPorts1 = io->win[0].len;
1012 if (io->nwin > 1) {
1013 link->io.Attributes2 = link->io.Attributes1;
1014 link->io.BasePort2 = io->win[1].base;
1015 link->io.NumPorts2 = io->win[1].len;
1016 }
1017 }
1018
1019 /* This reserves IO space but doesn't actually enable it */
1020 CFG_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
1021
1022 /* If we got this far, we're cool! */
1023 break;
1024
1025 next_entry:
1026 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
1027 dflt = *cfg;
1028 CS_CHECK(GetNextTuple,
1029 pcmcia_get_next_tuple(handle, &tuple));
1030 }
1031
1032 /* Allocate an interrupt line. Note that this does not assign a */
1033 /* handler to the interrupt, unless the 'Handler' member of the */
1034 /* irq structure is initialized. */
1035 if (link->conf.Attributes & CONF_ENABLE_IRQ)
1036 {
1037 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
1038 int i;
1039 link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
1040 if (irq_list[0] == -1)
1041 link->irq.IRQInfo2 = irq_mask;
1042 else
1043 for (i=0; i<4; i++)
1044 link->irq.IRQInfo2 |= 1 << irq_list[i];
1045 #else
1046 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
1047 #endif
1048 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
1049 link->irq.Handler = hfa384x_interrupt;
1050 link->irq.Instance = wlandev;
1051 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
1052 }
1053
1054 /* This actually configures the PCMCIA socket -- setting up */
1055 /* the I/O windows and the interrupt mapping, and putting the */
1056 /* card and host interface into "Memory and IO" mode. */
1057 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
1058
1059 /* Fill the netdevice with this info */
1060 wlandev->netdev->irq = link->irq.AssignedIRQ;
1061 wlandev->netdev->base_addr = link->io.BasePort1;
1062
1063 /* Report what we've done */
1064 WLAN_LOG_INFO("%s: index 0x%02x: Vcc %d.%d",
1065 dev_info, link->conf.ConfigIndex,
1066 link->conf.Vcc/10, link->conf.Vcc%10);
1067 if (link->conf.Vpp1)
1068 printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
1069 if (link->conf.Attributes & CONF_ENABLE_IRQ)
1070 printk(", irq %d", link->irq.AssignedIRQ);
1071 if (link->io.NumPorts1)
1072 printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1);
1073 if (link->io.NumPorts2)
1074 printk(" & 0x%04x-0x%04x", link->io.BasePort2, link->io.BasePort2+link->io.NumPorts2-1);
1075 printk("\n");
1076
1077 link->state &= ~DEV_CONFIG_PENDING;
1078
1079 /* Let pcmcia know the device name */
1080 link->dev = &hw->node;
1081
1082 /* Register the network device and get assigned a name */
1083 SET_MODULE_OWNER(wlandev->netdev);
1084 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) )
1085 SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(link->handle));
1086 #endif
1087 if (register_wlandev(wlandev) != 0) {
1088 WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n");
1089 goto failed;
1090 }
1091
1092 strcpy(hw->node.dev_name, wlandev->name);
1093
1094 /* Any device custom config/query stuff should be done here */
1095 /* For a netdevice, we should at least grab the mac address */
1096
1097 return;
1098 cs_failed:
1099 cs_error(link->handle, last_fn, last_ret);
1100 WLAN_LOG_ERROR("NextTuple failure? It's probably a Vcc mismatch.\n");
1101
1102 failed:
1103 prism2sta_release((u_long)link);
1104 return;
1105 }
1106
1107 /*----------------------------------------------------------------
1108 * prism2sta_release
1109 *
1110 * Half of the config/release pair. Usually called in response to
1111 * a card ejection event. Checks to make sure no higher layers
1112 * are still (or think they are) using the card via the link->open
1113 * field.
1114 *
1115 * NOTE: Don't forget to increment the link->open variable in the
1116 * device_open method, and decrement it in the device_close
1117 * method.
1118 *
1119 * Arguments:
1120 * arg a generic 32 bit variable. It's the value that
1121 * we assigned to link->release.data in sta_attach().
1122 *
1123 * Returns:
1124 * nothing
1125 *
1126 * Side effects:
1127 * All resources should be released after this function
1128 * executes and finds the device !open.
1129 *
1130 * Call context:
1131 * Possibly in a timer context. Don't do anything that'll
1132 * block.
1133 ----------------------------------------------------------------*/
1134 void prism2sta_release(u_long arg)
1135 {
1136 dev_link_t *link = (dev_link_t *)arg;
1137
1138 DBFENTER;
1139
1140 /* First thing we should do is get the MSD back to the
1141 * HWPRESENT state. I.e. everything quiescent.
1142 */
1143 prism2sta_ifstate(link->priv, P80211ENUM_ifstate_disable);
1144
1145 if (link->open) {
1146 /* TODO: I don't think we're even using this bit of code
1147 * and I don't think it's hurting us at the moment.
1148 */
1149 WLAN_LOG_DEBUG(1,
1150 "prism2sta_cs: release postponed, '%s' still open\n",
1151 link->dev->dev_name);
1152 link->state |= DEV_STALE_CONFIG;
1153 return;
1154 }
1155
1156 pcmcia_release_configuration(link->handle);
1157 pcmcia_release_io(link->handle, &link->io);
1158 pcmcia_release_irq(link->handle, &link->irq);
1159
1160 link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
1161
1162 DBFEXIT;
1163 }
1164
1165 /*----------------------------------------------------------------
1166 * prism2sta_event
1167 *
1168 * Handler for card services events.
1169 *
1170 * Arguments:
1171 * event The event code
1172 * priority hi/low - REMOVAL is the only hi
1173 * args ptr to card services struct containing info about
1174 * pcmcia status
1175 *
1176 * Returns:
1177 * Zero on success, non-zero otherwise
1178 *
1179 * Side effects:
1180 *
1181 *
1182 * Call context:
1183 * Both interrupt and process thread, depends on the event.
1184 ----------------------------------------------------------------*/
1185 static int
1186 prism2sta_event (
1187 event_t event,
1188 int priority,
1189 event_callback_args_t *args)
1190 {
1191 int result = 0;
1192 dev_link_t *link = (dev_link_t *) args->client_data;
1193 wlandevice_t *wlandev = (wlandevice_t*)link->priv;
1194 hfa384x_t *hw = NULL;
1195
1196 DBFENTER;
1197
1198 if (wlandev) hw = wlandev->priv;
1199
1200 switch (event)
1201 {
1202 case CS_EVENT_CARD_INSERTION:
1203 WLAN_LOG_DEBUG(5,"event is INSERTION\n");
1204 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
1205 prism2sta_config(link);
1206 if (!(link->state & DEV_CONFIG)) {
1207 wlandev->netdev->irq = 0;
1208 WLAN_LOG_ERROR(
1209 "%s: Initialization failed!\n", dev_info);
1210 wlandev->msdstate = WLAN_MSD_HWFAIL;
1211 break;
1212 }
1213
1214 /* Fill in the rest of the hw struct */
1215 hw->irq = wlandev->netdev->irq;
1216 hw->iobase = wlandev->netdev->base_addr;
1217 hw->link = link;
1218
1219 if (prism2_doreset) {
1220 result = hfa384x_corereset(hw,
1221 prism2_reset_holdtime,
1222 prism2_reset_settletime, 0);
1223 if ( result ) {
1224 WLAN_LOG_ERROR(
1225 "corereset() failed, result=%d.\n",
1226 result);
1227 wlandev->msdstate = WLAN_MSD_HWFAIL;
1228 break;
1229 }
1230 }
1231
1232 #if 0
1233 /*
1234 * TODO: test_hostif() not implemented yet.
1235 */
1236 result = hfa384x_test_hostif(hw);
1237 if (result) {
1238 WLAN_LOG_ERROR(
1239 "test_hostif() failed, result=%d.\n", result);
1240 wlandev->msdstate = WLAN_MSD_HWFAIL;
1241 break;
1242 }
1243 #endif
1244 wlandev->msdstate = WLAN_MSD_HWPRESENT;
1245 break;
1246
1247 case CS_EVENT_CARD_REMOVAL:
1248 WLAN_LOG_DEBUG(5,"event is REMOVAL\n");
1249 link->state &= ~DEV_PRESENT;
1250
1251 if (wlandev) {
1252 p80211netdev_hwremoved(wlandev);
1253 }
1254
1255 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
1256 if (link->state & DEV_CONFIG)
1257 {
1258 link->release.expires = jiffies + (HZ/20);
1259 add_timer(&link->release);
1260 }
1261 #endif
1262 break;
1263 case CS_EVENT_RESET_REQUEST:
1264 WLAN_LOG_DEBUG(5,"event is RESET_REQUEST\n");
1265 WLAN_LOG_NOTICE(
1266 "prism2 card reset not supported "
1267 "due to post-reset user mode configuration "
1268 "requirements.\n");
1269 WLAN_LOG_NOTICE(
1270 " From user mode, use "
1271 "'cardctl suspend;cardctl resume' "
1272 "instead.\n");
1273 break;
1274 case CS_EVENT_RESET_PHYSICAL:
1275 case CS_EVENT_CARD_RESET:
1276 WLAN_LOG_WARNING("Rx'd CS_EVENT_RESET_xxx, should not "
1277 "be possible since RESET_REQUEST was denied.\n");
1278 break;
1279
1280 case CS_EVENT_PM_SUSPEND:
1281 WLAN_LOG_DEBUG(5,"event is SUSPEND\n");
1282 link->state |= DEV_SUSPEND;
1283 if (link->state & DEV_CONFIG)
1284 {
1285 prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
1286 pcmcia_release_configuration(link->handle);
1287 }
1288 break;
1289
1290 case CS_EVENT_PM_RESUME:
1291 WLAN_LOG_DEBUG(5,"event is RESUME\n");
1292 link->state &= ~DEV_SUSPEND;
1293 if (link->state & DEV_CONFIG) {
1294 pcmcia_request_configuration(link->handle, &link->conf);
1295 }
1296 break;
1297 }
1298
1299 DBFEXIT;
1300 return 0; /* noone else does anthing with the return value */
1301 }
1302 #endif // <= 2.6.15
1303
1304
1305
1306 int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis)
1307 {
1308 int result = 0;
1309 conf_reg_t reg;
1310 UINT8 corsave;
1311 DBFENTER;
1312
1313 WLAN_LOG_DEBUG(3, "Doing reset via CardServices().\n");
1314
1315 /* Collect COR */
1316 reg.Function = 0;
1317 reg.Action = CS_READ;
1318 reg.Offset = CISREG_COR;
1319 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
1320 result = pcmcia_access_configuration_register(hw->pdev, &reg);
1321 #else
1322 result = pcmcia_access_configuration_register(
1323 hw->link->handle,
1324 &reg);
1325 #endif
1326 if (result != CS_SUCCESS ) {
1327 WLAN_LOG_ERROR(
1328 ":0: AccessConfigurationRegister(CS_READ) failed,"
1329 "result=%d.\n", result);
1330 result = -EIO;
1331 }
1332 corsave = reg.Value;
1333
1334 /* Write reset bit (BIT7) */
1335 reg.Value |= BIT7;
1336 reg.Action = CS_WRITE;
1337 reg.Offset = CISREG_COR;
1338 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
1339 result = pcmcia_access_configuration_register(hw->pdev, &reg);
1340 #else
1341 result = pcmcia_access_configuration_register(
1342 hw->link->handle,
1343 &reg);
1344 #endif
1345 if (result != CS_SUCCESS ) {
1346 WLAN_LOG_ERROR(
1347 ":1: AccessConfigurationRegister(CS_WRITE) failed,"
1348 "result=%d.\n", result);
1349 result = -EIO;
1350 }
1351
1352 /* Hold for holdtime */
1353 mdelay(holdtime);
1354
1355 if (genesis) {
1356 reg.Value = genesis;
1357 reg.Action = CS_WRITE;
1358 reg.Offset = CISREG_CCSR;
1359 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
1360 result = pcmcia_access_configuration_register(hw->pdev, &reg);
1361 #else
1362 result = pcmcia_access_configuration_register(
1363 hw->link->handle,
1364 &reg);
1365 #endif
1366 if (result != CS_SUCCESS ) {
1367 WLAN_LOG_ERROR(
1368 ":1: AccessConfigurationRegister(CS_WRITE) failed,"
1369 "result=%d.\n", result);
1370 result = -EIO;
1371 }
1372 }
1373
1374 /* Hold for holdtime */
1375 mdelay(holdtime);
1376
1377 /* Clear reset bit */
1378 reg.Value &= ~BIT7;
1379 reg.Action = CS_WRITE;
1380 reg.Offset = CISREG_COR;
1381 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
1382 result = pcmcia_access_configuration_register(hw->pdev, &reg);
1383 #else
1384 result = pcmcia_access_configuration_register(
1385 hw->link->handle,
1386 &reg);
1387 #endif
1388 if (result != CS_SUCCESS ) {
1389 WLAN_LOG_ERROR(
1390 ":2: AccessConfigurationRegister(CS_WRITE) failed,"
1391 "result=%d.\n", result);
1392 result = -EIO;
1393 goto done;
1394 }
1395
1396 /* Wait for settletime */
1397 mdelay(settletime);
1398
1399 /* Set non-reset bits back what they were */
1400 reg.Value = corsave;
1401 reg.Action = CS_WRITE;
1402 reg.Offset = CISREG_COR;
1403 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
1404 result = pcmcia_access_configuration_register(hw->pdev, &reg);
1405 #else
1406 result = pcmcia_access_configuration_register(
1407 hw->link->handle,
1408 &reg);
1409 #endif
1410 if (result != CS_SUCCESS ) {
1411 WLAN_LOG_ERROR(
1412 ":2: AccessConfigurationRegister(CS_WRITE) failed,"
1413 "result=%d.\n", result);
1414 result = -EIO;
1415 goto done;
1416 }
1417
1418 done:
1419 DBFEXIT;
1420 return result;
1421 }
1422
1423 #ifdef MODULE
1424
1425 static int __init prism2cs_init(void)
1426 {
1427 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
1428 servinfo_t serv;
1429 #endif
1430
1431 DBFENTER;
1432
1433 WLAN_LOG_NOTICE("%s Loaded\n", version);
1434 WLAN_LOG_NOTICE("dev_info is: %s\n", dev_info);
1435
1436 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
1437 pcmcia_get_card_services_info(&serv);
1438 if ( serv.Revision != CS_RELEASE_CODE )
1439 {
1440 printk(KERN_NOTICE"%s: CardServices release does not match!\n", dev_info);
1441 return -1;
1442 }
1443
1444 /* This call will result in a call to prism2sta_attach */
1445 /* and eventually prism2sta_detach */
1446 register_pccard_driver( &dev_info, &prism2sta_attach, &prism2sta_detach);
1447 #else
1448 pcmcia_register_driver(&prism2_cs_driver);
1449 #endif
1450
1451 DBFEXIT;
1452 return 0;
1453 }
1454
1455 static void __exit prism2cs_cleanup(void)
1456 {
1457 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
1458 dev_link_t *link = dev_list;
1459 dev_link_t *nlink;
1460 DBFENTER;
1461
1462 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) )
1463 for (link=dev_list; link != NULL; link = nlink) {
1464 nlink = link->next;
1465 if ( link->state & DEV_CONFIG ) {
1466 prism2sta_release((u_long)link);
1467 }
1468 prism2sta_detach(link); /* remember detach() frees link */
1469 }
1470 #endif
1471
1472 unregister_pccard_driver( &dev_info);
1473 #else
1474 pcmcia_unregister_driver(&prism2_cs_driver);
1475 #endif
1476
1477 printk(KERN_NOTICE "%s Unloaded\n", version);
1478
1479 DBFEXIT;
1480 return;
1481 }
1482
1483 module_init(prism2cs_init);
1484 module_exit(prism2cs_cleanup);
1485
1486 #endif // MODULE
1487