1 #define WLAN_HOSTIF WLAN_PCMCIA
3 #include "prism2mgmt.c"
7 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21) )
8 #if (WLAN_CPU_FAMILY == WLAN_Ix86)
10 #warning "You may need to enable ISA support in your kernel."
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 */
19 static u_int prism2_ignorevcc
=1; /* Boolean, if set, we
21 * is set to and what the CIS
24 module_param( prism2_ignorevcc
, int, 0644);
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);
31 module_param_array(irq_list
, int, NULL
, 0444);
33 module_param( irq_mask
, int, 0644);
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
);
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
);
48 static dev_link_t
*dev_list
= NULL
; /* head of instance list */
51 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
52 /*----------------------------------------------------------------
55 * Utility function to print card services error messages.
58 * handle client handle identifying this CS client
59 * func CS function number that generated the error
60 * ret CS function return code
69 ----------------------------------------------------------------*/
70 static void cs_error(client_handle_t handle
, int func
, int ret
)
72 #if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911))
73 CardServices(ReportError
, dev_info
, (void *)func
, (void *)ret
);
75 error_info_t err
= { func
, ret
};
76 pcmcia_report_error(handle
, &err
);
79 #else // kernel_version
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
138 MODULE_DEVICE_TABLE(pcmcia
, prism2_cs_ids
);
141 static struct pcmcia_driver prism2_cs_driver
= {
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
,
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
,
161 #endif /* kernel_version */
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)
167 #define CFG_CHECK(fn, retf) \
168 do { int ret = (retf); \
170 WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
171 cs_error(pdev, fn, ret); \
176 static void prism2_cs_remove(struct pcmcia_device
*pdev
)
178 struct wlandevice
*wlandev
;
180 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
181 dev_link_t
*link
= dev_to_instance(pdev
);
186 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
187 wlandev
= pdev
->priv
;
189 wlandev
= link
->priv
;
193 p80211netdev_hwremoved(wlandev
);
194 unregister_wlandev(wlandev
);
195 wlan_unsetup(wlandev
);
197 hfa384x_t
*hw
= wlandev
->priv
;
198 wlandev
->priv
= NULL
;
207 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
209 pcmcia_disable_device(pdev
);
211 if (link
->state
& DEV_CONFIG
) {
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
);
220 link
->state
&= ~DEV_CONFIG
;
231 static int prism2_cs_suspend(struct pcmcia_device
*pdev
)
233 struct wlandevice
*wlandev
;
235 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
236 dev_link_t
*link
= dev_to_instance(pdev
);
241 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
242 wlandev
= pdev
->priv
;
243 prism2sta_ifstate(wlandev
, P80211ENUM_ifstate_disable
);
245 wlandev
= link
->priv
;
247 link
->state
|= DEV_SUSPEND
;
248 if (link
->state
& DEV_CONFIG
) {
249 prism2sta_ifstate(wlandev
, P80211ENUM_ifstate_disable
);
250 pcmcia_release_configuration(link
->handle
);
259 static int prism2_cs_resume(struct pcmcia_device
*pdev
)
261 struct wlandevice
*wlandev
;
263 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
264 dev_link_t
*link
= dev_to_instance(pdev
);
269 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
270 wlandev
= pdev
->priv
;
271 // XXX do something here?
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?
287 static int prism2_cs_probe(struct pcmcia_device
*pdev
)
290 struct wlandevice
*wlandev
= NULL
;
291 hfa384x_t
*hw
= NULL
;
293 config_info_t socketconf
;
294 cisparse_t
*parse
= NULL
;
297 int last_fn
, last_ret
;
298 cistpl_cftable_entry_t dflt
= { 0 };
300 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
306 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
307 /* Set up interrupt type */
308 pdev
->conf
.IntType
= INT_MEMORY_AND_IO
;
310 link
= kmalloc(sizeof(dev_link_t
), GFP_KERNEL
);
313 memset(link
, 0, sizeof(dev_link_t
));
316 link
->conf
.IntType
= INT_MEMORY_AND_IO
;
319 pdev
->instance
= link
;
320 link
->state
|= DEV_PRESENT
| DEV_CONFIG_PENDING
;
325 parse
= kmalloc(sizeof(cisparse_t
), GFP_KERNEL
);
327 wlandev
= create_wlan();
328 if (!wlandev
|| !parse
) {
329 WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info
);
335 if ( wlan_setup(wlandev
) != 0 ) {
336 WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info
);
341 /* Initialize the hw struct for now */
342 hfa384x_create(hw
, 0, 0, NULL
);
343 hw
->wlandev
= wlandev
;
345 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
347 pdev
->priv
= wlandev
;
350 link
->priv
= wlandev
;
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];
365 link
->conf
.ConfigBase
= parse
->config
.base
;
366 link
->conf
.Present
= parse
->config
.rmask
[0];
368 link
->conf
.Vcc
= socketconf
.Vcc
;
370 CS_CHECK(GetConfigurationInfo
,
371 pcmcia_get_configuration_info(pdev
, &socketconf
));
373 tuple
.DesiredTuple
= CISTPL_CFTABLE_ENTRY
;
374 CS_CHECK(GetFirstTuple
, pcmcia_get_first_tuple(pdev
, &tuple
));
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
));
382 if (cfg
->flags
& CISTPL_CFTABLE_DEFAULT
)
386 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
387 pdev
->conf
.ConfigIndex
= cfg
->index
;
389 link
->conf
.ConfigIndex
= cfg
->index
;
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
;
398 link
->conf
.Attributes
|= CONF_ENABLE_SPKR
;
399 link
->conf
.Status
= CCSR_AUDIO_ENA
;
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"
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");
421 if (cfg
->vpp1
.present
& (1 << CISTPL_POWER_VNOM
)) {
422 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
424 cfg
->vpp1
.param
[CISTPL_POWER_VNOM
] / 10000;
426 link
->conf
.Vpp1
= link
->conf
.Vpp2
=
427 cfg
->vpp1
.param
[CISTPL_POWER_VNOM
] / 10000;
429 } else if (dflt
.vpp1
.present
& (1 << CISTPL_POWER_VNOM
)) {
430 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
432 dflt
.vpp1
.param
[CISTPL_POWER_VNOM
] / 10000;
434 link
->conf
.Vpp1
= link
->conf
.Vpp2
=
435 dflt
.vpp1
.param
[CISTPL_POWER_VNOM
] / 10000;
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
;
445 link
->conf
.Attributes
|= CONF_ENABLE_IRQ
;
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 ) {
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;
466 pdev
->io
.NumPorts1
= io
->win
[0].len
;
468 pdev
->io
.Attributes2
= pdev
->io
.Attributes1
;
469 pdev
->io
.BasePort2
= io
->win
[1].base
;
470 pdev
->io
.NumPorts2
= io
->win
[1].len
;
473 /* This reserves IO space but doesn't actually enable it */
474 CFG_CHECK(RequestIO
, pcmcia_request_io(pdev
, &pdev
->io
));
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 ) {
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;
492 link
->io
.NumPorts1
= io
->win
[0].len
;
494 link
->io
.Attributes2
= link
->io
.Attributes1
;
495 link
->io
.BasePort2
= io
->win
[1].base
;
496 link
->io
.NumPorts2
= io
->win
[1].len
;
499 /* This reserves IO space but doesn't actually enable it */
500 CFG_CHECK(RequestIO
, pcmcia_request_io(pdev
, &link
->io
));
502 /* If we got this far, we're cool! */
506 if (cfg
->flags
& CISTPL_CFTABLE_DEFAULT
)
508 CS_CHECK(GetNextTuple
, pcmcia_get_next_tuple(pdev
, &tuple
));
512 /* Let pcmcia know the device name */
513 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
514 pdev
->dev_node
= &hw
->node
;
516 link
->dev
= &hw
->node
;
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");
527 strcpy(hw
->node
.dev_name
, wlandev
->name
);
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
));
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
));
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
));
556 CS_CHECK(RequestConfiguration
, pcmcia_request_configuration(pdev
, &link
->conf
));
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
;
564 wlandev
->netdev
->irq
= link
->irq
.AssignedIRQ
;
565 wlandev
->netdev
->base_addr
= link
->io
.BasePort1
;
568 /* And the rest of the hw structure */
569 hw
->irq
= wlandev
->netdev
->irq
;
570 hw
->iobase
= wlandev
->netdev
->base_addr
;
572 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
573 link
->state
|= DEV_CONFIG
;
574 link
->state
&= ~DEV_CONFIG_PENDING
;
577 /* And now we're done! */
578 wlandev
->msdstate
= WLAN_MSD_HWPRESENT
;
583 cs_error(pdev
, last_fn
, last_ret
);
586 // wlandev, hw, etc etc..
587 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
590 pdev
->instance
= NULL
;
597 wlan_unsetup(wlandev
);
600 wlandev
->priv
= NULL
;
610 if (parse
) kfree(parse
);
616 #define CS_CHECK(fn, ret) \
617 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
619 #define CFG_CHECK(fn, retf) \
620 do { int ret = (retf); \
622 WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
623 cs_error(link->handle, fn, ret); \
628 /*----------------------------------------------------------------
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.
640 * A valid ptr to dev_link_t on success, NULL otherwise
646 * process thread (insmod/init_module/register_pccard_driver)
647 ----------------------------------------------------------------*/
648 dev_link_t
*prism2sta_attach(void)
650 client_reg_t client_reg
;
652 dev_link_t
*link
= NULL
;
653 wlandevice_t
*wlandev
= NULL
;
654 hfa384x_t
*hw
= NULL
;
658 /* Alloc our structures */
659 link
= kmalloc(sizeof(struct dev_link_t
), GFP_KERNEL
);
661 if (!link
|| ((wlandev
= create_wlan()) == NULL
)) {
662 WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info
);
668 /* Clear all the structs */
669 memset(link
, 0, sizeof(struct dev_link_t
));
671 if ( wlan_setup(wlandev
) != 0 ) {
672 WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info
);
677 /* Initialize the hw struct for now */
678 hfa384x_create(hw
, 0, 0, NULL
);
679 hw
->wlandev
= wlandev
;
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
;
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
;
693 /* Link in to the list of devices managed by this driver */
694 link
->next
= dev_list
;
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
;
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
;
712 client_reg
.Version
= 0x0210;
713 client_reg
.event_callback_args
.client_data
= link
;
715 result
= pcmcia_register_client(&link
->handle
, &client_reg
);
717 cs_error(link
->handle
, RegisterClient
, result
);
718 prism2sta_detach(link
);
725 if (link
) kfree(link
);
726 if (wlandev
) kfree(wlandev
);
736 /*----------------------------------------------------------------
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
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
752 * link ptr to the instance to detach
758 * the link structure is gone, the netdevice is gone
761 * Might be interrupt, don't block.
762 ----------------------------------------------------------------*/
763 void prism2sta_detach(dev_link_t
*link
)
766 wlandevice_t
*wlandev
;
771 /* Locate prev device structure */
772 for (linkp
= &dev_list
; *linkp
; linkp
= &(*linkp
)->next
) {
773 if (*linkp
== link
) break;
776 if (*linkp
!= NULL
) {
777 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
779 /* Get rid of any timer'd release call */
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
;
791 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
792 restore_flags(flags
);
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
;
804 /* Tell Card Services we're not around any more */
806 pcmcia_deregister_client(link
->handle
);
809 /* Unlink device structure, free bits */
811 if ( link
->priv
!= NULL
) {
812 wlandev
= (wlandevice_t
*)link
->priv
;
813 p80211netdev_hwremoved(wlandev
);
814 if (link
->dev
!= NULL
) {
815 unregister_wlandev(wlandev
);
817 wlan_unsetup(wlandev
);
820 wlandev
->priv
= NULL
;
836 /*----------------------------------------------------------------
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.
844 * Note the gotos and the macros. I recoded this once without
845 * them, and it got incredibly ugly. It's actually simpler with
849 * link the dev_link_t structure created in attach that
850 * represents this device instance.
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
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)
869 #define CFG_CHECK(fn, retf) \
870 do { int ret = (retf); \
872 WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
873 cs_error(link->handle, fn, ret); \
878 void prism2sta_config(dev_link_t
*link
)
880 client_handle_t handle
;
881 wlandevice_t
*wlandev
;
887 config_info_t socketconf
;
891 cistpl_cftable_entry_t dflt
= { 0 };
895 handle
= link
->handle
;
896 wlandev
= (wlandevice_t
*)link
->priv
;
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
));
909 link
->conf
.ConfigBase
= parse
.config
.base
;
910 link
->conf
.Present
= parse
.config
.rmask
[0];
913 link
->state
|= DEV_CONFIG
;
915 /* Acquire the current socket config (need Vcc setting) */
916 CS_CHECK(GetConfigurationInfo
, pcmcia_get_configuration_info(handle
, &socketconf
));
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
));
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
));
927 if (cfg
->index
== 0) goto next_entry
;
928 link
->conf
.ConfigIndex
= cfg
->index
;
930 /* Lets print out the Vcc that the controller+pcmcia-cs set
931 * for us, cause that's what we're going to use.
933 WLAN_LOG_DEBUG(1,"Initial Vcc=%d/10v\n", socketconf
.Vcc
);
934 if (prism2_ignorevcc
) {
935 link
->conf
.Vcc
= socketconf
.Vcc
;
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");
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");
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;
960 if ( socketconf
.Vcc
>= minVcc
&& socketconf
.Vcc
<= maxVcc
) {
961 link
->conf
.Vcc
= socketconf
.Vcc
;
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
987 WLAN_LOG_DEBUG(1, "link->conf.Vcc=%d\n", link
->conf
.Vcc
);
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
;
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 ) {
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;
1011 link
->io
.NumPorts1
= io
->win
[0].len
;
1013 link
->io
.Attributes2
= link
->io
.Attributes1
;
1014 link
->io
.BasePort2
= io
->win
[1].base
;
1015 link
->io
.NumPorts2
= io
->win
[1].len
;
1019 /* This reserves IO space but doesn't actually enable it */
1020 CFG_CHECK(RequestIO
, pcmcia_request_io(link
->handle
, &link
->io
));
1022 /* If we got this far, we're cool! */
1026 if (cfg
->flags
& CISTPL_CFTABLE_DEFAULT
)
1028 CS_CHECK(GetNextTuple
,
1029 pcmcia_get_next_tuple(handle
, &tuple
));
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
)
1037 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
1039 link
->irq
.IRQInfo1
= IRQ_INFO2_VALID
| IRQ_LEVEL_ID
;
1040 if (irq_list
[0] == -1)
1041 link
->irq
.IRQInfo2
= irq_mask
;
1044 link
->irq
.IRQInfo2
|= 1 << irq_list
[i
];
1046 link
->irq
.IRQInfo1
= IRQ_LEVEL_ID
;
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
));
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
));
1059 /* Fill the netdevice with this info */
1060 wlandev
->netdev
->irq
= link
->irq
.AssignedIRQ
;
1061 wlandev
->netdev
->base_addr
= link
->io
.BasePort1
;
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);
1077 link
->state
&= ~DEV_CONFIG_PENDING
;
1079 /* Let pcmcia know the device name */
1080 link
->dev
= &hw
->node
;
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
));
1087 if (register_wlandev(wlandev
) != 0) {
1088 WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n");
1092 strcpy(hw
->node
.dev_name
, wlandev
->name
);
1094 /* Any device custom config/query stuff should be done here */
1095 /* For a netdevice, we should at least grab the mac address */
1099 cs_error(link
->handle
, last_fn
, last_ret
);
1100 WLAN_LOG_ERROR("NextTuple failure? It's probably a Vcc mismatch.\n");
1103 prism2sta_release((u_long
)link
);
1107 /*----------------------------------------------------------------
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
1115 * NOTE: Don't forget to increment the link->open variable in the
1116 * device_open method, and decrement it in the device_close
1120 * arg a generic 32 bit variable. It's the value that
1121 * we assigned to link->release.data in sta_attach().
1127 * All resources should be released after this function
1128 * executes and finds the device !open.
1131 * Possibly in a timer context. Don't do anything that'll
1133 ----------------------------------------------------------------*/
1134 void prism2sta_release(u_long arg
)
1136 dev_link_t
*link
= (dev_link_t
*)arg
;
1140 /* First thing we should do is get the MSD back to the
1141 * HWPRESENT state. I.e. everything quiescent.
1143 prism2sta_ifstate(link
->priv
, P80211ENUM_ifstate_disable
);
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.
1150 "prism2sta_cs: release postponed, '%s' still open\n",
1151 link
->dev
->dev_name
);
1152 link
->state
|= DEV_STALE_CONFIG
;
1156 pcmcia_release_configuration(link
->handle
);
1157 pcmcia_release_io(link
->handle
, &link
->io
);
1158 pcmcia_release_irq(link
->handle
, &link
->irq
);
1160 link
->state
&= ~(DEV_CONFIG
| DEV_RELEASE_PENDING
);
1165 /*----------------------------------------------------------------
1168 * Handler for card services events.
1171 * event The event code
1172 * priority hi/low - REMOVAL is the only hi
1173 * args ptr to card services struct containing info about
1177 * Zero on success, non-zero otherwise
1183 * Both interrupt and process thread, depends on the event.
1184 ----------------------------------------------------------------*/
1189 event_callback_args_t
*args
)
1192 dev_link_t
*link
= (dev_link_t
*) args
->client_data
;
1193 wlandevice_t
*wlandev
= (wlandevice_t
*)link
->priv
;
1194 hfa384x_t
*hw
= NULL
;
1198 if (wlandev
) hw
= wlandev
->priv
;
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;
1209 "%s: Initialization failed!\n", dev_info
);
1210 wlandev
->msdstate
= WLAN_MSD_HWFAIL
;
1214 /* Fill in the rest of the hw struct */
1215 hw
->irq
= wlandev
->netdev
->irq
;
1216 hw
->iobase
= wlandev
->netdev
->base_addr
;
1219 if (prism2_doreset
) {
1220 result
= hfa384x_corereset(hw
,
1221 prism2_reset_holdtime
,
1222 prism2_reset_settletime
, 0);
1225 "corereset() failed, result=%d.\n",
1227 wlandev
->msdstate
= WLAN_MSD_HWFAIL
;
1234 * TODO: test_hostif() not implemented yet.
1236 result
= hfa384x_test_hostif(hw
);
1239 "test_hostif() failed, result=%d.\n", result
);
1240 wlandev
->msdstate
= WLAN_MSD_HWFAIL
;
1244 wlandev
->msdstate
= WLAN_MSD_HWPRESENT
;
1247 case CS_EVENT_CARD_REMOVAL
:
1248 WLAN_LOG_DEBUG(5,"event is REMOVAL\n");
1249 link
->state
&= ~DEV_PRESENT
;
1252 p80211netdev_hwremoved(wlandev
);
1255 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
1256 if (link
->state
& DEV_CONFIG
)
1258 link
->release
.expires
= jiffies
+ (HZ
/20);
1259 add_timer(&link
->release
);
1263 case CS_EVENT_RESET_REQUEST
:
1264 WLAN_LOG_DEBUG(5,"event is RESET_REQUEST\n");
1266 "prism2 card reset not supported "
1267 "due to post-reset user mode configuration "
1270 " From user mode, use "
1271 "'cardctl suspend;cardctl resume' "
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");
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
)
1285 prism2sta_ifstate(wlandev
, P80211ENUM_ifstate_disable
);
1286 pcmcia_release_configuration(link
->handle
);
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
);
1300 return 0; /* noone else does anthing with the return value */
1306 int hfa384x_corereset(hfa384x_t
*hw
, int holdtime
, int settletime
, int genesis
)
1313 WLAN_LOG_DEBUG(3, "Doing reset via CardServices().\n");
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
, ®
);
1322 result
= pcmcia_access_configuration_register(
1326 if (result
!= CS_SUCCESS
) {
1328 ":0: AccessConfigurationRegister(CS_READ) failed,"
1329 "result=%d.\n", result
);
1332 corsave
= reg
.Value
;
1334 /* Write reset bit (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
, ®
);
1341 result
= pcmcia_access_configuration_register(
1345 if (result
!= CS_SUCCESS
) {
1347 ":1: AccessConfigurationRegister(CS_WRITE) failed,"
1348 "result=%d.\n", result
);
1352 /* Hold for holdtime */
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
, ®
);
1362 result
= pcmcia_access_configuration_register(
1366 if (result
!= CS_SUCCESS
) {
1368 ":1: AccessConfigurationRegister(CS_WRITE) failed,"
1369 "result=%d.\n", result
);
1374 /* Hold for holdtime */
1377 /* Clear reset bit */
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
, ®
);
1384 result
= pcmcia_access_configuration_register(
1388 if (result
!= CS_SUCCESS
) {
1390 ":2: AccessConfigurationRegister(CS_WRITE) failed,"
1391 "result=%d.\n", result
);
1396 /* Wait for settletime */
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
, ®
);
1406 result
= pcmcia_access_configuration_register(
1410 if (result
!= CS_SUCCESS
) {
1412 ":2: AccessConfigurationRegister(CS_WRITE) failed,"
1413 "result=%d.\n", result
);
1425 static int __init
prism2cs_init(void)
1427 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
1433 WLAN_LOG_NOTICE("%s Loaded\n", version
);
1434 WLAN_LOG_NOTICE("dev_info is: %s\n", dev_info
);
1436 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
1437 pcmcia_get_card_services_info(&serv
);
1438 if ( serv
.Revision
!= CS_RELEASE_CODE
)
1440 printk(KERN_NOTICE
"%s: CardServices release does not match!\n", dev_info
);
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
);
1448 pcmcia_register_driver(&prism2_cs_driver
);
1455 static void __exit
prism2cs_cleanup(void)
1457 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
1458 dev_link_t
*link
= dev_list
;
1462 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) )
1463 for (link
=dev_list
; link
!= NULL
; link
= nlink
) {
1465 if ( link
->state
& DEV_CONFIG
) {
1466 prism2sta_release((u_long
)link
);
1468 prism2sta_detach(link
); /* remember detach() frees link */
1472 unregister_pccard_driver( &dev_info
);
1474 pcmcia_unregister_driver(&prism2_cs_driver
);
1477 printk(KERN_NOTICE
"%s Unloaded\n", version
);
1483 module_init(prism2cs_init
);
1484 module_exit(prism2cs_cleanup
);