diff options
author | Pavel Roskin <proski@gnu.org> | 2006-04-07 04:10:57 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-04-24 16:15:52 -0400 |
commit | b884c872fa1917614b42a39020ffcca7fa9302b1 (patch) | |
tree | 82f5ba67f6b38c96804fb449e018d83fbdce65a1 /drivers/net/wireless | |
parent | c6fb2e9abef894efc4870e4c1e3aa4365b830a11 (diff) |
[PATCH] orinoco: reduce differences between PCI drivers, create orinoco_pci.h
Make all Orinoco PCI drivers (orinoco_pci, orinoco_plx, orinoco_tmd and
orinoco_nortel) as similar as possible. Use the best implementation of
error handling, the best error messages, the best comments.
Put common code to orinoco_pci.h. For now, it's suspend and resume
functions and function for registering the network device.
Signed-off-by: Pavel Roskin <proski@gnu.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/orinoco_nortel.c | 240 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco_pci.c | 144 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco_pci.h | 125 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco_plx.c | 259 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco_tmd.c | 165 |
5 files changed, 368 insertions, 565 deletions
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c index 3fff013f6788..deb22fb35515 100644 --- a/drivers/net/wireless/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco_nortel.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* orinoco_nortel.c | 1 | /* orinoco_nortel.c |
2 | * | 2 | * |
3 | * Driver for Prism II devices which would usually be driven by orinoco_cs, | 3 | * Driver for Prism II devices which would usually be driven by orinoco_cs, |
4 | * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in | 4 | * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in |
5 | * Nortel emobility, Symbol LA-4113 and Symbol LA-4123. | 5 | * Nortel emobility, Symbol LA-4113 and Symbol LA-4123. |
@@ -50,17 +50,12 @@ | |||
50 | #include <pcmcia/cisreg.h> | 50 | #include <pcmcia/cisreg.h> |
51 | 51 | ||
52 | #include "orinoco.h" | 52 | #include "orinoco.h" |
53 | #include "orinoco_pci.h" | ||
53 | 54 | ||
54 | #define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */ | 55 | #define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */ |
55 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ | 56 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ |
56 | 57 | ||
57 | 58 | ||
58 | /* Nortel specific data */ | ||
59 | struct nortel_pci_card { | ||
60 | unsigned long iobase1; | ||
61 | unsigned long iobase2; | ||
62 | }; | ||
63 | |||
64 | /* | 59 | /* |
65 | * Do a soft reset of the PCI card using the Configuration Option Register | 60 | * Do a soft reset of the PCI card using the Configuration Option Register |
66 | * We need this to get going... | 61 | * We need this to get going... |
@@ -69,48 +64,48 @@ struct nortel_pci_card { | |||
69 | * Note bis : Don't try to access HERMES_CMD during the reset phase. | 64 | * Note bis : Don't try to access HERMES_CMD during the reset phase. |
70 | * It just won't work ! | 65 | * It just won't work ! |
71 | */ | 66 | */ |
72 | static int nortel_pci_cor_reset(struct orinoco_private *priv) | 67 | static int orinoco_nortel_cor_reset(struct orinoco_private *priv) |
73 | { | 68 | { |
74 | struct nortel_pci_card *card = priv->card; | 69 | struct orinoco_pci_card *card = priv->card; |
75 | 70 | ||
76 | /* Assert the reset until the card notice */ | 71 | /* Assert the reset until the card notice */ |
77 | outw_p(8, card->iobase1 + 2); | 72 | iowrite16(8, card->bridge_io + 2); |
78 | inw(card->iobase2 + COR_OFFSET); | 73 | ioread16(card->attr_io + COR_OFFSET); |
79 | outw_p(0x80, card->iobase2 + COR_OFFSET); | 74 | iowrite16(0x80, card->attr_io + COR_OFFSET); |
80 | mdelay(1); | 75 | mdelay(1); |
81 | 76 | ||
82 | /* Give time for the card to recover from this hard effort */ | 77 | /* Give time for the card to recover from this hard effort */ |
83 | outw_p(0, card->iobase2 + COR_OFFSET); | 78 | iowrite16(0, card->attr_io + COR_OFFSET); |
84 | outw_p(0, card->iobase2 + COR_OFFSET); | 79 | iowrite16(0, card->attr_io + COR_OFFSET); |
85 | mdelay(1); | 80 | mdelay(1); |
86 | 81 | ||
87 | /* set COR as usual */ | 82 | /* Set COR as usual */ |
88 | outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); | 83 | iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); |
89 | outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); | 84 | iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); |
90 | mdelay(1); | 85 | mdelay(1); |
91 | 86 | ||
92 | outw_p(0x228, card->iobase1 + 2); | 87 | iowrite16(0x228, card->bridge_io + 2); |
93 | 88 | ||
94 | return 0; | 89 | return 0; |
95 | } | 90 | } |
96 | 91 | ||
97 | static int nortel_pci_hw_init(struct nortel_pci_card *card) | 92 | static int orinoco_nortel_hw_init(struct orinoco_pci_card *card) |
98 | { | 93 | { |
99 | int i; | 94 | int i; |
100 | u32 reg; | 95 | u32 reg; |
101 | 96 | ||
102 | /* setup bridge */ | 97 | /* Setup bridge */ |
103 | if (inw(card->iobase1) & 1) { | 98 | if (ioread16(card->bridge_io) & 1) { |
104 | printk(KERN_ERR PFX "brg1 answer1 wrong\n"); | 99 | printk(KERN_ERR PFX "brg1 answer1 wrong\n"); |
105 | return -EBUSY; | 100 | return -EBUSY; |
106 | } | 101 | } |
107 | outw_p(0x118, card->iobase1 + 2); | 102 | iowrite16(0x118, card->bridge_io + 2); |
108 | outw_p(0x108, card->iobase1 + 2); | 103 | iowrite16(0x108, card->bridge_io + 2); |
109 | mdelay(30); | 104 | mdelay(30); |
110 | outw_p(0x8, card->iobase1 + 2); | 105 | iowrite16(0x8, card->bridge_io + 2); |
111 | for (i = 0; i < 30; i++) { | 106 | for (i = 0; i < 30; i++) { |
112 | mdelay(30); | 107 | mdelay(30); |
113 | if (inw(card->iobase1) & 0x10) { | 108 | if (ioread16(card->bridge_io) & 0x10) { |
114 | break; | 109 | break; |
115 | } | 110 | } |
116 | } | 111 | } |
@@ -118,42 +113,42 @@ static int nortel_pci_hw_init(struct nortel_pci_card *card) | |||
118 | printk(KERN_ERR PFX "brg1 timed out\n"); | 113 | printk(KERN_ERR PFX "brg1 timed out\n"); |
119 | return -EBUSY; | 114 | return -EBUSY; |
120 | } | 115 | } |
121 | if (inw(card->iobase2 + 0xe0) & 1) { | 116 | if (ioread16(card->attr_io + COR_OFFSET) & 1) { |
122 | printk(KERN_ERR PFX "brg2 answer1 wrong\n"); | 117 | printk(KERN_ERR PFX "brg2 answer1 wrong\n"); |
123 | return -EBUSY; | 118 | return -EBUSY; |
124 | } | 119 | } |
125 | if (inw(card->iobase2 + 0xe2) & 1) { | 120 | if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) { |
126 | printk(KERN_ERR PFX "brg2 answer2 wrong\n"); | 121 | printk(KERN_ERR PFX "brg2 answer2 wrong\n"); |
127 | return -EBUSY; | 122 | return -EBUSY; |
128 | } | 123 | } |
129 | if (inw(card->iobase2 + 0xe4) & 1) { | 124 | if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) { |
130 | printk(KERN_ERR PFX "brg2 answer3 wrong\n"); | 125 | printk(KERN_ERR PFX "brg2 answer3 wrong\n"); |
131 | return -EBUSY; | 126 | return -EBUSY; |
132 | } | 127 | } |
133 | 128 | ||
134 | /* set the PCMCIA COR-Register */ | 129 | /* Set the PCMCIA COR-Register */ |
135 | outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); | 130 | iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); |
136 | mdelay(1); | 131 | mdelay(1); |
137 | reg = inw(card->iobase2 + COR_OFFSET); | 132 | reg = ioread16(card->attr_io + COR_OFFSET); |
138 | if (reg != COR_VALUE) { | 133 | if (reg != COR_VALUE) { |
139 | printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n", | 134 | printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n", |
140 | reg); | 135 | reg); |
141 | return -EBUSY; | 136 | return -EBUSY; |
142 | } | 137 | } |
143 | 138 | ||
144 | /* set leds */ | 139 | /* Set LEDs */ |
145 | outw_p(1, card->iobase1 + 10); | 140 | iowrite16(1, card->bridge_io + 10); |
146 | return 0; | 141 | return 0; |
147 | } | 142 | } |
148 | 143 | ||
149 | static int nortel_pci_init_one(struct pci_dev *pdev, | 144 | static int orinoco_nortel_init_one(struct pci_dev *pdev, |
150 | const struct pci_device_id *ent) | 145 | const struct pci_device_id *ent) |
151 | { | 146 | { |
152 | int err; | 147 | int err; |
153 | struct orinoco_private *priv; | 148 | struct orinoco_private *priv; |
154 | struct nortel_pci_card *card; | 149 | struct orinoco_pci_card *card; |
155 | struct net_device *dev; | 150 | struct net_device *dev; |
156 | void __iomem *iomem; | 151 | void __iomem *hermes_io, *bridge_io, *attr_io; |
157 | 152 | ||
158 | err = pci_enable_device(pdev); | 153 | err = pci_enable_device(pdev); |
159 | if (err) { | 154 | if (err) { |
@@ -162,19 +157,34 @@ static int nortel_pci_init_one(struct pci_dev *pdev, | |||
162 | } | 157 | } |
163 | 158 | ||
164 | err = pci_request_regions(pdev, DRIVER_NAME); | 159 | err = pci_request_regions(pdev, DRIVER_NAME); |
165 | if (err != 0) { | 160 | if (err) { |
166 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); | 161 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); |
167 | goto fail_resources; | 162 | goto fail_resources; |
168 | } | 163 | } |
169 | 164 | ||
170 | iomem = pci_iomap(pdev, 2, 0); | 165 | bridge_io = pci_iomap(pdev, 0, 0); |
171 | if (!iomem) { | 166 | if (!bridge_io) { |
172 | err = -ENOMEM; | 167 | printk(KERN_ERR PFX "Cannot map bridge registers\n"); |
173 | goto fail_map_io; | 168 | err = -EIO; |
169 | goto fail_map_bridge; | ||
170 | } | ||
171 | |||
172 | attr_io = pci_iomap(pdev, 1, 0); | ||
173 | if (!attr_io) { | ||
174 | printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n"); | ||
175 | err = -EIO; | ||
176 | goto fail_map_attr; | ||
177 | } | ||
178 | |||
179 | hermes_io = pci_iomap(pdev, 2, 0); | ||
180 | if (!hermes_io) { | ||
181 | printk(KERN_ERR PFX "Cannot map chipset registers\n"); | ||
182 | err = -EIO; | ||
183 | goto fail_map_hermes; | ||
174 | } | 184 | } |
175 | 185 | ||
176 | /* Allocate network device */ | 186 | /* Allocate network device */ |
177 | dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset); | 187 | dev = alloc_orinocodev(sizeof(*card), orinoco_nortel_cor_reset); |
178 | if (!dev) { | 188 | if (!dev) { |
179 | printk(KERN_ERR PFX "Cannot allocate network device\n"); | 189 | printk(KERN_ERR PFX "Cannot allocate network device\n"); |
180 | err = -ENOMEM; | 190 | err = -ENOMEM; |
@@ -183,16 +193,12 @@ static int nortel_pci_init_one(struct pci_dev *pdev, | |||
183 | 193 | ||
184 | priv = netdev_priv(dev); | 194 | priv = netdev_priv(dev); |
185 | card = priv->card; | 195 | card = priv->card; |
186 | card->iobase1 = pci_resource_start(pdev, 0); | 196 | card->bridge_io = bridge_io; |
187 | card->iobase2 = pci_resource_start(pdev, 1); | 197 | card->attr_io = attr_io; |
188 | dev->base_addr = pci_resource_start(pdev, 2); | ||
189 | SET_MODULE_OWNER(dev); | 198 | SET_MODULE_OWNER(dev); |
190 | SET_NETDEV_DEV(dev, &pdev->dev); | 199 | SET_NETDEV_DEV(dev, &pdev->dev); |
191 | 200 | ||
192 | hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING); | 201 | hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); |
193 | |||
194 | printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, " | ||
195 | "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr); | ||
196 | 202 | ||
197 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | 203 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, |
198 | dev->name, dev); | 204 | dev->name, dev); |
@@ -201,21 +207,20 @@ static int nortel_pci_init_one(struct pci_dev *pdev, | |||
201 | err = -EBUSY; | 207 | err = -EBUSY; |
202 | goto fail_irq; | 208 | goto fail_irq; |
203 | } | 209 | } |
204 | dev->irq = pdev->irq; | 210 | orinoco_pci_setup_netdev(dev, pdev, 2); |
205 | 211 | ||
206 | err = nortel_pci_hw_init(card); | 212 | err = orinoco_nortel_hw_init(card); |
207 | if (err) { | 213 | if (err) { |
208 | printk(KERN_ERR PFX "Hardware initialization failed\n"); | 214 | printk(KERN_ERR PFX "Hardware initialization failed\n"); |
209 | goto fail; | 215 | goto fail; |
210 | } | 216 | } |
211 | 217 | ||
212 | err = nortel_pci_cor_reset(priv); | 218 | err = orinoco_nortel_cor_reset(priv); |
213 | if (err) { | 219 | if (err) { |
214 | printk(KERN_ERR PFX "Initial reset failed\n"); | 220 | printk(KERN_ERR PFX "Initial reset failed\n"); |
215 | goto fail; | 221 | goto fail; |
216 | } | 222 | } |
217 | 223 | ||
218 | |||
219 | err = register_netdev(dev); | 224 | err = register_netdev(dev); |
220 | if (err) { | 225 | if (err) { |
221 | printk(KERN_ERR PFX "Cannot register network device\n"); | 226 | printk(KERN_ERR PFX "Cannot register network device\n"); |
@@ -234,9 +239,15 @@ static int nortel_pci_init_one(struct pci_dev *pdev, | |||
234 | free_orinocodev(dev); | 239 | free_orinocodev(dev); |
235 | 240 | ||
236 | fail_alloc: | 241 | fail_alloc: |
237 | pci_iounmap(pdev, iomem); | 242 | pci_iounmap(pdev, hermes_io); |
243 | |||
244 | fail_map_hermes: | ||
245 | pci_iounmap(pdev, attr_io); | ||
246 | |||
247 | fail_map_attr: | ||
248 | pci_iounmap(pdev, bridge_io); | ||
238 | 249 | ||
239 | fail_map_io: | 250 | fail_map_bridge: |
240 | pci_release_regions(pdev); | 251 | pci_release_regions(pdev); |
241 | 252 | ||
242 | fail_resources: | 253 | fail_resources: |
@@ -245,103 +256,27 @@ static int nortel_pci_init_one(struct pci_dev *pdev, | |||
245 | return err; | 256 | return err; |
246 | } | 257 | } |
247 | 258 | ||
248 | static void __devexit nortel_pci_remove_one(struct pci_dev *pdev) | 259 | static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev) |
249 | { | 260 | { |
250 | struct net_device *dev = pci_get_drvdata(pdev); | 261 | struct net_device *dev = pci_get_drvdata(pdev); |
251 | struct orinoco_private *priv = netdev_priv(dev); | 262 | struct orinoco_private *priv = netdev_priv(dev); |
252 | struct nortel_pci_card *card = priv->card; | 263 | struct orinoco_pci_card *card = priv->card; |
253 | 264 | ||
254 | /* clear leds */ | 265 | /* Clear LEDs */ |
255 | outw_p(0, card->iobase1 + 10); | 266 | iowrite16(0, card->bridge_io + 10); |
256 | 267 | ||
257 | unregister_netdev(dev); | 268 | unregister_netdev(dev); |
258 | free_irq(dev->irq, dev); | 269 | free_irq(dev->irq, dev); |
259 | pci_set_drvdata(pdev, NULL); | 270 | pci_set_drvdata(pdev, NULL); |
260 | free_orinocodev(dev); | 271 | free_orinocodev(dev); |
261 | pci_iounmap(pdev, priv->hw.iobase); | 272 | pci_iounmap(pdev, priv->hw.iobase); |
273 | pci_iounmap(pdev, card->attr_io); | ||
274 | pci_iounmap(pdev, card->bridge_io); | ||
262 | pci_release_regions(pdev); | 275 | pci_release_regions(pdev); |
263 | pci_disable_device(pdev); | 276 | pci_disable_device(pdev); |
264 | } | 277 | } |
265 | 278 | ||
266 | static int orinoco_nortel_suspend(struct pci_dev *pdev, pm_message_t state) | 279 | static struct pci_device_id orinoco_nortel_id_table[] = { |
267 | { | ||
268 | struct net_device *dev = pci_get_drvdata(pdev); | ||
269 | struct orinoco_private *priv = netdev_priv(dev); | ||
270 | unsigned long flags; | ||
271 | int err; | ||
272 | |||
273 | err = orinoco_lock(priv, &flags); | ||
274 | if (err) { | ||
275 | printk(KERN_ERR "%s: cannot lock hardware for suspend\n", | ||
276 | dev->name); | ||
277 | return err; | ||
278 | } | ||
279 | |||
280 | err = __orinoco_down(dev); | ||
281 | if (err) | ||
282 | printk(KERN_WARNING "%s: error %d bringing interface down " | ||
283 | "for suspend\n", dev->name, err); | ||
284 | |||
285 | netif_device_detach(dev); | ||
286 | |||
287 | priv->hw_unavailable++; | ||
288 | |||
289 | orinoco_unlock(priv, &flags); | ||
290 | |||
291 | free_irq(pdev->irq, dev); | ||
292 | pci_save_state(pdev); | ||
293 | pci_disable_device(pdev); | ||
294 | pci_set_power_state(pdev, PCI_D3hot); | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static int orinoco_nortel_resume(struct pci_dev *pdev) | ||
300 | { | ||
301 | struct net_device *dev = pci_get_drvdata(pdev); | ||
302 | struct orinoco_private *priv = netdev_priv(dev); | ||
303 | unsigned long flags; | ||
304 | int err; | ||
305 | |||
306 | pci_set_power_state(pdev, 0); | ||
307 | pci_enable_device(pdev); | ||
308 | pci_restore_state(pdev); | ||
309 | |||
310 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | ||
311 | dev->name, dev); | ||
312 | if (err) { | ||
313 | printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n", | ||
314 | dev->name); | ||
315 | pci_disable_device(pdev); | ||
316 | return -EBUSY; | ||
317 | } | ||
318 | |||
319 | err = orinoco_reinit_firmware(dev); | ||
320 | if (err) { | ||
321 | printk(KERN_ERR "%s: error %d re-initializing firmware " | ||
322 | "on resume\n", dev->name, err); | ||
323 | return err; | ||
324 | } | ||
325 | |||
326 | spin_lock_irqsave(&priv->lock, flags); | ||
327 | |||
328 | netif_device_attach(dev); | ||
329 | |||
330 | priv->hw_unavailable--; | ||
331 | |||
332 | if (priv->open && (! priv->hw_unavailable)) { | ||
333 | err = __orinoco_up(dev); | ||
334 | if (err) | ||
335 | printk(KERN_ERR "%s: Error %d restarting card on resume\n", | ||
336 | dev->name, err); | ||
337 | } | ||
338 | |||
339 | spin_unlock_irqrestore(&priv->lock, flags); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static struct pci_device_id nortel_pci_id_table[] = { | ||
345 | /* Nortel emobility PCI */ | 280 | /* Nortel emobility PCI */ |
346 | {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, | 281 | {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, |
347 | /* Symbol LA-4123 PCI */ | 282 | /* Symbol LA-4123 PCI */ |
@@ -349,15 +284,15 @@ static struct pci_device_id nortel_pci_id_table[] = { | |||
349 | {0,}, | 284 | {0,}, |
350 | }; | 285 | }; |
351 | 286 | ||
352 | MODULE_DEVICE_TABLE(pci, nortel_pci_id_table); | 287 | MODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table); |
353 | 288 | ||
354 | static struct pci_driver nortel_pci_driver = { | 289 | static struct pci_driver orinoco_nortel_driver = { |
355 | .name = DRIVER_NAME, | 290 | .name = DRIVER_NAME, |
356 | .id_table = nortel_pci_id_table, | 291 | .id_table = orinoco_nortel_id_table, |
357 | .probe = nortel_pci_init_one, | 292 | .probe = orinoco_nortel_init_one, |
358 | .remove = __devexit_p(nortel_pci_remove_one), | 293 | .remove = __devexit_p(orinoco_nortel_remove_one), |
359 | .suspend = orinoco_nortel_suspend, | 294 | .suspend = orinoco_pci_suspend, |
360 | .resume = orinoco_nortel_resume, | 295 | .resume = orinoco_pci_resume, |
361 | }; | 296 | }; |
362 | 297 | ||
363 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | 298 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION |
@@ -367,20 +302,19 @@ MODULE_DESCRIPTION | |||
367 | ("Driver for wireless LAN cards using the Nortel PCI bridge"); | 302 | ("Driver for wireless LAN cards using the Nortel PCI bridge"); |
368 | MODULE_LICENSE("Dual MPL/GPL"); | 303 | MODULE_LICENSE("Dual MPL/GPL"); |
369 | 304 | ||
370 | static int __init nortel_pci_init(void) | 305 | static int __init orinoco_nortel_init(void) |
371 | { | 306 | { |
372 | printk(KERN_DEBUG "%s\n", version); | 307 | printk(KERN_DEBUG "%s\n", version); |
373 | return pci_module_init(&nortel_pci_driver); | 308 | return pci_module_init(&orinoco_nortel_driver); |
374 | } | 309 | } |
375 | 310 | ||
376 | static void __exit nortel_pci_exit(void) | 311 | static void __exit orinoco_nortel_exit(void) |
377 | { | 312 | { |
378 | pci_unregister_driver(&nortel_pci_driver); | 313 | pci_unregister_driver(&orinoco_nortel_driver); |
379 | ssleep(1); | ||
380 | } | 314 | } |
381 | 315 | ||
382 | module_init(nortel_pci_init); | 316 | module_init(orinoco_nortel_init); |
383 | module_exit(nortel_pci_exit); | 317 | module_exit(orinoco_nortel_exit); |
384 | 318 | ||
385 | /* | 319 | /* |
386 | * Local variables: | 320 | * Local variables: |
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c index 75df90ff1dc9..41efac22ba6a 100644 --- a/drivers/net/wireless/orinoco_pci.c +++ b/drivers/net/wireless/orinoco_pci.c | |||
@@ -100,6 +100,7 @@ | |||
100 | #include <linux/pci.h> | 100 | #include <linux/pci.h> |
101 | 101 | ||
102 | #include "orinoco.h" | 102 | #include "orinoco.h" |
103 | #include "orinoco_pci.h" | ||
103 | 104 | ||
104 | /* All the magic there is from wlan-ng */ | 105 | /* All the magic there is from wlan-ng */ |
105 | /* Magic offset of the reset register of the PCI card */ | 106 | /* Magic offset of the reset register of the PCI card */ |
@@ -113,11 +114,6 @@ | |||
113 | #define HERMES_PCI_COR_OFFT (500) /* ms */ | 114 | #define HERMES_PCI_COR_OFFT (500) /* ms */ |
114 | #define HERMES_PCI_COR_BUSYT (500) /* ms */ | 115 | #define HERMES_PCI_COR_BUSYT (500) /* ms */ |
115 | 116 | ||
116 | /* Orinoco PCI specific data */ | ||
117 | struct orinoco_pci_card { | ||
118 | void __iomem *pci_ioaddr; | ||
119 | }; | ||
120 | |||
121 | /* | 117 | /* |
122 | * Do a soft reset of the PCI card using the Configuration Option Register | 118 | * Do a soft reset of the PCI card using the Configuration Option Register |
123 | * We need this to get going... | 119 | * We need this to get going... |
@@ -131,12 +127,11 @@ struct orinoco_pci_card { | |||
131 | * Note bis : Don't try to access HERMES_CMD during the reset phase. | 127 | * Note bis : Don't try to access HERMES_CMD during the reset phase. |
132 | * It just won't work ! | 128 | * It just won't work ! |
133 | */ | 129 | */ |
134 | static int | 130 | static int orinoco_pci_cor_reset(struct orinoco_private *priv) |
135 | orinoco_pci_cor_reset(struct orinoco_private *priv) | ||
136 | { | 131 | { |
137 | hermes_t *hw = &priv->hw; | 132 | hermes_t *hw = &priv->hw; |
138 | unsigned long timeout; | 133 | unsigned long timeout; |
139 | u16 reg; | 134 | u16 reg; |
140 | 135 | ||
141 | /* Assert the reset until the card notice */ | 136 | /* Assert the reset until the card notice */ |
142 | hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK); | 137 | hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK); |
@@ -163,17 +158,14 @@ orinoco_pci_cor_reset(struct orinoco_private *priv) | |||
163 | return 0; | 158 | return 0; |
164 | } | 159 | } |
165 | 160 | ||
166 | /* | ||
167 | * Initialise a card. Mostly similar to PLX code. | ||
168 | */ | ||
169 | static int orinoco_pci_init_one(struct pci_dev *pdev, | 161 | static int orinoco_pci_init_one(struct pci_dev *pdev, |
170 | const struct pci_device_id *ent) | 162 | const struct pci_device_id *ent) |
171 | { | 163 | { |
172 | int err = 0; | 164 | int err; |
173 | void __iomem *pci_ioaddr = NULL; | 165 | struct orinoco_private *priv; |
174 | struct orinoco_private *priv = NULL; | ||
175 | struct orinoco_pci_card *card; | 166 | struct orinoco_pci_card *card; |
176 | struct net_device *dev = NULL; | 167 | struct net_device *dev; |
168 | void __iomem *hermes_io; | ||
177 | 169 | ||
178 | err = pci_enable_device(pdev); | 170 | err = pci_enable_device(pdev); |
179 | if (err) { | 171 | if (err) { |
@@ -182,38 +174,32 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, | |||
182 | } | 174 | } |
183 | 175 | ||
184 | err = pci_request_regions(pdev, DRIVER_NAME); | 176 | err = pci_request_regions(pdev, DRIVER_NAME); |
185 | if (err != 0) { | 177 | if (err) { |
186 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); | 178 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); |
187 | goto fail_resources; | 179 | goto fail_resources; |
188 | } | 180 | } |
189 | 181 | ||
190 | /* Resource 0 is mapped to the hermes registers */ | 182 | hermes_io = pci_iomap(pdev, 0, 0); |
191 | pci_ioaddr = pci_iomap(pdev, 0, 0); | 183 | if (!hermes_io) { |
192 | if (!pci_ioaddr) { | 184 | printk(KERN_ERR PFX "Cannot remap chipset registers\n"); |
193 | err = -EIO; | 185 | err = -EIO; |
194 | printk(KERN_ERR PFX "Cannot remap hardware registers\n"); | 186 | goto fail_map_hermes; |
195 | goto fail_map; | ||
196 | } | 187 | } |
197 | 188 | ||
198 | /* Allocate network device */ | 189 | /* Allocate network device */ |
199 | dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset); | 190 | dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset); |
200 | if (! dev) { | 191 | if (!dev) { |
192 | printk(KERN_ERR PFX "Cannot allocate network device\n"); | ||
201 | err = -ENOMEM; | 193 | err = -ENOMEM; |
202 | goto fail_alloc; | 194 | goto fail_alloc; |
203 | } | 195 | } |
204 | 196 | ||
205 | priv = netdev_priv(dev); | 197 | priv = netdev_priv(dev); |
206 | card = priv->card; | 198 | card = priv->card; |
207 | card->pci_ioaddr = pci_ioaddr; | ||
208 | dev->mem_start = pci_resource_start(pdev, 0); | ||
209 | dev->mem_end = dev->mem_start + pci_resource_len(pdev, 0) - 1; | ||
210 | SET_MODULE_OWNER(dev); | 199 | SET_MODULE_OWNER(dev); |
211 | SET_NETDEV_DEV(dev, &pdev->dev); | 200 | SET_NETDEV_DEV(dev, &pdev->dev); |
212 | 201 | ||
213 | hermes_struct_init(&priv->hw, pci_ioaddr, HERMES_32BIT_REGSPACING); | 202 | hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING); |
214 | |||
215 | printk(KERN_DEBUG PFX "Detected device %s, mem:0x%lx-0x%lx, irq %d\n", | ||
216 | pci_name(pdev), dev->mem_start, dev->mem_end, pdev->irq); | ||
217 | 203 | ||
218 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | 204 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, |
219 | dev->name, dev); | 205 | dev->name, dev); |
@@ -222,9 +208,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, | |||
222 | err = -EBUSY; | 208 | err = -EBUSY; |
223 | goto fail_irq; | 209 | goto fail_irq; |
224 | } | 210 | } |
225 | dev->irq = pdev->irq; | 211 | orinoco_pci_setup_netdev(dev, pdev, 0); |
226 | 212 | ||
227 | /* Perform a COR reset to start the card */ | ||
228 | err = orinoco_pci_cor_reset(priv); | 213 | err = orinoco_pci_cor_reset(priv); |
229 | if (err) { | 214 | if (err) { |
230 | printk(KERN_ERR PFX "Initial reset failed\n"); | 215 | printk(KERN_ERR PFX "Initial reset failed\n"); |
@@ -233,7 +218,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, | |||
233 | 218 | ||
234 | err = register_netdev(dev); | 219 | err = register_netdev(dev); |
235 | if (err) { | 220 | if (err) { |
236 | printk(KERN_ERR PFX "Failed to register net device\n"); | 221 | printk(KERN_ERR PFX "Cannot register network device\n"); |
237 | goto fail; | 222 | goto fail; |
238 | } | 223 | } |
239 | 224 | ||
@@ -249,9 +234,9 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, | |||
249 | free_orinocodev(dev); | 234 | free_orinocodev(dev); |
250 | 235 | ||
251 | fail_alloc: | 236 | fail_alloc: |
252 | iounmap(pci_ioaddr); | 237 | pci_iounmap(pdev, hermes_io); |
253 | 238 | ||
254 | fail_map: | 239 | fail_map_hermes: |
255 | pci_release_regions(pdev); | 240 | pci_release_regions(pdev); |
256 | 241 | ||
257 | fail_resources: | 242 | fail_resources: |
@@ -264,98 +249,17 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev) | |||
264 | { | 249 | { |
265 | struct net_device *dev = pci_get_drvdata(pdev); | 250 | struct net_device *dev = pci_get_drvdata(pdev); |
266 | struct orinoco_private *priv = netdev_priv(dev); | 251 | struct orinoco_private *priv = netdev_priv(dev); |
267 | struct orinoco_pci_card *card = priv->card; | ||
268 | 252 | ||
269 | unregister_netdev(dev); | 253 | unregister_netdev(dev); |
270 | free_irq(dev->irq, dev); | 254 | free_irq(dev->irq, dev); |
271 | pci_set_drvdata(pdev, NULL); | 255 | pci_set_drvdata(pdev, NULL); |
272 | free_orinocodev(dev); | 256 | free_orinocodev(dev); |
273 | iounmap(card->pci_ioaddr); | 257 | pci_iounmap(pdev, priv->hw.iobase); |
274 | pci_release_regions(pdev); | 258 | pci_release_regions(pdev); |
275 | pci_disable_device(pdev); | 259 | pci_disable_device(pdev); |
276 | } | 260 | } |
277 | 261 | ||
278 | static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 262 | static struct pci_device_id orinoco_pci_id_table[] = { |
279 | { | ||
280 | struct net_device *dev = pci_get_drvdata(pdev); | ||
281 | struct orinoco_private *priv = netdev_priv(dev); | ||
282 | unsigned long flags; | ||
283 | int err; | ||
284 | |||
285 | |||
286 | err = orinoco_lock(priv, &flags); | ||
287 | if (err) { | ||
288 | printk(KERN_ERR "%s: hw_unavailable on orinoco_pci_suspend\n", | ||
289 | dev->name); | ||
290 | return err; | ||
291 | } | ||
292 | |||
293 | err = __orinoco_down(dev); | ||
294 | if (err) | ||
295 | printk(KERN_WARNING "%s: orinoco_pci_suspend(): Error %d downing interface\n", | ||
296 | dev->name, err); | ||
297 | |||
298 | netif_device_detach(dev); | ||
299 | |||
300 | priv->hw_unavailable++; | ||
301 | |||
302 | orinoco_unlock(priv, &flags); | ||
303 | |||
304 | free_irq(pdev->irq, dev); | ||
305 | pci_save_state(pdev); | ||
306 | pci_disable_device(pdev); | ||
307 | pci_set_power_state(pdev, PCI_D3hot); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static int orinoco_pci_resume(struct pci_dev *pdev) | ||
313 | { | ||
314 | struct net_device *dev = pci_get_drvdata(pdev); | ||
315 | struct orinoco_private *priv = netdev_priv(dev); | ||
316 | unsigned long flags; | ||
317 | int err; | ||
318 | |||
319 | printk(KERN_DEBUG "%s: Orinoco-PCI waking up\n", dev->name); | ||
320 | |||
321 | pci_set_power_state(pdev, 0); | ||
322 | pci_enable_device(pdev); | ||
323 | pci_restore_state(pdev); | ||
324 | |||
325 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | ||
326 | dev->name, dev); | ||
327 | if (err) { | ||
328 | printk(KERN_ERR "%s: Cannot re-allocate IRQ\n", dev->name); | ||
329 | pci_disable_device(pdev); | ||
330 | return -EBUSY; | ||
331 | } | ||
332 | |||
333 | err = orinoco_reinit_firmware(dev); | ||
334 | if (err) { | ||
335 | printk(KERN_ERR "%s: Error %d re-initializing firmware on orinoco_pci_resume()\n", | ||
336 | dev->name, err); | ||
337 | return err; | ||
338 | } | ||
339 | |||
340 | spin_lock_irqsave(&priv->lock, flags); | ||
341 | |||
342 | netif_device_attach(dev); | ||
343 | |||
344 | priv->hw_unavailable--; | ||
345 | |||
346 | if (priv->open && (! priv->hw_unavailable)) { | ||
347 | err = __orinoco_up(dev); | ||
348 | if (err) | ||
349 | printk(KERN_ERR "%s: Error %d restarting card on orinoco_pci_resume()\n", | ||
350 | dev->name, err); | ||
351 | } | ||
352 | |||
353 | spin_unlock_irqrestore(&priv->lock, flags); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static struct pci_device_id orinoco_pci_pci_id_table[] = { | ||
359 | /* Intersil Prism 3 */ | 263 | /* Intersil Prism 3 */ |
360 | {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, | 264 | {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, |
361 | /* Intersil Prism 2.5 */ | 265 | /* Intersil Prism 2.5 */ |
@@ -365,11 +269,11 @@ static struct pci_device_id orinoco_pci_pci_id_table[] = { | |||
365 | {0,}, | 269 | {0,}, |
366 | }; | 270 | }; |
367 | 271 | ||
368 | MODULE_DEVICE_TABLE(pci, orinoco_pci_pci_id_table); | 272 | MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table); |
369 | 273 | ||
370 | static struct pci_driver orinoco_pci_driver = { | 274 | static struct pci_driver orinoco_pci_driver = { |
371 | .name = DRIVER_NAME, | 275 | .name = DRIVER_NAME, |
372 | .id_table = orinoco_pci_pci_id_table, | 276 | .id_table = orinoco_pci_id_table, |
373 | .probe = orinoco_pci_init_one, | 277 | .probe = orinoco_pci_init_one, |
374 | .remove = __devexit_p(orinoco_pci_remove_one), | 278 | .remove = __devexit_p(orinoco_pci_remove_one), |
375 | .suspend = orinoco_pci_suspend, | 279 | .suspend = orinoco_pci_suspend, |
diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco_pci.h new file mode 100644 index 000000000000..b05a9a5b1f5f --- /dev/null +++ b/drivers/net/wireless/orinoco_pci.h | |||
@@ -0,0 +1,125 @@ | |||
1 | /* orinoco_pci.h | ||
2 | * | ||
3 | * Common code for all Orinoco drivers for PCI devices, including | ||
4 | * both native PCI and PCMCIA-to-PCI bridges. | ||
5 | * | ||
6 | * Copyright (C) 2005, Pavel Roskin. | ||
7 | * See orinoco.c for license. | ||
8 | */ | ||
9 | |||
10 | #ifndef _ORINOCO_PCI_H | ||
11 | #define _ORINOCO_PCI_H | ||
12 | |||
13 | #include <linux/netdevice.h> | ||
14 | |||
15 | /* Driver specific data */ | ||
16 | struct orinoco_pci_card { | ||
17 | void __iomem *bridge_io; | ||
18 | void __iomem *attr_io; | ||
19 | }; | ||
20 | |||
21 | /* Set base address or memory range of the network device based on | ||
22 | * the PCI device it's using. Specify BAR of the "main" resource. | ||
23 | * To be used after request_irq(). */ | ||
24 | static inline void orinoco_pci_setup_netdev(struct net_device *dev, | ||
25 | struct pci_dev *pdev, int bar) | ||
26 | { | ||
27 | char *range_type; | ||
28 | unsigned long start = pci_resource_start(pdev, bar); | ||
29 | unsigned long len = pci_resource_len(pdev, bar); | ||
30 | unsigned long flags = pci_resource_flags(pdev, bar); | ||
31 | unsigned long end = start + len - 1; | ||
32 | |||
33 | dev->irq = pdev->irq; | ||
34 | if (flags & IORESOURCE_IO) { | ||
35 | dev->base_addr = start; | ||
36 | range_type = "ports"; | ||
37 | } else { | ||
38 | dev->mem_start = start; | ||
39 | dev->mem_end = end; | ||
40 | range_type = "memory"; | ||
41 | } | ||
42 | |||
43 | printk(KERN_DEBUG PFX "%s: irq %d, %s 0x%lx-0x%lx\n", | ||
44 | pci_name(pdev), pdev->irq, range_type, start, end); | ||
45 | } | ||
46 | |||
47 | static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
48 | { | ||
49 | struct net_device *dev = pci_get_drvdata(pdev); | ||
50 | struct orinoco_private *priv = netdev_priv(dev); | ||
51 | unsigned long flags; | ||
52 | int err; | ||
53 | |||
54 | err = orinoco_lock(priv, &flags); | ||
55 | if (err) { | ||
56 | printk(KERN_ERR "%s: cannot lock hardware for suspend\n", | ||
57 | dev->name); | ||
58 | return err; | ||
59 | } | ||
60 | |||
61 | err = __orinoco_down(dev); | ||
62 | if (err) | ||
63 | printk(KERN_WARNING "%s: error %d bringing interface down " | ||
64 | "for suspend\n", dev->name, err); | ||
65 | |||
66 | netif_device_detach(dev); | ||
67 | |||
68 | priv->hw_unavailable++; | ||
69 | |||
70 | orinoco_unlock(priv, &flags); | ||
71 | |||
72 | free_irq(pdev->irq, dev); | ||
73 | pci_save_state(pdev); | ||
74 | pci_disable_device(pdev); | ||
75 | pci_set_power_state(pdev, PCI_D3hot); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int orinoco_pci_resume(struct pci_dev *pdev) | ||
81 | { | ||
82 | struct net_device *dev = pci_get_drvdata(pdev); | ||
83 | struct orinoco_private *priv = netdev_priv(dev); | ||
84 | unsigned long flags; | ||
85 | int err; | ||
86 | |||
87 | pci_set_power_state(pdev, 0); | ||
88 | pci_enable_device(pdev); | ||
89 | pci_restore_state(pdev); | ||
90 | |||
91 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | ||
92 | dev->name, dev); | ||
93 | if (err) { | ||
94 | printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n", | ||
95 | dev->name); | ||
96 | pci_disable_device(pdev); | ||
97 | return -EBUSY; | ||
98 | } | ||
99 | |||
100 | err = orinoco_reinit_firmware(dev); | ||
101 | if (err) { | ||
102 | printk(KERN_ERR "%s: error %d re-initializing firmware " | ||
103 | "on resume\n", dev->name, err); | ||
104 | return err; | ||
105 | } | ||
106 | |||
107 | spin_lock_irqsave(&priv->lock, flags); | ||
108 | |||
109 | netif_device_attach(dev); | ||
110 | |||
111 | priv->hw_unavailable--; | ||
112 | |||
113 | if (priv->open && (! priv->hw_unavailable)) { | ||
114 | err = __orinoco_up(dev); | ||
115 | if (err) | ||
116 | printk(KERN_ERR "%s: Error %d restarting card on resume\n", | ||
117 | dev->name, err); | ||
118 | } | ||
119 | |||
120 | spin_unlock_irqrestore(&priv->lock, flags); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | #endif /* _ORINOCO_PCI_H */ | ||
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c index 3fe7a2f37896..c00388ec9460 100644 --- a/drivers/net/wireless/orinoco_plx.c +++ b/drivers/net/wireless/orinoco_plx.c | |||
@@ -33,7 +33,7 @@ | |||
33 | 33 | ||
34 | * Caution: this is experimental and probably buggy. For success and | 34 | * Caution: this is experimental and probably buggy. For success and |
35 | * failure reports for different cards and adaptors, see | 35 | * failure reports for different cards and adaptors, see |
36 | * orinoco_plx_pci_id_table near the end of the file. If you have a | 36 | * orinoco_plx_id_table near the end of the file. If you have a |
37 | * card we don't have the PCI id for, and looks like it should work, | 37 | * card we don't have the PCI id for, and looks like it should work, |
38 | * drop me mail with the id and "it works"/"it doesn't work". | 38 | * drop me mail with the id and "it works"/"it doesn't work". |
39 | * | 39 | * |
@@ -125,6 +125,7 @@ | |||
125 | #include <pcmcia/cisreg.h> | 125 | #include <pcmcia/cisreg.h> |
126 | 126 | ||
127 | #include "orinoco.h" | 127 | #include "orinoco.h" |
128 | #include "orinoco_pci.h" | ||
128 | 129 | ||
129 | #define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */ | 130 | #define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */ |
130 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ | 131 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ |
@@ -134,30 +135,20 @@ | |||
134 | #define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */ | 135 | #define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */ |
135 | #define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ | 136 | #define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ |
136 | 137 | ||
137 | static const u8 cis_magic[] = { | ||
138 | 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67 | ||
139 | }; | ||
140 | |||
141 | /* Orinoco PLX specific data */ | ||
142 | struct orinoco_plx_card { | ||
143 | void __iomem *attr_mem; | ||
144 | }; | ||
145 | |||
146 | /* | 138 | /* |
147 | * Do a soft reset of the card using the Configuration Option Register | 139 | * Do a soft reset of the card using the Configuration Option Register |
148 | */ | 140 | */ |
149 | static int orinoco_plx_cor_reset(struct orinoco_private *priv) | 141 | static int orinoco_plx_cor_reset(struct orinoco_private *priv) |
150 | { | 142 | { |
151 | hermes_t *hw = &priv->hw; | 143 | hermes_t *hw = &priv->hw; |
152 | struct orinoco_plx_card *card = priv->card; | 144 | struct orinoco_pci_card *card = priv->card; |
153 | u8 __iomem *attr_mem = card->attr_mem; | ||
154 | unsigned long timeout; | 145 | unsigned long timeout; |
155 | u16 reg; | 146 | u16 reg; |
156 | 147 | ||
157 | writeb(COR_VALUE | COR_RESET, attr_mem + COR_OFFSET); | 148 | iowrite8(COR_VALUE | COR_RESET, card->attr_io + COR_OFFSET); |
158 | mdelay(1); | 149 | mdelay(1); |
159 | 150 | ||
160 | writeb(COR_VALUE, attr_mem + COR_OFFSET); | 151 | iowrite8(COR_VALUE, card->attr_io + COR_OFFSET); |
161 | mdelay(1); | 152 | mdelay(1); |
162 | 153 | ||
163 | /* Just in case, wait more until the card is no longer busy */ | 154 | /* Just in case, wait more until the card is no longer busy */ |
@@ -168,7 +159,7 @@ static int orinoco_plx_cor_reset(struct orinoco_private *priv) | |||
168 | reg = hermes_read_regn(hw, CMD); | 159 | reg = hermes_read_regn(hw, CMD); |
169 | } | 160 | } |
170 | 161 | ||
171 | /* Did we timeout ? */ | 162 | /* Still busy? */ |
172 | if (reg & HERMES_CMD_BUSY) { | 163 | if (reg & HERMES_CMD_BUSY) { |
173 | printk(KERN_ERR PFX "Busy timeout\n"); | 164 | printk(KERN_ERR PFX "Busy timeout\n"); |
174 | return -ETIMEDOUT; | 165 | return -ETIMEDOUT; |
@@ -177,20 +168,55 @@ static int orinoco_plx_cor_reset(struct orinoco_private *priv) | |||
177 | return 0; | 168 | return 0; |
178 | } | 169 | } |
179 | 170 | ||
171 | static int orinoco_plx_hw_init(struct orinoco_pci_card *card) | ||
172 | { | ||
173 | int i; | ||
174 | u32 csr_reg; | ||
175 | static const u8 cis_magic[] = { | ||
176 | 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67 | ||
177 | }; | ||
178 | |||
179 | printk(KERN_DEBUG PFX "CIS: "); | ||
180 | for (i = 0; i < 16; i++) { | ||
181 | printk("%02X:", ioread8(card->attr_io + (i << 1))); | ||
182 | } | ||
183 | printk("\n"); | ||
184 | |||
185 | /* Verify whether a supported PC card is present */ | ||
186 | /* FIXME: we probably need to be smarted about this */ | ||
187 | for (i = 0; i < sizeof(cis_magic); i++) { | ||
188 | if (cis_magic[i] != ioread8(card->attr_io + (i << 1))) { | ||
189 | printk(KERN_ERR PFX "The CIS value of Prism2 PC " | ||
190 | "card is unexpected\n"); | ||
191 | return -ENODEV; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | /* bjoern: We need to tell the card to enable interrupts, in | ||
196 | case the serial eprom didn't do this already. See the | ||
197 | PLX9052 data book, p8-1 and 8-24 for reference. */ | ||
198 | csr_reg = ioread32(card->bridge_io + PLX_INTCSR); | ||
199 | if (!(csr_reg & PLX_INTCSR_INTEN)) { | ||
200 | csr_reg |= PLX_INTCSR_INTEN; | ||
201 | iowrite32(csr_reg, card->bridge_io + PLX_INTCSR); | ||
202 | csr_reg = ioread32(card->bridge_io + PLX_INTCSR); | ||
203 | if (!(csr_reg & PLX_INTCSR_INTEN)) { | ||
204 | printk(KERN_ERR PFX "Cannot enable interrupts\n"); | ||
205 | return -EIO; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | } | ||
180 | 211 | ||
181 | static int orinoco_plx_init_one(struct pci_dev *pdev, | 212 | static int orinoco_plx_init_one(struct pci_dev *pdev, |
182 | const struct pci_device_id *ent) | 213 | const struct pci_device_id *ent) |
183 | { | 214 | { |
184 | int err = 0; | 215 | int err; |
185 | u8 __iomem *attr_mem = NULL; | 216 | struct orinoco_private *priv; |
186 | u32 csr_reg, plx_addr; | 217 | struct orinoco_pci_card *card; |
187 | struct orinoco_private *priv = NULL; | 218 | struct net_device *dev; |
188 | struct orinoco_plx_card *card; | 219 | void __iomem *hermes_io, *attr_io, *bridge_io; |
189 | unsigned long pccard_ioaddr = 0; | ||
190 | unsigned long pccard_iolen = 0; | ||
191 | struct net_device *dev = NULL; | ||
192 | void __iomem *mem; | ||
193 | int i; | ||
194 | 220 | ||
195 | err = pci_enable_device(pdev); | 221 | err = pci_enable_device(pdev); |
196 | if (err) { | 222 | if (err) { |
@@ -199,30 +225,30 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
199 | } | 225 | } |
200 | 226 | ||
201 | err = pci_request_regions(pdev, DRIVER_NAME); | 227 | err = pci_request_regions(pdev, DRIVER_NAME); |
202 | if (err != 0) { | 228 | if (err) { |
203 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); | 229 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); |
204 | goto fail_resources; | 230 | goto fail_resources; |
205 | } | 231 | } |
206 | 232 | ||
207 | /* Resource 1 is mapped to PLX-specific registers */ | 233 | bridge_io = pci_iomap(pdev, 1, 0); |
208 | plx_addr = pci_resource_start(pdev, 1); | 234 | if (!bridge_io) { |
235 | printk(KERN_ERR PFX "Cannot map bridge registers\n"); | ||
236 | err = -EIO; | ||
237 | goto fail_map_bridge; | ||
238 | } | ||
209 | 239 | ||
210 | /* Resource 2 is mapped to the PCMCIA attribute memory */ | 240 | attr_io = pci_iomap(pdev, 2, 0); |
211 | attr_mem = ioremap(pci_resource_start(pdev, 2), | 241 | if (!attr_io) { |
212 | pci_resource_len(pdev, 2)); | 242 | printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n"); |
213 | if (!attr_mem) { | 243 | err = -EIO; |
214 | printk(KERN_ERR PFX "Cannot remap PCMCIA space\n"); | ||
215 | goto fail_map_attr; | 244 | goto fail_map_attr; |
216 | } | 245 | } |
217 | 246 | ||
218 | /* Resource 3 is mapped to the PCMCIA I/O address space */ | 247 | hermes_io = pci_iomap(pdev, 3, 0); |
219 | pccard_ioaddr = pci_resource_start(pdev, 3); | 248 | if (!hermes_io) { |
220 | pccard_iolen = pci_resource_len(pdev, 3); | 249 | printk(KERN_ERR PFX "Cannot map chipset registers\n"); |
221 | 250 | err = -EIO; | |
222 | mem = pci_iomap(pdev, 3, 0); | 251 | goto fail_map_hermes; |
223 | if (!mem) { | ||
224 | err = -ENOMEM; | ||
225 | goto fail_map_io; | ||
226 | } | 252 | } |
227 | 253 | ||
228 | /* Allocate network device */ | 254 | /* Allocate network device */ |
@@ -235,16 +261,12 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
235 | 261 | ||
236 | priv = netdev_priv(dev); | 262 | priv = netdev_priv(dev); |
237 | card = priv->card; | 263 | card = priv->card; |
238 | card->attr_mem = attr_mem; | 264 | card->bridge_io = bridge_io; |
239 | dev->base_addr = pccard_ioaddr; | 265 | card->attr_io = attr_io; |
240 | SET_MODULE_OWNER(dev); | 266 | SET_MODULE_OWNER(dev); |
241 | SET_NETDEV_DEV(dev, &pdev->dev); | 267 | SET_NETDEV_DEV(dev, &pdev->dev); |
242 | 268 | ||
243 | hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING); | 269 | hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); |
244 | |||
245 | printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PLX device " | ||
246 | "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq, | ||
247 | pccard_ioaddr); | ||
248 | 270 | ||
249 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | 271 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, |
250 | dev->name, dev); | 272 | dev->name, dev); |
@@ -253,20 +275,12 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
253 | err = -EBUSY; | 275 | err = -EBUSY; |
254 | goto fail_irq; | 276 | goto fail_irq; |
255 | } | 277 | } |
256 | dev->irq = pdev->irq; | 278 | orinoco_pci_setup_netdev(dev, pdev, 2); |
257 | 279 | ||
258 | /* bjoern: We need to tell the card to enable interrupts, in | 280 | err = orinoco_plx_hw_init(card); |
259 | case the serial eprom didn't do this already. See the | 281 | if (err) { |
260 | PLX9052 data book, p8-1 and 8-24 for reference. */ | 282 | printk(KERN_ERR PFX "Hardware initialization failed\n"); |
261 | csr_reg = inl(plx_addr + PLX_INTCSR); | 283 | goto fail; |
262 | if (!(csr_reg & PLX_INTCSR_INTEN)) { | ||
263 | csr_reg |= PLX_INTCSR_INTEN; | ||
264 | outl(csr_reg, plx_addr + PLX_INTCSR); | ||
265 | csr_reg = inl(plx_addr + PLX_INTCSR); | ||
266 | if (!(csr_reg & PLX_INTCSR_INTEN)) { | ||
267 | printk(KERN_ERR PFX "Cannot enable interrupts\n"); | ||
268 | goto fail; | ||
269 | } | ||
270 | } | 284 | } |
271 | 285 | ||
272 | err = orinoco_plx_cor_reset(priv); | 286 | err = orinoco_plx_cor_reset(priv); |
@@ -275,23 +289,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
275 | goto fail; | 289 | goto fail; |
276 | } | 290 | } |
277 | 291 | ||
278 | printk(KERN_DEBUG PFX "CIS: "); | ||
279 | for (i = 0; i < 16; i++) { | ||
280 | printk("%02X:", readb(attr_mem + 2*i)); | ||
281 | } | ||
282 | printk("\n"); | ||
283 | |||
284 | /* Verify whether a supported PC card is present */ | ||
285 | /* FIXME: we probably need to be smarted about this */ | ||
286 | for (i = 0; i < sizeof(cis_magic); i++) { | ||
287 | if (cis_magic[i] != readb(attr_mem +2*i)) { | ||
288 | printk(KERN_ERR PFX "The CIS value of Prism2 PC " | ||
289 | "card is unexpected\n"); | ||
290 | err = -EIO; | ||
291 | goto fail; | ||
292 | } | ||
293 | } | ||
294 | |||
295 | err = register_netdev(dev); | 292 | err = register_netdev(dev); |
296 | if (err) { | 293 | if (err) { |
297 | printk(KERN_ERR PFX "Cannot register network device\n"); | 294 | printk(KERN_ERR PFX "Cannot register network device\n"); |
@@ -310,12 +307,15 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
310 | free_orinocodev(dev); | 307 | free_orinocodev(dev); |
311 | 308 | ||
312 | fail_alloc: | 309 | fail_alloc: |
313 | pci_iounmap(pdev, mem); | 310 | pci_iounmap(pdev, hermes_io); |
314 | 311 | ||
315 | fail_map_io: | 312 | fail_map_hermes: |
316 | iounmap(attr_mem); | 313 | pci_iounmap(pdev, attr_io); |
317 | 314 | ||
318 | fail_map_attr: | 315 | fail_map_attr: |
316 | pci_iounmap(pdev, bridge_io); | ||
317 | |||
318 | fail_map_bridge: | ||
319 | pci_release_regions(pdev); | 319 | pci_release_regions(pdev); |
320 | 320 | ||
321 | fail_resources: | 321 | fail_resources: |
@@ -328,100 +328,20 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev) | |||
328 | { | 328 | { |
329 | struct net_device *dev = pci_get_drvdata(pdev); | 329 | struct net_device *dev = pci_get_drvdata(pdev); |
330 | struct orinoco_private *priv = netdev_priv(dev); | 330 | struct orinoco_private *priv = netdev_priv(dev); |
331 | struct orinoco_plx_card *card = priv->card; | 331 | struct orinoco_pci_card *card = priv->card; |
332 | u8 __iomem *attr_mem = card->attr_mem; | ||
333 | |||
334 | BUG_ON(! dev); | ||
335 | 332 | ||
336 | unregister_netdev(dev); | 333 | unregister_netdev(dev); |
337 | free_irq(dev->irq, dev); | 334 | free_irq(dev->irq, dev); |
338 | pci_set_drvdata(pdev, NULL); | 335 | pci_set_drvdata(pdev, NULL); |
339 | free_orinocodev(dev); | 336 | free_orinocodev(dev); |
340 | pci_iounmap(pdev, priv->hw.iobase); | 337 | pci_iounmap(pdev, priv->hw.iobase); |
341 | iounmap(attr_mem); | 338 | pci_iounmap(pdev, card->attr_io); |
339 | pci_iounmap(pdev, card->bridge_io); | ||
342 | pci_release_regions(pdev); | 340 | pci_release_regions(pdev); |
343 | pci_disable_device(pdev); | 341 | pci_disable_device(pdev); |
344 | } | 342 | } |
345 | 343 | ||
346 | static int orinoco_plx_suspend(struct pci_dev *pdev, pm_message_t state) | 344 | static struct pci_device_id orinoco_plx_id_table[] = { |
347 | { | ||
348 | struct net_device *dev = pci_get_drvdata(pdev); | ||
349 | struct orinoco_private *priv = netdev_priv(dev); | ||
350 | unsigned long flags; | ||
351 | int err; | ||
352 | |||
353 | err = orinoco_lock(priv, &flags); | ||
354 | if (err) { | ||
355 | printk(KERN_ERR "%s: cannot lock hardware for suspend\n", | ||
356 | dev->name); | ||
357 | return err; | ||
358 | } | ||
359 | |||
360 | err = __orinoco_down(dev); | ||
361 | if (err) | ||
362 | printk(KERN_WARNING "%s: error %d bringing interface down " | ||
363 | "for suspend\n", dev->name, err); | ||
364 | |||
365 | netif_device_detach(dev); | ||
366 | |||
367 | priv->hw_unavailable++; | ||
368 | |||
369 | orinoco_unlock(priv, &flags); | ||
370 | |||
371 | free_irq(pdev->irq, dev); | ||
372 | pci_save_state(pdev); | ||
373 | pci_disable_device(pdev); | ||
374 | pci_set_power_state(pdev, PCI_D3hot); | ||
375 | |||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static int orinoco_plx_resume(struct pci_dev *pdev) | ||
380 | { | ||
381 | struct net_device *dev = pci_get_drvdata(pdev); | ||
382 | struct orinoco_private *priv = netdev_priv(dev); | ||
383 | unsigned long flags; | ||
384 | int err; | ||
385 | |||
386 | pci_set_power_state(pdev, 0); | ||
387 | pci_enable_device(pdev); | ||
388 | pci_restore_state(pdev); | ||
389 | |||
390 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | ||
391 | dev->name, dev); | ||
392 | if (err) { | ||
393 | printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n", | ||
394 | dev->name); | ||
395 | pci_disable_device(pdev); | ||
396 | return -EBUSY; | ||
397 | } | ||
398 | |||
399 | err = orinoco_reinit_firmware(dev); | ||
400 | if (err) { | ||
401 | printk(KERN_ERR "%s: error %d re-initializing firmware " | ||
402 | "on resume\n", dev->name, err); | ||
403 | return err; | ||
404 | } | ||
405 | |||
406 | spin_lock_irqsave(&priv->lock, flags); | ||
407 | |||
408 | netif_device_attach(dev); | ||
409 | |||
410 | priv->hw_unavailable--; | ||
411 | |||
412 | if (priv->open && (! priv->hw_unavailable)) { | ||
413 | err = __orinoco_up(dev); | ||
414 | if (err) | ||
415 | printk(KERN_ERR "%s: Error %d restarting card on resume\n", | ||
416 | dev->name, err); | ||
417 | } | ||
418 | |||
419 | spin_unlock_irqrestore(&priv->lock, flags); | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static struct pci_device_id orinoco_plx_pci_id_table[] = { | ||
425 | {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */ | 345 | {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */ |
426 | {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */ | 346 | {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */ |
427 | {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ | 347 | {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ |
@@ -439,15 +359,15 @@ static struct pci_device_id orinoco_plx_pci_id_table[] = { | |||
439 | {0,}, | 359 | {0,}, |
440 | }; | 360 | }; |
441 | 361 | ||
442 | MODULE_DEVICE_TABLE(pci, orinoco_plx_pci_id_table); | 362 | MODULE_DEVICE_TABLE(pci, orinoco_plx_id_table); |
443 | 363 | ||
444 | static struct pci_driver orinoco_plx_driver = { | 364 | static struct pci_driver orinoco_plx_driver = { |
445 | .name = DRIVER_NAME, | 365 | .name = DRIVER_NAME, |
446 | .id_table = orinoco_plx_pci_id_table, | 366 | .id_table = orinoco_plx_id_table, |
447 | .probe = orinoco_plx_init_one, | 367 | .probe = orinoco_plx_init_one, |
448 | .remove = __devexit_p(orinoco_plx_remove_one), | 368 | .remove = __devexit_p(orinoco_plx_remove_one), |
449 | .suspend = orinoco_plx_suspend, | 369 | .suspend = orinoco_pci_suspend, |
450 | .resume = orinoco_plx_resume, | 370 | .resume = orinoco_pci_resume, |
451 | }; | 371 | }; |
452 | 372 | ||
453 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | 373 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION |
@@ -467,7 +387,6 @@ static int __init orinoco_plx_init(void) | |||
467 | static void __exit orinoco_plx_exit(void) | 387 | static void __exit orinoco_plx_exit(void) |
468 | { | 388 | { |
469 | pci_unregister_driver(&orinoco_plx_driver); | 389 | pci_unregister_driver(&orinoco_plx_driver); |
470 | ssleep(1); | ||
471 | } | 390 | } |
472 | 391 | ||
473 | module_init(orinoco_plx_init); | 392 | module_init(orinoco_plx_init); |
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c index b74807d4141f..438fe545b184 100644 --- a/drivers/net/wireless/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco_tmd.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* orinoco_tmd.c | 1 | /* orinoco_tmd.c |
2 | * | 2 | * |
3 | * Driver for Prism II devices which would usually be driven by orinoco_cs, | 3 | * Driver for Prism II devices which would usually be driven by orinoco_cs, |
4 | * but are connected to the PCI bus by a TMD7160. | 4 | * but are connected to the PCI bus by a TMD7160. |
5 | * | 5 | * |
@@ -29,14 +29,14 @@ | |||
29 | 29 | ||
30 | * Caution: this is experimental and probably buggy. For success and | 30 | * Caution: this is experimental and probably buggy. For success and |
31 | * failure reports for different cards and adaptors, see | 31 | * failure reports for different cards and adaptors, see |
32 | * orinoco_tmd_pci_id_table near the end of the file. If you have a | 32 | * orinoco_tmd_id_table near the end of the file. If you have a |
33 | * card we don't have the PCI id for, and looks like it should work, | 33 | * card we don't have the PCI id for, and looks like it should work, |
34 | * drop me mail with the id and "it works"/"it doesn't work". | 34 | * drop me mail with the id and "it works"/"it doesn't work". |
35 | * | 35 | * |
36 | * Note: if everything gets detected fine but it doesn't actually send | 36 | * Note: if everything gets detected fine but it doesn't actually send |
37 | * or receive packets, your first port of call should probably be to | 37 | * or receive packets, your first port of call should probably be to |
38 | * try newer firmware in the card. Especially if you're doing Ad-Hoc | 38 | * try newer firmware in the card. Especially if you're doing Ad-Hoc |
39 | * modes | 39 | * modes. |
40 | * | 40 | * |
41 | * The actual driving is done by orinoco.c, this is just resource | 41 | * The actual driving is done by orinoco.c, this is just resource |
42 | * allocation stuff. | 42 | * allocation stuff. |
@@ -61,32 +61,26 @@ | |||
61 | #include <pcmcia/cisreg.h> | 61 | #include <pcmcia/cisreg.h> |
62 | 62 | ||
63 | #include "orinoco.h" | 63 | #include "orinoco.h" |
64 | #include "orinoco_pci.h" | ||
64 | 65 | ||
65 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ | 66 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ |
66 | #define COR_RESET (0x80) /* reset bit in the COR register */ | 67 | #define COR_RESET (0x80) /* reset bit in the COR register */ |
67 | #define TMD_RESET_TIME (500) /* milliseconds */ | 68 | #define TMD_RESET_TIME (500) /* milliseconds */ |
68 | 69 | ||
69 | /* Orinoco TMD specific data */ | ||
70 | struct orinoco_tmd_card { | ||
71 | u32 tmd_io; | ||
72 | }; | ||
73 | |||
74 | |||
75 | /* | 70 | /* |
76 | * Do a soft reset of the card using the Configuration Option Register | 71 | * Do a soft reset of the card using the Configuration Option Register |
77 | */ | 72 | */ |
78 | static int orinoco_tmd_cor_reset(struct orinoco_private *priv) | 73 | static int orinoco_tmd_cor_reset(struct orinoco_private *priv) |
79 | { | 74 | { |
80 | hermes_t *hw = &priv->hw; | 75 | hermes_t *hw = &priv->hw; |
81 | struct orinoco_tmd_card *card = priv->card; | 76 | struct orinoco_pci_card *card = priv->card; |
82 | u32 addr = card->tmd_io; | ||
83 | unsigned long timeout; | 77 | unsigned long timeout; |
84 | u16 reg; | 78 | u16 reg; |
85 | 79 | ||
86 | outb(COR_VALUE | COR_RESET, addr); | 80 | iowrite8(COR_VALUE | COR_RESET, card->bridge_io); |
87 | mdelay(1); | 81 | mdelay(1); |
88 | 82 | ||
89 | outb(COR_VALUE, addr); | 83 | iowrite8(COR_VALUE, card->bridge_io); |
90 | mdelay(1); | 84 | mdelay(1); |
91 | 85 | ||
92 | /* Just in case, wait more until the card is no longer busy */ | 86 | /* Just in case, wait more until the card is no longer busy */ |
@@ -97,7 +91,7 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv) | |||
97 | reg = hermes_read_regn(hw, CMD); | 91 | reg = hermes_read_regn(hw, CMD); |
98 | } | 92 | } |
99 | 93 | ||
100 | /* Did we timeout ? */ | 94 | /* Still busy? */ |
101 | if (reg & HERMES_CMD_BUSY) { | 95 | if (reg & HERMES_CMD_BUSY) { |
102 | printk(KERN_ERR PFX "Busy timeout\n"); | 96 | printk(KERN_ERR PFX "Busy timeout\n"); |
103 | return -ETIMEDOUT; | 97 | return -ETIMEDOUT; |
@@ -110,11 +104,11 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv) | |||
110 | static int orinoco_tmd_init_one(struct pci_dev *pdev, | 104 | static int orinoco_tmd_init_one(struct pci_dev *pdev, |
111 | const struct pci_device_id *ent) | 105 | const struct pci_device_id *ent) |
112 | { | 106 | { |
113 | int err = 0; | 107 | int err; |
114 | struct orinoco_private *priv = NULL; | 108 | struct orinoco_private *priv; |
115 | struct orinoco_tmd_card *card; | 109 | struct orinoco_pci_card *card; |
116 | struct net_device *dev = NULL; | 110 | struct net_device *dev; |
117 | void __iomem *mem; | 111 | void __iomem *hermes_io, *bridge_io; |
118 | 112 | ||
119 | err = pci_enable_device(pdev); | 113 | err = pci_enable_device(pdev); |
120 | if (err) { | 114 | if (err) { |
@@ -123,20 +117,28 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, | |||
123 | } | 117 | } |
124 | 118 | ||
125 | err = pci_request_regions(pdev, DRIVER_NAME); | 119 | err = pci_request_regions(pdev, DRIVER_NAME); |
126 | if (err != 0) { | 120 | if (err) { |
127 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); | 121 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); |
128 | goto fail_resources; | 122 | goto fail_resources; |
129 | } | 123 | } |
130 | 124 | ||
131 | mem = pci_iomap(pdev, 2, 0); | 125 | bridge_io = pci_iomap(pdev, 1, 0); |
132 | if (! mem) { | 126 | if (!bridge_io) { |
133 | err = -ENOMEM; | 127 | printk(KERN_ERR PFX "Cannot map bridge registers\n"); |
134 | goto fail_iomap; | 128 | err = -EIO; |
129 | goto fail_map_bridge; | ||
130 | } | ||
131 | |||
132 | hermes_io = pci_iomap(pdev, 2, 0); | ||
133 | if (!hermes_io) { | ||
134 | printk(KERN_ERR PFX "Cannot map chipset registers\n"); | ||
135 | err = -EIO; | ||
136 | goto fail_map_hermes; | ||
135 | } | 137 | } |
136 | 138 | ||
137 | /* Allocate network device */ | 139 | /* Allocate network device */ |
138 | dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset); | 140 | dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset); |
139 | if (! dev) { | 141 | if (!dev) { |
140 | printk(KERN_ERR PFX "Cannot allocate network device\n"); | 142 | printk(KERN_ERR PFX "Cannot allocate network device\n"); |
141 | err = -ENOMEM; | 143 | err = -ENOMEM; |
142 | goto fail_alloc; | 144 | goto fail_alloc; |
@@ -144,16 +146,11 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, | |||
144 | 146 | ||
145 | priv = netdev_priv(dev); | 147 | priv = netdev_priv(dev); |
146 | card = priv->card; | 148 | card = priv->card; |
147 | card->tmd_io = pci_resource_start(pdev, 1); | 149 | card->bridge_io = bridge_io; |
148 | dev->base_addr = pci_resource_start(pdev, 2); | ||
149 | SET_MODULE_OWNER(dev); | 150 | SET_MODULE_OWNER(dev); |
150 | SET_NETDEV_DEV(dev, &pdev->dev); | 151 | SET_NETDEV_DEV(dev, &pdev->dev); |
151 | 152 | ||
152 | hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING); | 153 | hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); |
153 | |||
154 | printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device " | ||
155 | "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq, | ||
156 | dev->base_addr); | ||
157 | 154 | ||
158 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | 155 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, |
159 | dev->name, dev); | 156 | dev->name, dev); |
@@ -162,7 +159,7 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, | |||
162 | err = -EBUSY; | 159 | err = -EBUSY; |
163 | goto fail_irq; | 160 | goto fail_irq; |
164 | } | 161 | } |
165 | dev->irq = pdev->irq; | 162 | orinoco_pci_setup_netdev(dev, pdev, 2); |
166 | 163 | ||
167 | err = orinoco_tmd_cor_reset(priv); | 164 | err = orinoco_tmd_cor_reset(priv); |
168 | if (err) { | 165 | if (err) { |
@@ -188,9 +185,12 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, | |||
188 | free_orinocodev(dev); | 185 | free_orinocodev(dev); |
189 | 186 | ||
190 | fail_alloc: | 187 | fail_alloc: |
191 | pci_iounmap(pdev, mem); | 188 | pci_iounmap(pdev, hermes_io); |
192 | 189 | ||
193 | fail_iomap: | 190 | fail_map_hermes: |
191 | pci_iounmap(pdev, bridge_io); | ||
192 | |||
193 | fail_map_bridge: | ||
194 | pci_release_regions(pdev); | 194 | pci_release_regions(pdev); |
195 | 195 | ||
196 | fail_resources: | 196 | fail_resources: |
@@ -203,110 +203,32 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev) | |||
203 | { | 203 | { |
204 | struct net_device *dev = pci_get_drvdata(pdev); | 204 | struct net_device *dev = pci_get_drvdata(pdev); |
205 | struct orinoco_private *priv = dev->priv; | 205 | struct orinoco_private *priv = dev->priv; |
206 | 206 | struct orinoco_pci_card *card = priv->card; | |
207 | BUG_ON(! dev); | ||
208 | 207 | ||
209 | unregister_netdev(dev); | 208 | unregister_netdev(dev); |
210 | free_irq(dev->irq, dev); | 209 | free_irq(dev->irq, dev); |
211 | pci_set_drvdata(pdev, NULL); | 210 | pci_set_drvdata(pdev, NULL); |
212 | free_orinocodev(dev); | 211 | free_orinocodev(dev); |
213 | pci_iounmap(pdev, priv->hw.iobase); | 212 | pci_iounmap(pdev, priv->hw.iobase); |
213 | pci_iounmap(pdev, card->bridge_io); | ||
214 | pci_release_regions(pdev); | 214 | pci_release_regions(pdev); |
215 | pci_disable_device(pdev); | 215 | pci_disable_device(pdev); |
216 | } | 216 | } |
217 | 217 | ||
218 | static int orinoco_tmd_suspend(struct pci_dev *pdev, pm_message_t state) | 218 | static struct pci_device_id orinoco_tmd_id_table[] = { |
219 | { | ||
220 | struct net_device *dev = pci_get_drvdata(pdev); | ||
221 | struct orinoco_private *priv = netdev_priv(dev); | ||
222 | unsigned long flags; | ||
223 | int err; | ||
224 | |||
225 | err = orinoco_lock(priv, &flags); | ||
226 | if (err) { | ||
227 | printk(KERN_ERR "%s: cannot lock hardware for suspend\n", | ||
228 | dev->name); | ||
229 | return err; | ||
230 | } | ||
231 | |||
232 | err = __orinoco_down(dev); | ||
233 | if (err) | ||
234 | printk(KERN_WARNING "%s: error %d bringing interface down " | ||
235 | "for suspend\n", dev->name, err); | ||
236 | |||
237 | netif_device_detach(dev); | ||
238 | |||
239 | priv->hw_unavailable++; | ||
240 | |||
241 | orinoco_unlock(priv, &flags); | ||
242 | |||
243 | free_irq(pdev->irq, dev); | ||
244 | pci_save_state(pdev); | ||
245 | pci_disable_device(pdev); | ||
246 | pci_set_power_state(pdev, PCI_D3hot); | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static int orinoco_tmd_resume(struct pci_dev *pdev) | ||
252 | { | ||
253 | struct net_device *dev = pci_get_drvdata(pdev); | ||
254 | struct orinoco_private *priv = netdev_priv(dev); | ||
255 | unsigned long flags; | ||
256 | int err; | ||
257 | |||
258 | pci_set_power_state(pdev, 0); | ||
259 | pci_enable_device(pdev); | ||
260 | pci_restore_state(pdev); | ||
261 | |||
262 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | ||
263 | dev->name, dev); | ||
264 | if (err) { | ||
265 | printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n", | ||
266 | dev->name); | ||
267 | pci_disable_device(pdev); | ||
268 | return -EBUSY; | ||
269 | } | ||
270 | |||
271 | err = orinoco_reinit_firmware(dev); | ||
272 | if (err) { | ||
273 | printk(KERN_ERR "%s: error %d re-initializing firmware " | ||
274 | "on resume\n", dev->name, err); | ||
275 | return err; | ||
276 | } | ||
277 | |||
278 | spin_lock_irqsave(&priv->lock, flags); | ||
279 | |||
280 | netif_device_attach(dev); | ||
281 | |||
282 | priv->hw_unavailable--; | ||
283 | |||
284 | if (priv->open && (! priv->hw_unavailable)) { | ||
285 | err = __orinoco_up(dev); | ||
286 | if (err) | ||
287 | printk(KERN_ERR "%s: Error %d restarting card on resume\n", | ||
288 | dev->name, err); | ||
289 | } | ||
290 | |||
291 | spin_unlock_irqrestore(&priv->lock, flags); | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static struct pci_device_id orinoco_tmd_pci_id_table[] = { | ||
297 | {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ | 219 | {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ |
298 | {0,}, | 220 | {0,}, |
299 | }; | 221 | }; |
300 | 222 | ||
301 | MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table); | 223 | MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table); |
302 | 224 | ||
303 | static struct pci_driver orinoco_tmd_driver = { | 225 | static struct pci_driver orinoco_tmd_driver = { |
304 | .name = DRIVER_NAME, | 226 | .name = DRIVER_NAME, |
305 | .id_table = orinoco_tmd_pci_id_table, | 227 | .id_table = orinoco_tmd_id_table, |
306 | .probe = orinoco_tmd_init_one, | 228 | .probe = orinoco_tmd_init_one, |
307 | .remove = __devexit_p(orinoco_tmd_remove_one), | 229 | .remove = __devexit_p(orinoco_tmd_remove_one), |
308 | .suspend = orinoco_tmd_suspend, | 230 | .suspend = orinoco_pci_suspend, |
309 | .resume = orinoco_tmd_resume, | 231 | .resume = orinoco_pci_resume, |
310 | }; | 232 | }; |
311 | 233 | ||
312 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | 234 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION |
@@ -324,7 +246,6 @@ static int __init orinoco_tmd_init(void) | |||
324 | static void __exit orinoco_tmd_exit(void) | 246 | static void __exit orinoco_tmd_exit(void) |
325 | { | 247 | { |
326 | pci_unregister_driver(&orinoco_tmd_driver); | 248 | pci_unregister_driver(&orinoco_tmd_driver); |
327 | ssleep(1); | ||
328 | } | 249 | } |
329 | 250 | ||
330 | module_init(orinoco_tmd_init); | 251 | module_init(orinoco_tmd_init); |