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