vserver 1.9.3
[linux-2.6.git] / drivers / net / wireless / airport.c
1 /* airport.c
2  *
3  * A driver for "Hermes" chipset based Apple Airport wireless
4  * card.
5  *
6  * Copyright notice & release notes in file orinoco.c
7  * 
8  * Note specific to airport stub:
9  * 
10  *  0.05 : first version of the new split driver
11  *  0.06 : fix possible hang on powerup, add sleep support
12  */
13
14 #define DRIVER_NAME "airport"
15 #define PFX DRIVER_NAME ": "
16
17 #include <linux/config.h>
18
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/init.h>
22 #include <linux/ptrace.h>
23 #include <linux/slab.h>
24 #include <linux/string.h>
25 #include <linux/timer.h>
26 #include <linux/ioport.h>
27 #include <linux/netdevice.h>
28 #include <linux/if_arp.h>
29 #include <linux/etherdevice.h>
30 #include <linux/wireless.h>
31 #include <linux/delay.h>
32
33 #include <asm/io.h>
34 #include <asm/system.h>
35 #include <asm/current.h>
36 #include <asm/prom.h>
37 #include <asm/machdep.h>
38 #include <asm/pmac_feature.h>
39 #include <asm/irq.h>
40 #include <asm/uaccess.h>
41
42 #include "orinoco.h"
43
44 #define AIRPORT_IO_LEN  (0x1000)        /* one page */
45
46 struct airport {
47         struct macio_dev *mdev;
48         void *vaddr;
49         int irq_requested;
50         int ndev_registered;
51 };
52
53 static int
54 airport_suspend(struct macio_dev *mdev, u32 state)
55 {
56         struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
57         struct orinoco_private *priv = netdev_priv(dev);
58         unsigned long flags;
59         int err;
60
61         printk(KERN_DEBUG "%s: Airport entering sleep mode\n", dev->name);
62
63         err = orinoco_lock(priv, &flags);
64         if (err) {
65                 printk(KERN_ERR "%s: hw_unavailable on PBOOK_SLEEP_NOW\n",
66                        dev->name);
67                 return 0;
68         }
69
70         err = __orinoco_down(dev);
71         if (err)
72                 printk(KERN_WARNING "%s: PBOOK_SLEEP_NOW: Error %d downing interface\n",
73                        dev->name, err);
74
75         netif_device_detach(dev);
76
77         priv->hw_unavailable++;
78
79         orinoco_unlock(priv, &flags);
80
81         disable_irq(dev->irq);
82         pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
83
84         return 0;
85 }
86
87 static int
88 airport_resume(struct macio_dev *mdev)
89 {
90         struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
91         struct orinoco_private *priv = netdev_priv(dev);
92         unsigned long flags;
93         int err;
94
95         printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
96
97         pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
98         msleep(200);
99
100         enable_irq(dev->irq);
101
102         err = orinoco_reinit_firmware(dev);
103         if (err) {
104                 printk(KERN_ERR "%s: Error %d re-initializing firmware on PBOOK_WAKE\n",
105                        dev->name, err);
106                 return 0;
107         }
108
109         spin_lock_irqsave(&priv->lock, flags);
110
111         netif_device_attach(dev);
112
113         priv->hw_unavailable--;
114
115         if (priv->open && (! priv->hw_unavailable)) {
116                 err = __orinoco_up(dev);
117                 if (err)
118                         printk(KERN_ERR "%s: Error %d restarting card on PBOOK_WAKE\n",
119                                dev->name, err);
120         }
121
122
123         spin_unlock_irqrestore(&priv->lock, flags);
124
125         return 0;
126 }
127
128 static int
129 airport_detach(struct macio_dev *mdev)
130 {
131         struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
132         struct orinoco_private *priv = netdev_priv(dev);
133         struct airport *card = priv->card;
134
135         if (card->ndev_registered)
136                 unregister_netdev(dev);
137         card->ndev_registered = 0;
138
139         if (card->irq_requested)
140                 free_irq(dev->irq, dev);
141         card->irq_requested = 0;
142
143         if (card->vaddr)
144                 iounmap(card->vaddr);
145         card->vaddr = NULL;
146
147         macio_release_resource(mdev, 0);
148
149         pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
150         ssleep(1);
151
152         macio_set_drvdata(mdev, NULL);
153         free_netdev(dev);
154
155         return 0;
156 }
157
158 static int airport_hard_reset(struct orinoco_private *priv)
159 {
160         /* It would be nice to power cycle the Airport for a real hard
161          * reset, but for some reason although it appears to
162          * re-initialize properly, it falls in a screaming heap
163          * shortly afterwards. */
164 #if 0
165         struct net_device *dev = priv->ndev;
166         struct airport *card = priv->card;
167
168         /* Vitally important.  If we don't do this it seems we get an
169          * interrupt somewhere during the power cycle, since
170          * hw_unavailable is already set it doesn't get ACKed, we get
171          * into an interrupt loop and the the PMU decides to turn us
172          * off. */
173         disable_irq(dev->irq);
174
175         pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 0);
176         ssleep(1);
177         pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 1);
178         ssleep(1);
179
180         enable_irq(dev->irq);
181         ssleep(1);
182 #endif
183
184         return 0;
185 }
186
187 static int
188 airport_attach(struct macio_dev *mdev, const struct of_match *match)
189 {
190         struct orinoco_private *priv;
191         struct net_device *dev;
192         struct airport *card;
193         unsigned long phys_addr;
194         hermes_t *hw;
195
196         if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
197                 printk(KERN_ERR PFX "wrong interrupt/addresses in OF tree\n");
198                 return -ENODEV;
199         }
200
201         /* Allocate space for private device-specific data */
202         dev = alloc_orinocodev(sizeof(*card), airport_hard_reset);
203         if (! dev) {
204                 printk(KERN_ERR PFX "can't allocate device datas\n");
205                 return -ENODEV;
206         }
207         priv = netdev_priv(dev);
208         card = priv->card;
209
210         hw = &priv->hw;
211         card->mdev = mdev;
212
213         if (macio_request_resource(mdev, 0, "airport")) {
214                 printk(KERN_ERR PFX "can't request IO resource !\n");
215                 free_netdev(dev);
216                 return -EBUSY;
217         }
218
219         SET_MODULE_OWNER(dev);
220         SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
221
222         macio_set_drvdata(mdev, dev);
223
224         /* Setup interrupts & base address */
225         dev->irq = macio_irq(mdev, 0);
226         phys_addr = macio_resource_start(mdev, 0);  /* Physical address */
227         printk(KERN_DEBUG PFX "Airport at physical address %lx\n", phys_addr);
228         dev->base_addr = phys_addr;
229         card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
230         if (!card->vaddr) {
231                 printk(PFX "ioremap() failed\n");
232                 goto failed;
233         }
234
235         hermes_struct_init(hw, (ulong)card->vaddr,
236                         HERMES_MEM, HERMES_16BIT_REGSPACING);
237                 
238         /* Power up card */
239         pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
240         ssleep(1);
241
242         /* Reset it before we get the interrupt */
243         hermes_init(hw);
244
245         if (request_irq(dev->irq, orinoco_interrupt, 0, "Airport", dev)) {
246                 printk(KERN_ERR PFX "Couldn't get IRQ %d\n", dev->irq);
247                 goto failed;
248         }
249         card->irq_requested = 1;
250
251         /* Tell the stack we exist */
252         if (register_netdev(dev) != 0) {
253                 printk(KERN_ERR PFX "register_netdev() failed\n");
254                 goto failed;
255         }
256         printk(KERN_DEBUG PFX "card registered for interface %s\n", dev->name);
257         card->ndev_registered = 1;
258         return 0;
259  failed:
260         airport_detach(mdev);
261         return -ENODEV;
262 }                               /* airport_attach */
263
264
265 static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
266         " (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
267 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
268 MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
269 MODULE_LICENSE("Dual MPL/GPL");
270
271 static struct of_match airport_match[] = 
272 {
273         {
274         .name           = "radio",
275         .type           = OF_ANY_MATCH,
276         .compatible     = OF_ANY_MATCH
277         },
278         {},
279 };
280
281 static struct macio_driver airport_driver = 
282 {
283         .name           = DRIVER_NAME,
284         .match_table    = airport_match,
285         .probe          = airport_attach,
286         .remove         = airport_detach,
287         .suspend        = airport_suspend,
288         .resume         = airport_resume,
289 };
290
291 static int __init
292 init_airport(void)
293 {
294         printk(KERN_DEBUG "%s\n", version);
295
296         return macio_register_driver(&airport_driver);
297 }
298
299 static void __exit
300 exit_airport(void)
301 {
302         return macio_unregister_driver(&airport_driver);
303 }
304
305 module_init(init_airport);
306 module_exit(exit_airport);