]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blob - drivers/staging/wlags49_h2/wl_cs.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[mirror_ubuntu-eoan-kernel.git] / drivers / staging / wlags49_h2 / wl_cs.c
1 /*******************************************************************************
2 * Agere Systems Inc.
3 * Wireless device driver for Linux (wlags49).
4 *
5 * Copyright (c) 1998-2003 Agere Systems Inc.
6 * All rights reserved.
7 * http://www.agere.com
8 *
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
11 *
12 *------------------------------------------------------------------------------
13 *
14 * This file contains processing and initialization specific to Card Services
15 * devices (PCMCIA, CF).
16 *
17 *------------------------------------------------------------------------------
18 *
19 * SOFTWARE LICENSE
20 *
21 * This software is provided subject to the following terms and conditions,
22 * which you should read carefully before using the software. Using this
23 * software indicates your acceptance of these terms and conditions. If you do
24 * not agree with these terms and conditions, do not use the software.
25 *
26 * Copyright © 2003 Agere Systems Inc.
27 * All rights reserved.
28 *
29 * Redistribution and use in source or binary forms, with or without
30 * modifications, are permitted provided that the following conditions are met:
31 *
32 * . Redistributions of source code must retain the above copyright notice, this
33 * list of conditions and the following Disclaimer as comments in the code as
34 * well as in the documentation and/or other materials provided with the
35 * distribution.
36 *
37 * . Redistributions in binary form must reproduce the above copyright notice,
38 * this list of conditions and the following Disclaimer in the documentation
39 * and/or other materials provided with the distribution.
40 *
41 * . Neither the name of Agere Systems Inc. nor the names of the contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * Disclaimer
46 *
47 * THIS SOFTWARE IS PROVIDED \93AS IS\94 AND ANY EXPRESS OR IMPLIED WARRANTIES,
48 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
49 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
50 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
51 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
52 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
55 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
57 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
58 * DAMAGE.
59 *
60 ******************************************************************************/
61
62 /*******************************************************************************
63 * include files
64 ******************************************************************************/
65 #include <wl_version.h>
66
67 #include <linux/kernel.h>
68 #include <linux/sched.h>
69 #include <linux/ptrace.h>
70 #include <linux/ctype.h>
71 #include <linux/string.h>
72 #include <linux/timer.h>
73 #include <linux/interrupt.h>
74 #include <linux/in.h>
75 #include <linux/delay.h>
76 #include <asm/io.h>
77 #include <asm/system.h>
78 #include <asm/bitops.h>
79
80 #include <linux/netdevice.h>
81 #include <linux/etherdevice.h>
82 #include <linux/skbuff.h>
83 #include <linux/if_arp.h>
84 #include <linux/ioport.h>
85
86 #include <pcmcia/cs_types.h>
87 #include <pcmcia/cs.h>
88 #include <pcmcia/cistpl.h>
89 #include <pcmcia/cisreg.h>
90 #include <pcmcia/ciscode.h>
91 #include <pcmcia/ds.h>
92 #include <debug.h>
93
94 #include <hcf.h>
95 #include <dhf.h>
96 #include <hcfdef.h>
97
98 #include <wl_if.h>
99 #include <wl_internal.h>
100 #include <wl_util.h>
101 #include <wl_main.h>
102 #include <wl_netdev.h>
103 #include <wl_cs.h>
104 #include <wl_sysfs.h>
105
106
107 /*******************************************************************************
108 * macro definitions
109 ******************************************************************************/
110 #define CS_CHECK(fn, ret) do { \
111 last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
112 } while (0)
113
114 /*******************************************************************************
115 * global definitions
116 ******************************************************************************/
117 #if DBG
118 extern dbg_info_t *DbgInfo;
119 #endif /* DBG */
120
121
122 /*******************************************************************************
123 * wl_adapter_attach()
124 *******************************************************************************
125 *
126 * DESCRIPTION:
127 *
128 * Creates an instance of the driver, allocating local data structures for
129 * one device. The device is registered with Card Services.
130 *
131 * PARAMETERS:
132 *
133 * none
134 *
135 * RETURNS:
136 *
137 * pointer to an allocated dev_link_t structure
138 * NULL on failure
139 *
140 ******************************************************************************/
141 static int wl_adapter_attach(struct pcmcia_device *link)
142 {
143 struct net_device *dev;
144 struct wl_private *lp;
145 /*------------------------------------------------------------------------*/
146
147 DBG_FUNC( "wl_adapter_attach" );
148 DBG_ENTER( DbgInfo );
149
150 dev = wl_device_alloc();
151 if(dev == NULL) {
152 DBG_ERROR( DbgInfo, "wl_device_alloc returned NULL\n");
153 return -ENOMEM;
154 }
155
156 link->io.NumPorts1 = HCF_NUM_IO_PORTS;
157 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
158 link->io.IOAddrLines = 6;
159 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
160 link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
161 link->irq.Handler = &wl_isr;
162 link->conf.Attributes = CONF_ENABLE_IRQ;
163 link->conf.IntType = INT_MEMORY_AND_IO;
164 link->conf.ConfigIndex = 5;
165 link->conf.Present = PRESENT_OPTION;
166
167 link->priv = link->irq.Instance = dev;
168 lp = wl_priv(dev);
169 lp->link = link;
170
171 wl_adapter_insert(link);
172
173 DBG_LEAVE( DbgInfo );
174 return 0;
175 } // wl_adapter_attach
176 /*============================================================================*/
177
178
179
180 /*******************************************************************************
181 * wl_adapter_detach()
182 *******************************************************************************
183 *
184 * DESCRIPTION:
185 *
186 * This deletes a driver "instance". The device is de-registered with Card
187 * Services. If it has been released, then the net device is unregistered, and
188 * all local data structures are freed. Otherwise, the structures will be
189 * freed when the device is released.
190 *
191 * PARAMETERS:
192 *
193 * link - pointer to the dev_link_t structure representing the device to
194 * detach
195 *
196 * RETURNS:
197 *
198 * N/A
199 *
200 ******************************************************************************/
201 static void wl_adapter_detach(struct pcmcia_device *link)
202 {
203 struct net_device *dev = link->priv;
204 /*------------------------------------------------------------------------*/
205
206
207 DBG_FUNC( "wl_adapter_detach" );
208 DBG_ENTER( DbgInfo );
209 DBG_PARAM( DbgInfo, "link", "0x%p", link );
210
211 wl_adapter_release(link);
212
213 if (dev) {
214 unregister_wlags_sysfs(dev);
215 unregister_netdev(dev);
216 }
217
218 wl_device_dealloc(dev);
219
220 DBG_LEAVE( DbgInfo );
221 } // wl_adapter_detach
222 /*============================================================================*/
223
224
225 /*******************************************************************************
226 * wl_adapter_release()
227 *******************************************************************************
228 *
229 * DESCRIPTION:
230 *
231 * After a card is removed, this routine will release the PCMCIA
232 * configuration. If the device is still open, this will be postponed until it
233 * is closed.
234 *
235 * PARAMETERS:
236 *
237 * arg - a u_long representing a pointer to a dev_link_t structure for the
238 * device to be released.
239 *
240 * RETURNS:
241 *
242 * N/A
243 *
244 ******************************************************************************/
245 void wl_adapter_release( struct pcmcia_device *link )
246 {
247 DBG_FUNC( "wl_adapter_release" );
248 DBG_ENTER( DbgInfo );
249 DBG_PARAM( DbgInfo, "link", "0x%p", link);
250
251 /* Stop hardware */
252 wl_remove(link->priv);
253
254 pcmcia_disable_device(link);
255
256 DBG_LEAVE( DbgInfo );
257 } // wl_adapter_release
258 /*============================================================================*/
259
260 static int wl_adapter_suspend(struct pcmcia_device *link)
261 {
262 struct net_device *dev = link->priv;
263
264 //if (link->open) {
265 netif_device_detach(dev);
266 wl_suspend(dev);
267 //// CHECK! pcmcia_release_configuration(link->handle);
268 //}
269
270 return 0;
271 } // wl_adapter_suspend
272
273 static int wl_adapter_resume(struct pcmcia_device *link)
274 {
275 struct net_device *dev = link->priv;
276
277 wl_resume(dev);
278
279 netif_device_attach( dev );
280
281 return 0;
282 } // wl_adapter_resume
283
284 /*******************************************************************************
285 * wl_adapter_insert()
286 *******************************************************************************
287 *
288 * DESCRIPTION:
289 *
290 * wl_adapter_insert() is scheduled to run after a CARD_INSERTION event is
291 * received, to configure the PCMCIA socket, and to make the ethernet device
292 * available to the system.
293 *
294 * PARAMETERS:
295 *
296 * link - pointer to the dev_link_t structure representing the device to
297 * insert
298 *
299 * RETURNS:
300 *
301 * N/A
302 *
303 ******************************************************************************/
304 void wl_adapter_insert( struct pcmcia_device *link )
305 {
306 struct net_device *dev;
307 int i;
308 int last_fn, last_ret;
309 /*------------------------------------------------------------------------*/
310
311 DBG_FUNC( "wl_adapter_insert" );
312 DBG_ENTER( DbgInfo );
313 DBG_PARAM( DbgInfo, "link", "0x%p", link );
314
315 dev = link->priv;
316
317 /* Do we need to allocate an interrupt? */
318 link->conf.Attributes |= CONF_ENABLE_IRQ;
319
320 CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
321 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
322 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
323
324
325 dev->irq = link->irq.AssignedIRQ;
326 dev->base_addr = link->io.BasePort1;
327
328 SET_NETDEV_DEV(dev, &handle_to_dev(link));
329 if (register_netdev(dev) != 0) {
330 printk("%s: register_netdev() failed\n", MODULE_NAME);
331 goto failed;
332 }
333 link->dev_node = &( wl_priv(dev) )->node;
334 strcpy(( wl_priv(dev) )->node.dev_name, dev->name);
335 register_wlags_sysfs(dev);
336
337 printk(KERN_INFO "%s: Wireless, io_addr %#03lx, irq %d, ""mac_address ",
338 dev->name, dev->base_addr, dev->irq);
339 for( i = 0; i < ETH_ALEN; i++ ) {
340 printk("%02X%c", dev->dev_addr[i], ((i < (ETH_ALEN-1)) ? ':' : '\n'));
341 }
342
343 DBG_LEAVE( DbgInfo );
344 return;
345
346
347 cs_failed:
348 cs_error( link, last_fn, last_ret );
349
350
351 failed:
352 wl_adapter_release( link );
353
354 DBG_LEAVE(DbgInfo);
355 return;
356 } // wl_adapter_insert
357 /*============================================================================*/
358
359
360 /*******************************************************************************
361 * wl_adapter_open()
362 *******************************************************************************
363 *
364 * DESCRIPTION:
365 *
366 * Open the device.
367 *
368 * PARAMETERS:
369 *
370 * dev - a pointer to a net_device structure representing the network
371 * device to open.
372 *
373 * RETURNS:
374 *
375 * 0 on success
376 * errno value otherwise
377 *
378 ******************************************************************************/
379 int wl_adapter_open( struct net_device *dev )
380 {
381 struct wl_private *lp = wl_priv(dev);
382 struct pcmcia_device *link = lp->link;
383 int result = 0;
384 int hcf_status = HCF_SUCCESS;
385 /*------------------------------------------------------------------------*/
386
387
388 DBG_FUNC( "wl_adapter_open" );
389 DBG_ENTER( DbgInfo );
390 DBG_PRINT( "%s\n", VERSION_INFO );
391 DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
392
393 if(!pcmcia_dev_present(link))
394 {
395 DBG_LEAVE( DbgInfo );
396 return -ENODEV;
397 }
398
399 link->open++;
400
401 hcf_status = wl_open( dev );
402
403 if( hcf_status != HCF_SUCCESS ) {
404 link->open--;
405 result = -ENODEV;
406 }
407
408 DBG_LEAVE( DbgInfo );
409 return result;
410 } // wl_adapter_open
411 /*============================================================================*/
412
413
414 /*******************************************************************************
415 * wl_adapter_close()
416 *******************************************************************************
417 *
418 * DESCRIPTION:
419 *
420 * Close the device.
421 *
422 * PARAMETERS:
423 *
424 * dev - a pointer to a net_device structure representing the network
425 * device to close.
426 *
427 * RETURNS:
428 *
429 * 0 on success
430 * errno value otherwise
431 *
432 ******************************************************************************/
433 int wl_adapter_close( struct net_device *dev )
434 {
435 struct wl_private *lp = wl_priv(dev);
436 struct pcmcia_device *link = lp->link;
437 /*------------------------------------------------------------------------*/
438
439
440 DBG_FUNC( "wl_adapter_close" );
441 DBG_ENTER( DbgInfo );
442 DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
443
444 if( link == NULL ) {
445 DBG_LEAVE( DbgInfo );
446 return -ENODEV;
447 }
448
449 DBG_TRACE( DbgInfo, "%s: Shutting down adapter.\n", dev->name );
450 wl_close( dev );
451
452 link->open--;
453
454 DBG_LEAVE( DbgInfo );
455 return 0;
456 } // wl_adapter_close
457 /*============================================================================*/
458
459 static struct pcmcia_device_id wl_adapter_ids[] = {
460 #if ! ((HCF_TYPE) & HCF_TYPE_HII5)
461 PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0003),
462 PCMCIA_DEVICE_PROD_ID12("Agere Systems", "Wireless PC Card Model 0110",
463 0x33103a9b, 0xe175b0dd),
464 #else
465 PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0004),
466 PCMCIA_DEVICE_PROD_ID12("Linksys", "WCF54G_Wireless-G_CompactFlash_Card",
467 0x0733cc81, 0x98a599e1),
468 #endif // (HCF_TYPE) & HCF_TYPE_HII5
469 PCMCIA_DEVICE_NULL,
470 };
471 MODULE_DEVICE_TABLE(pcmcia, wl_adapter_ids);
472
473 static struct pcmcia_driver wlags49_driver = {
474 .owner = THIS_MODULE,
475 .drv = {
476 .name = DRIVER_NAME,
477 },
478 .probe = wl_adapter_attach,
479 .remove = wl_adapter_detach,
480 .id_table = wl_adapter_ids,
481 .suspend = wl_adapter_suspend,
482 .resume = wl_adapter_resume,
483 };
484
485
486
487 /*******************************************************************************
488 * wl_adapter_init_module()
489 *******************************************************************************
490 *
491 * DESCRIPTION:
492 *
493 * Called by init_module() to perform PCMCIA driver initialization.
494 *
495 * PARAMETERS:
496 *
497 * N/A
498 *
499 * RETURNS:
500 *
501 * 0 on success
502 * -1 on error
503 *
504 ******************************************************************************/
505 int wl_adapter_init_module( void )
506 {
507 int ret;
508 /*------------------------------------------------------------------------*/
509
510
511 DBG_FUNC( "wl_adapter_init_module" );
512 DBG_ENTER( DbgInfo );
513 DBG_TRACE( DbgInfo, "wl_adapter_init_module() -- PCMCIA\n" );
514
515 ret = pcmcia_register_driver(&wlags49_driver);
516
517 DBG_LEAVE( DbgInfo );
518 return ret;
519 } // wl_adapter_init_module
520 /*============================================================================*/
521
522
523 /*******************************************************************************
524 * wl_adapter_cleanup_module()
525 *******************************************************************************
526 *
527 * DESCRIPTION:
528 *
529 * Called by cleanup_module() to perform driver uninitialization.
530 *
531 * PARAMETERS:
532 *
533 * N/A
534 *
535 * RETURNS:
536 *
537 * N/A
538 *
539 ******************************************************************************/
540 void wl_adapter_cleanup_module( void )
541 {
542 DBG_FUNC( "wl_adapter_cleanup_module" );
543 DBG_ENTER( DbgInfo );
544 DBG_TRACE( DbgInfo, "wl_adapter_cleanup_module() -- PCMCIA\n" );
545
546
547 pcmcia_unregister_driver(&wlags49_driver);
548
549 DBG_LEAVE( DbgInfo );
550 return;
551 } // wl_adapter_cleanup_module
552 /*============================================================================*/
553
554
555 /*******************************************************************************
556 * wl_adapter_is_open()
557 *******************************************************************************
558 *
559 * DESCRIPTION:
560 *
561 * Check with Card Services to determine if this device is open.
562 *
563 * PARAMETERS:
564 *
565 * dev - a pointer to the net_device structure whose open status will be
566 * checked
567 *
568 * RETURNS:
569 *
570 * nonzero if device is open
571 * 0 otherwise
572 *
573 ******************************************************************************/
574 int wl_adapter_is_open( struct net_device *dev )
575 {
576 struct wl_private *lp = wl_priv(dev);
577 struct pcmcia_device *link = lp->link;
578
579 if(!pcmcia_dev_present(link)) {
580 return 0;
581 }
582
583 return( link->open );
584 } // wl_adapter_is_open
585 /*============================================================================*/
586
587
588 #if DBG
589
590 /*******************************************************************************
591 * DbgEvent()
592 *******************************************************************************
593 *
594 * DESCRIPTION:
595 *
596 * Converts the card serivces events to text for debugging.
597 *
598 * PARAMETERS:
599 *
600 * mask - a integer representing the error(s) being reported by Card
601 * Services.
602 *
603 * RETURNS:
604 *
605 * a pointer to a string describing the error(s)
606 *
607 ******************************************************************************/
608 const char* DbgEvent( int mask )
609 {
610 static char DbgBuffer[256];
611 char *pBuf;
612 /*------------------------------------------------------------------------*/
613
614
615 pBuf = DbgBuffer;
616 *pBuf = '\0';
617
618
619 if( mask & CS_EVENT_WRITE_PROTECT )
620 strcat( pBuf, "WRITE_PROTECT " );
621
622 if(mask & CS_EVENT_CARD_LOCK)
623 strcat( pBuf, "CARD_LOCK " );
624
625 if(mask & CS_EVENT_CARD_INSERTION)
626 strcat( pBuf, "CARD_INSERTION " );
627
628 if(mask & CS_EVENT_CARD_REMOVAL)
629 strcat( pBuf, "CARD_REMOVAL " );
630
631 if(mask & CS_EVENT_BATTERY_DEAD)
632 strcat( pBuf, "BATTERY_DEAD " );
633
634 if(mask & CS_EVENT_BATTERY_LOW)
635 strcat( pBuf, "BATTERY_LOW " );
636
637 if(mask & CS_EVENT_READY_CHANGE)
638 strcat( pBuf, "READY_CHANGE " );
639
640 if(mask & CS_EVENT_CARD_DETECT)
641 strcat( pBuf, "CARD_DETECT " );
642
643 if(mask & CS_EVENT_RESET_REQUEST)
644 strcat( pBuf, "RESET_REQUEST " );
645
646 if(mask & CS_EVENT_RESET_PHYSICAL)
647 strcat( pBuf, "RESET_PHYSICAL " );
648
649 if(mask & CS_EVENT_CARD_RESET)
650 strcat( pBuf, "CARD_RESET " );
651
652 if(mask & CS_EVENT_REGISTRATION_COMPLETE)
653 strcat( pBuf, "REGISTRATION_COMPLETE " );
654
655 // if(mask & CS_EVENT_RESET_COMPLETE)
656 // strcat( pBuf, "RESET_COMPLETE " );
657
658 if(mask & CS_EVENT_PM_SUSPEND)
659 strcat( pBuf, "PM_SUSPEND " );
660
661 if(mask & CS_EVENT_PM_RESUME)
662 strcat( pBuf, "PM_RESUME " );
663
664 if(mask & CS_EVENT_INSERTION_REQUEST)
665 strcat( pBuf, "INSERTION_REQUEST " );
666
667 if(mask & CS_EVENT_EJECTION_REQUEST)
668 strcat( pBuf, "EJECTION_REQUEST " );
669
670 if(mask & CS_EVENT_MTD_REQUEST)
671 strcat( pBuf, "MTD_REQUEST " );
672
673 if(mask & CS_EVENT_ERASE_COMPLETE)
674 strcat( pBuf, "ERASE_COMPLETE " );
675
676 if(mask & CS_EVENT_REQUEST_ATTENTION)
677 strcat( pBuf, "REQUEST_ATTENTION " );
678
679 if(mask & CS_EVENT_CB_DETECT)
680 strcat( pBuf, "CB_DETECT " );
681
682 if(mask & CS_EVENT_3VCARD)
683 strcat( pBuf, "3VCARD " );
684
685 if(mask & CS_EVENT_XVCARD)
686 strcat( pBuf, "XVCARD " );
687
688
689 if( *pBuf ) {
690 pBuf[strlen(pBuf) - 1] = '\0';
691 } else {
692 if( mask != 0x0 ) {
693 sprintf( pBuf, "<<0x%08x>>", mask );
694 }
695 }
696
697 return pBuf;
698 } // DbgEvent
699 /*============================================================================*/
700
701 #endif /* DBG */