File: /usr/src/linux/drivers/net/tokenring/abyss.c
1 /*
2 * abyss.c: Network driver for the Madge Smart 16/4 PCI Mk2 token ring card.
3 *
4 * Written 1999-2000 by Adam Fritzler
5 *
6 * This software may be used and distributed according to the terms
7 * of the GNU General Public License, incorporated herein by reference.
8 *
9 * This driver module supports the following cards:
10 * - Madge Smart 16/4 PCI Mk2
11 *
12 * Maintainer(s):
13 * AF Adam Fritzler mid@auk.cx
14 *
15 * Modification History:
16 * 30-Dec-99 AF Split off from the tms380tr driver.
17 * 22-Jan-00 AF Updated to use indirect read/writes
18 * 23-Nov-00 JG New PCI API, cleanups
19 *
20 *
21 * TODO:
22 * 1. See if we can use MMIO instead of inb/outb/inw/outw
23 * 2. Add support for Mk1 (has AT24 attached to the PCI
24 * config registers)
25 *
26 */
27
28 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/sched.h>
31 #include <linux/errno.h>
32 #include <linux/pci.h>
33 #include <linux/init.h>
34
35 #include <asm/system.h>
36 #include <asm/io.h>
37 #include <asm/irq.h>
38
39 #include <linux/netdevice.h>
40 #include <linux/trdevice.h>
41 #include "tms380tr.h"
42 #include "abyss.h" /* Madge-specific constants */
43
44 static char version[] __initdata =
45 "abyss.c: v1.02 23/11/2000 by Adam Fritzler\n";
46
47 #define ABYSS_IO_EXTENT 64
48
49 static struct pci_device_id abyss_pci_tbl[] __initdata = {
50 { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_MK2,
51 PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_TOKEN_RING << 8, 0x00ffffff, },
52 { } /* Terminating entry */
53 };
54 MODULE_DEVICE_TABLE(pci, abyss_pci_tbl);
55
56 MODULE_LICENSE("GPL");
57
58 static int abyss_open(struct net_device *dev);
59 static int abyss_close(struct net_device *dev);
60 static void abyss_enable(struct net_device *dev);
61 static int abyss_chipset_init(struct net_device *dev);
62 static void abyss_read_eeprom(struct net_device *dev);
63 static unsigned short abyss_setnselout_pins(struct net_device *dev);
64
65 static void at24_writedatabyte(unsigned long regaddr, unsigned char byte);
66 static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr);
67 static int at24_sendcmd(unsigned long regaddr, unsigned char cmd);
68 static unsigned char at24_readdatabit(unsigned long regaddr);
69 static unsigned char at24_readdatabyte(unsigned long regaddr);
70 static int at24_waitforack(unsigned long regaddr);
71 static int at24_waitfornack(unsigned long regaddr);
72 static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data);
73 static void at24_start(unsigned long regaddr);
74 static unsigned char at24_readb(unsigned long regaddr, unsigned char addr);
75
76 static unsigned short abyss_sifreadb(struct net_device *dev, unsigned short reg)
77 {
78 return inb(dev->base_addr + reg);
79 }
80
81 static unsigned short abyss_sifreadw(struct net_device *dev, unsigned short reg)
82 {
83 return inw(dev->base_addr + reg);
84 }
85
86 static void abyss_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
87 {
88 outb(val, dev->base_addr + reg);
89 }
90
91 static void abyss_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
92 {
93 outw(val, dev->base_addr + reg);
94 }
95
96 static int __init abyss_attach(struct pci_dev *pdev, const struct pci_device_id *ent)
97 {
98 static int versionprinted;
99 struct net_device *dev;
100 struct net_local *tp;
101 int i, ret, pci_irq_line;
102 unsigned long pci_ioaddr;
103
104 if (versionprinted++ == 0)
105 printk("%s", version);
106
107 if (pci_enable_device(pdev))
108 return -EIO;
109
110 /* Remove I/O space marker in bit 0. */
111 pci_irq_line = pdev->irq;
112 pci_ioaddr = pci_resource_start (pdev, 0);
113
114 /* At this point we have found a valid card. */
115
116 dev = init_trdev(NULL, 0);
117 if (!dev)
118 return -ENOMEM;
119 SET_MODULE_OWNER(dev);
120
121 if (!request_region(pci_ioaddr, ABYSS_IO_EXTENT, dev->name)) {
122 ret = -EBUSY;
123 goto err_out_trdev;
124 }
125
126 ret = request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ,
127 dev->name, dev);
128 if (ret)
129 goto err_out_region;
130
131 dev->base_addr = pci_ioaddr;
132 dev->irq = pci_irq_line;
133
134 printk("%s: Madge Smart 16/4 PCI Mk2 (Abyss)\n", dev->name);
135 printk("%s: IO: %#4lx IRQ: %d\n",
136 dev->name, pci_ioaddr, dev->irq);
137 /*
138 * The TMS SIF registers lay 0x10 above the card base address.
139 */
140 dev->base_addr += 0x10;
141
142 ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev);
143 if (ret) {
144 printk("%s: unable to get memory for dev->priv.\n",
145 dev->name);
146 goto err_out_irq;
147 }
148
149 abyss_read_eeprom(dev);
150
151 printk("%s: Ring Station Address: ", dev->name);
152 printk("%2.2x", dev->dev_addr[0]);
153 for (i = 1; i < 6; i++)
154 printk(":%2.2x", dev->dev_addr[i]);
155 printk("\n");
156
157 tp = dev->priv;
158 tp->setnselout = abyss_setnselout_pins;
159 tp->sifreadb = abyss_sifreadb;
160 tp->sifreadw = abyss_sifreadw;
161 tp->sifwriteb = abyss_sifwriteb;
162 tp->sifwritew = abyss_sifwritew;
163
164 memcpy(tp->ProductID, "Madge PCI 16/4 Mk2", PROD_ID_SIZE + 1);
165
166 dev->open = abyss_open;
167 dev->stop = abyss_close;
168
169 ret = register_trdev(dev);
170 if (ret)
171 goto err_out_tmsdev;
172
173 pci_set_drvdata(pdev, dev);
174 return 0;
175
176 err_out_tmsdev:
177 tmsdev_term(dev);
178 err_out_irq:
179 free_irq(pdev->irq, dev);
180 err_out_region:
181 release_region(pci_ioaddr, ABYSS_IO_EXTENT);
182 err_out_trdev:
183 unregister_netdev(dev);
184 kfree(dev);
185 return ret;
186 }
187
188 static unsigned short abyss_setnselout_pins(struct net_device *dev)
189 {
190 unsigned short val = 0;
191 struct net_local *tp = (struct net_local *)dev->priv;
192
193 if(tp->DataRate == SPEED_4)
194 val |= 0x01; /* Set 4Mbps */
195 else
196 val |= 0x00; /* Set 16Mbps */
197
198 return val;
199 }
200
201 /*
202 * The following Madge boards should use this code:
203 * - Smart 16/4 PCI Mk2 (Abyss)
204 * - Smart 16/4 PCI Mk1 (PCI T)
205 * - Smart 16/4 Client Plus PnP (Big Apple)
206 * - Smart 16/4 Cardbus Mk2
207 *
208 * These access an Atmel AT24 SEEPROM using their glue chip registers.
209 *
210 */
211 static void at24_writedatabyte(unsigned long regaddr, unsigned char byte)
212 {
213 int i;
214
215 for (i = 0; i < 8; i++) {
216 at24_setlines(regaddr, 0, (byte >> (7-i))&0x01);
217 at24_setlines(regaddr, 1, (byte >> (7-i))&0x01);
218 at24_setlines(regaddr, 0, (byte >> (7-i))&0x01);
219 }
220 }
221
222 static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr)
223 {
224 if (at24_sendcmd(regaddr, cmd)) {
225 at24_writedatabyte(regaddr, addr);
226 return at24_waitforack(regaddr);
227 }
228 return 0;
229 }
230
231 static int at24_sendcmd(unsigned long regaddr, unsigned char cmd)
232 {
233 int i;
234
235 for (i = 0; i < 10; i++) {
236 at24_start(regaddr);
237 at24_writedatabyte(regaddr, cmd);
238 if (at24_waitforack(regaddr))
239 return 1;
240 }
241 return 0;
242 }
243
244 static unsigned char at24_readdatabit(unsigned long regaddr)
245 {
246 unsigned char val;
247
248 at24_setlines(regaddr, 0, 1);
249 at24_setlines(regaddr, 1, 1);
250 val = (inb(regaddr) & AT24_DATA)?1:0;
251 at24_setlines(regaddr, 1, 1);
252 at24_setlines(regaddr, 0, 1);
253 return val;
254 }
255
256 static unsigned char at24_readdatabyte(unsigned long regaddr)
257 {
258 unsigned char data = 0;
259 int i;
260
261 for (i = 0; i < 8; i++) {
262 data <<= 1;
263 data |= at24_readdatabit(regaddr);
264 }
265
266 return data;
267 }
268
269 static int at24_waitforack(unsigned long regaddr)
270 {
271 int i;
272
273 for (i = 0; i < 10; i++) {
274 if ((at24_readdatabit(regaddr) & 0x01) == 0x00)
275 return 1;
276 }
277 return 0;
278 }
279
280 static int at24_waitfornack(unsigned long regaddr)
281 {
282 int i;
283 for (i = 0; i < 10; i++) {
284 if ((at24_readdatabit(regaddr) & 0x01) == 0x01)
285 return 1;
286 }
287 return 0;
288 }
289
290 static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data)
291 {
292 unsigned char val = AT24_ENABLE;
293 if (clock)
294 val |= AT24_CLOCK;
295 if (data)
296 val |= AT24_DATA;
297
298 outb(val, regaddr);
299 tms380tr_wait(20); /* Very necessary. */
300 }
301
302 static void at24_start(unsigned long regaddr)
303 {
304 at24_setlines(regaddr, 0, 1);
305 at24_setlines(regaddr, 1, 1);
306 at24_setlines(regaddr, 1, 0);
307 at24_setlines(regaddr, 0, 1);
308 }
309
310 static unsigned char at24_readb(unsigned long regaddr, unsigned char addr)
311 {
312 unsigned char data = 0xff;
313
314 if (at24_sendfullcmd(regaddr, AT24_WRITE, addr)) {
315 if (at24_sendcmd(regaddr, AT24_READ)) {
316 data = at24_readdatabyte(regaddr);
317 if (!at24_waitfornack(regaddr))
318 data = 0xff;
319 }
320 }
321 return data;
322 }
323
324
325 /*
326 * Enable basic functions of the Madge chipset needed
327 * for initialization.
328 */
329 static void abyss_enable(struct net_device *dev)
330 {
331 unsigned char reset_reg;
332 unsigned long ioaddr;
333
334 ioaddr = dev->base_addr;
335 reset_reg = inb(ioaddr + PCIBM2_RESET_REG);
336 reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;
337 outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
338 tms380tr_wait(100);
339 }
340
341 /*
342 * Enable the functions of the Madge chipset needed for
343 * full working order.
344 */
345 static int abyss_chipset_init(struct net_device *dev)
346 {
347 unsigned char reset_reg;
348 unsigned long ioaddr;
349
350 ioaddr = dev->base_addr;
351
352 reset_reg = inb(ioaddr + PCIBM2_RESET_REG);
353
354 reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;
355 outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
356
357 reset_reg &= ~(PCIBM2_RESET_REG_CHIP_NRES |
358 PCIBM2_RESET_REG_FIFO_NRES |
359 PCIBM2_RESET_REG_SIF_NRES);
360 outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
361
362 tms380tr_wait(100);
363
364 reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;
365 outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
366
367 reset_reg |= PCIBM2_RESET_REG_SIF_NRES;
368 outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
369
370 reset_reg |= PCIBM2_RESET_REG_FIFO_NRES;
371 outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
372
373 outb(PCIBM2_INT_CONTROL_REG_SINTEN |
374 PCIBM2_INT_CONTROL_REG_PCI_ERR_ENABLE,
375 ioaddr + PCIBM2_INT_CONTROL_REG);
376
377 outb(30, ioaddr + PCIBM2_FIFO_THRESHOLD);
378
379 return 0;
380 }
381
382 static inline void abyss_chipset_close(struct net_device *dev)
383 {
384 unsigned long ioaddr;
385
386 ioaddr = dev->base_addr;
387 outb(0, ioaddr + PCIBM2_RESET_REG);
388 }
389
390 /*
391 * Read configuration data from the AT24 SEEPROM on Madge cards.
392 *
393 */
394 static void abyss_read_eeprom(struct net_device *dev)
395 {
396 struct net_local *tp;
397 unsigned long ioaddr;
398 unsigned short val;
399 int i;
400
401 tp = (struct net_local *)dev->priv;
402 ioaddr = dev->base_addr;
403
404 /* Must enable glue chip first */
405 abyss_enable(dev);
406
407 val = at24_readb(ioaddr + PCIBM2_SEEPROM_REG,
408 PCIBM2_SEEPROM_RING_SPEED);
409 tp->DataRate = val?SPEED_4:SPEED_16; /* set open speed */
410 printk("%s: SEEPROM: ring speed: %dMb/sec\n", dev->name, tp->DataRate);
411
412 val = at24_readb(ioaddr + PCIBM2_SEEPROM_REG,
413 PCIBM2_SEEPROM_RAM_SIZE) * 128;
414 printk("%s: SEEPROM: adapter RAM: %dkb\n", dev->name, val);
415
416 dev->addr_len = 6;
417 for (i = 0; i < 6; i++)
418 dev->dev_addr[i] = at24_readb(ioaddr + PCIBM2_SEEPROM_REG,
419 PCIBM2_SEEPROM_BIA+i);
420 }
421
422 static int abyss_open(struct net_device *dev)
423 {
424 abyss_chipset_init(dev);
425 tms380tr_open(dev);
426 return 0;
427 }
428
429 static int abyss_close(struct net_device *dev)
430 {
431 tms380tr_close(dev);
432 abyss_chipset_close(dev);
433 return 0;
434 }
435
436 static void __exit abyss_detach (struct pci_dev *pdev)
437 {
438 struct net_device *dev = pci_get_drvdata(pdev);
439
440 if (!dev)
441 BUG();
442 unregister_netdev(dev);
443 release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT);
444 free_irq(dev->irq, dev);
445 tmsdev_term(dev);
446 kfree(dev);
447 pci_set_drvdata(pdev, NULL);
448 }
449
450 static struct pci_driver abyss_driver = {
451 name: "abyss",
452 id_table: abyss_pci_tbl,
453 probe: abyss_attach,
454 remove: abyss_detach,
455 };
456
457 static int __init abyss_init (void)
458 {
459 int rc = pci_register_driver (&abyss_driver);
460 if (rc < 0)
461 return rc;
462 if (rc == 0) {
463 pci_unregister_driver (&abyss_driver);
464 return -ENODEV;
465 }
466 return 0;
467 }
468
469 static void __exit abyss_rmmod (void)
470 {
471 pci_unregister_driver (&abyss_driver);
472 }
473
474 module_init(abyss_init);
475 module_exit(abyss_rmmod);
476
477
478 /*
479 * Local variables:
480 * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c"
481 * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c"
482 * c-set-style "K&R"
483 * c-indent-level: 8
484 * c-basic-offset: 8
485 * tab-width: 8
486 * End:
487 */
488