1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86#define DRIVER_NAME "orinoco_plx"
87#define PFX DRIVER_NAME ": "
88
89#include <linux/module.h>
90#include <linux/kernel.h>
91#include <linux/init.h>
92#include <linux/delay.h>
93#include <linux/pci.h>
94#include <pcmcia/cisreg.h>
95
96#include "orinoco.h"
97#include "orinoco_pci.h"
98
99#define COR_OFFSET (0x3e0)
100#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA)
101#define COR_RESET (0x80)
102#define PLX_RESET_TIME (500)
103
104#define PLX_INTCSR 0x4c
105#define PLX_INTCSR_INTEN (1 << 6)
106
107
108
109
110static int orinoco_plx_cor_reset(struct orinoco_private *priv)
111{
112 struct hermes *hw = &priv->hw;
113 struct orinoco_pci_card *card = priv->card;
114 unsigned long timeout;
115 u16 reg;
116
117 iowrite8(COR_VALUE | COR_RESET, card->attr_io + COR_OFFSET);
118 mdelay(1);
119
120 iowrite8(COR_VALUE, card->attr_io + COR_OFFSET);
121 mdelay(1);
122
123
124 timeout = jiffies + (PLX_RESET_TIME * HZ / 1000);
125 reg = hermes_read_regn(hw, CMD);
126 while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
127 mdelay(1);
128 reg = hermes_read_regn(hw, CMD);
129 }
130
131
132 if (reg & HERMES_CMD_BUSY) {
133 printk(KERN_ERR PFX "Busy timeout\n");
134 return -ETIMEDOUT;
135 }
136
137 return 0;
138}
139
140static int orinoco_plx_hw_init(struct orinoco_pci_card *card)
141{
142 int i;
143 u32 csr_reg;
144 static const u8 cis_magic[] = {
145 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
146 };
147
148 printk(KERN_DEBUG PFX "CIS: ");
149 for (i = 0; i < 16; i++)
150 printk("%02X:", ioread8(card->attr_io + (i << 1)));
151 printk("\n");
152
153
154
155 for (i = 0; i < sizeof(cis_magic); i++) {
156 if (cis_magic[i] != ioread8(card->attr_io + (i << 1))) {
157 printk(KERN_ERR PFX "The CIS value of Prism2 PC "
158 "card is unexpected\n");
159 return -ENODEV;
160 }
161 }
162
163
164
165
166 csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
167 if (!(csr_reg & PLX_INTCSR_INTEN)) {
168 csr_reg |= PLX_INTCSR_INTEN;
169 iowrite32(csr_reg, card->bridge_io + PLX_INTCSR);
170 csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
171 if (!(csr_reg & PLX_INTCSR_INTEN)) {
172 printk(KERN_ERR PFX "Cannot enable interrupts\n");
173 return -EIO;
174 }
175 }
176
177 return 0;
178}
179
180static int orinoco_plx_init_one(struct pci_dev *pdev,
181 const struct pci_device_id *ent)
182{
183 int err;
184 struct orinoco_private *priv;
185 struct orinoco_pci_card *card;
186 void __iomem *hermes_io, *attr_io, *bridge_io;
187
188 err = pci_enable_device(pdev);
189 if (err) {
190 printk(KERN_ERR PFX "Cannot enable PCI device\n");
191 return err;
192 }
193
194 err = pci_request_regions(pdev, DRIVER_NAME);
195 if (err) {
196 printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
197 goto fail_resources;
198 }
199
200 bridge_io = pci_iomap(pdev, 1, 0);
201 if (!bridge_io) {
202 printk(KERN_ERR PFX "Cannot map bridge registers\n");
203 err = -EIO;
204 goto fail_map_bridge;
205 }
206
207 attr_io = pci_iomap(pdev, 2, 0);
208 if (!attr_io) {
209 printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
210 err = -EIO;
211 goto fail_map_attr;
212 }
213
214 hermes_io = pci_iomap(pdev, 3, 0);
215 if (!hermes_io) {
216 printk(KERN_ERR PFX "Cannot map chipset registers\n");
217 err = -EIO;
218 goto fail_map_hermes;
219 }
220
221
222 priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
223 orinoco_plx_cor_reset, NULL);
224 if (!priv) {
225 printk(KERN_ERR PFX "Cannot allocate network device\n");
226 err = -ENOMEM;
227 goto fail_alloc;
228 }
229
230 card = priv->card;
231 card->bridge_io = bridge_io;
232 card->attr_io = attr_io;
233
234 hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
235
236 err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
237 DRIVER_NAME, priv);
238 if (err) {
239 printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
240 err = -EBUSY;
241 goto fail_irq;
242 }
243
244 err = orinoco_plx_hw_init(card);
245 if (err) {
246 printk(KERN_ERR PFX "Hardware initialization failed\n");
247 goto fail;
248 }
249
250 err = orinoco_plx_cor_reset(priv);
251 if (err) {
252 printk(KERN_ERR PFX "Initial reset failed\n");
253 goto fail;
254 }
255
256 err = orinoco_init(priv);
257 if (err) {
258 printk(KERN_ERR PFX "orinoco_init() failed\n");
259 goto fail;
260 }
261
262 err = orinoco_if_add(priv, 0, 0, NULL);
263 if (err) {
264 printk(KERN_ERR PFX "orinoco_if_add() failed\n");
265 goto fail;
266 }
267
268 pci_set_drvdata(pdev, priv);
269
270 return 0;
271
272 fail:
273 free_irq(pdev->irq, priv);
274
275 fail_irq:
276 pci_set_drvdata(pdev, NULL);
277 free_orinocodev(priv);
278
279 fail_alloc:
280 pci_iounmap(pdev, hermes_io);
281
282 fail_map_hermes:
283 pci_iounmap(pdev, attr_io);
284
285 fail_map_attr:
286 pci_iounmap(pdev, bridge_io);
287
288 fail_map_bridge:
289 pci_release_regions(pdev);
290
291 fail_resources:
292 pci_disable_device(pdev);
293
294 return err;
295}
296
297static void orinoco_plx_remove_one(struct pci_dev *pdev)
298{
299 struct orinoco_private *priv = pci_get_drvdata(pdev);
300 struct orinoco_pci_card *card = priv->card;
301
302 orinoco_if_del(priv);
303 free_irq(pdev->irq, priv);
304 pci_set_drvdata(pdev, NULL);
305 free_orinocodev(priv);
306 pci_iounmap(pdev, priv->hw.iobase);
307 pci_iounmap(pdev, card->attr_io);
308 pci_iounmap(pdev, card->bridge_io);
309 pci_release_regions(pdev);
310 pci_disable_device(pdev);
311}
312
313static const struct pci_device_id orinoco_plx_id_table[] = {
314 {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,},
315 {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,},
316 {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,},
317 {0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},
318
319
320 {0x16ab, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},
321 {0x16ab, 0x1101, PCI_ANY_ID, PCI_ANY_ID,},
322 {0x16ab, 0x1102, PCI_ANY_ID, PCI_ANY_ID,},
323 {0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,},
324 {0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,},
325
326 {0x10b7, 0x7770, PCI_ANY_ID, PCI_ANY_ID,},
327
328 {0,},
329};
330
331MODULE_DEVICE_TABLE(pci, orinoco_plx_id_table);
332
333static struct pci_driver orinoco_plx_driver = {
334 .name = DRIVER_NAME,
335 .id_table = orinoco_plx_id_table,
336 .probe = orinoco_plx_init_one,
337 .remove = orinoco_plx_remove_one,
338 .suspend = orinoco_pci_suspend,
339 .resume = orinoco_pci_resume,
340};
341
342static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
343 " (Pavel Roskin <proski@gnu.org>,"
344 " David Gibson <hermes@gibson.dropbear.id.au>,"
345 " Daniel Barlow <dan@telent.net>)";
346MODULE_AUTHOR("Daniel Barlow <dan@telent.net>");
347MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge");
348MODULE_LICENSE("Dual MPL/GPL");
349
350static int __init orinoco_plx_init(void)
351{
352 printk(KERN_DEBUG "%s\n", version);
353 return pci_register_driver(&orinoco_plx_driver);
354}
355
356static void __exit orinoco_plx_exit(void)
357{
358 pci_unregister_driver(&orinoco_plx_driver);
359}
360
361module_init(orinoco_plx_init);
362module_exit(orinoco_plx_exit);
363
364
365
366
367
368
369
370
371