Merge with Linux 2.4.0-test4-pre3.
[linux-2.6/linux-mips.git] / drivers / net / ptifddi.c
blobdfabcdb949ded092115d60ba8821fc9ea58be427
1 /* $Id: ptifddi.c,v 1.13 2000/07/11 22:35:22 davem Exp $
2 * ptifddi.c: Network driver for Performance Technologies single-attach
3 * and dual-attach FDDI sbus cards.
5 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
6 */
8 static char *version =
9 "ptifddi.c:v1.0 10/Dec/96 David S. Miller (davem@caipfs.rutgers.edu)\n";
11 #include <linux/string.h>
12 #include <linux/init.h>
14 #include "ptifddi.h"
16 #include "ptifddi_asm.h"
18 #ifdef MODULE
19 static struct ptifddi *root_pti_dev = NULL;
20 #endif
22 static inline void pti_reset(struct ptifddi *pp)
24 pp->reset = 1;
27 static inline void pti_unreset(struct ptifddi *pp)
29 pp->unreset = 1;
32 static inline void pti_load_code_base(struct dfddi_ram *rp, unsigned short addr)
34 rp->loader_addr = ((addr << 8) & 0xff00) | ((addr >> 8) & 0x00ff);
37 static inline void pti_clear_dpram(struct ptifddi *pp)
39 memset(pp->dpram, 0, DPRAM_SIZE);
42 #define CARD_TEST_TIMEOUT 100000
44 static inline int pti_card_test(struct ptifddi *pp)
46 struct dfddi_ram *rp = pp->dpram;
47 unsigned char *code = &rp->loader;
48 unsigned char *status = (unsigned char *) rp;
49 int clicks = CARD_TEST_TIMEOUT;
51 /* Clear it out. */
52 pti_clear_dpram(pp);
54 /* Load test data. */
55 for(i = 0; i < test_firmware_size; i++)
56 code[i] = test_firmware[i];
58 /* Tell card where to execute the code. */
59 pti_load_code_base(pp, test_firmware_dev_addr);
61 /* Clear test run status in dpram. */
62 *status = 0;
64 /* Reset single attach state machine before the test. */
65 rp->reset = 1;
67 /* Unreset, to get the test code running. */
68 pti_unreset(pp);
70 /* Wait for dpram status to become 5, else fail if we time out. */
71 while(--clicks) {
72 if(*status == 5) {
73 pti_reset(pp);
74 return 0;
76 udelay(20);
78 return 1;
81 static inline void pti_init_firmware_loader(struct ptifddi *pp)
83 struct dfddi_ram *rp = pp->dpram;
84 int i;
86 for(i = 0; i < firmware_loader_size; i++)
87 rp->loader.loader_firmware[i] = firmware_loader[i];
90 static inline void pti_load_main_firmware(struct ptifddi *pp)
92 struct dfddi_ram *rp = pp->dpram;
93 struct dpram_loader *lp = &rp.loader;
94 int i;
99 static void pti_init_rings(struct ptifddi *pp, int from_irq)
103 static int pti_init(struct ptifddi *pp, int from_irq)
107 static void pti_is_not_so_happy(struct ptifddi *pp)
111 static inline void pti_tx(struct ptifddi *pp, struct net_device *dev)
115 static inline void myri_rx(struct ptifddi *pp, struct net_device *dev)
119 static void pti_interrupt(int irq, void *dev_id, struct pt_regs *regs)
121 struct net_device *dev = (struct net_device *) dev_id;
122 struct ptifddi *pp = (struct ptifddi *) dev->priv;
126 static int pti_open(struct net_device *dev)
128 struct ptifddi *pp = (struct ptifddi *) dev->priv;
130 return pti_init(pp, in_interrupt());
133 static int pti_close(struct net_device *dev)
135 struct ptifddi *pp = (struct ptifddi *) dev->priv;
137 return 0;
140 static int pti_start_xmit(struct sk_buff *skb, struct net_device *dev)
142 struct ptifddi *pp = (struct ptifddi *) dev->priv;
145 static struct net_device_stats *pti_get_stats(struct net_device *dev)
146 { return &(((struct ptifddi *)dev->priv)->enet_stats); }
148 static void pti_set_multicast(struct net_device *dev)
152 static inline int pti_fddi_init(struct net_device *dev, struct sbus_dev *sdev, int num)
154 static unsigned version_printed = 0;
155 struct ptifddi *pp;
156 int i;
158 dev = init_fddidev(0, sizeof(struct ptifddi));
160 if(version_printed++ == 0)
161 printk(version);
163 /* Register 0 mapping contains DPRAM. */
164 pp->dpram = (struct dfddi_ram *) sbus_ioremap(
165 &sdep->resource[0], 0, sizeof(sturct dfddi_ram), "PTI FDDI DPRAM");
166 if(!pp->dpram) {
167 printk("ptiFDDI: Cannot map DPRAM I/O area.\n");
168 return -ENODEV;
171 /* Next, register 1 contains reset byte. */
172 pp->reset = (unsigned char *) sbus_ioremap(
173 &sdep->resource[1], 0, 1, "PTI FDDI RESET Byte");
174 if(!pp->reset) {
175 printk("ptiFDDI: Cannot map RESET byte.\n");
176 return -ENODEV;
179 /* Register 2 contains unreset byte. */
180 pp->unreset = (unsigned char *) sbus_ioremap(
181 &sdep->resource[2], 0, 1, "PTI FDDI UNRESET Byte");
182 if(!pp->unreset) {
183 printk("ptiFDDI: Cannot map UNRESET byte.\n");
184 return -ENODEV;
187 /* Reset the card. */
188 pti_reset(pp);
190 /* Run boot-up card tests. */
191 i = pti_card_test(pp);
192 if(i) {
193 printk("ptiFDDI: Bootup card test fails.\n");
194 return -ENODEV;
197 /* Clear DPRAM, start afresh. */
198 pti_clear_dpram(pp);
200 /* Init the firmware loader. */
201 pti_init_firmware_loader(pp);
203 /* Now load main card FDDI firmware, using the loader. */
204 pti_load_main_firmware(pp);
207 int __init ptifddi_sbus_probe(struct net_device *dev)
209 struct sbus_bus *bus;
210 struct sbus_dev *sdev = 0;
211 static int called = 0;
212 int cards = 0, v;
214 if(called)
215 return -ENODEV;
216 called++;
218 for_each_sbus(bus) {
219 for_each_sbusdev(sdev, bus) {
220 if(cards) dev = NULL;
221 if(!strcmp(sdev->prom_name, "PTI,sbs600") ||
222 !strcmp(sdev->prom_name, "DPV,fddid")) {
223 cards++;
224 DET(("Found PTI FDDI as %s\n", sdev->prom_name));
225 if((v = pti_fddi_init(dev, sdev, (cards - 1))))
226 return v;
230 if(!cards)
231 return -ENODEV;
232 return 0;
236 #ifdef MODULE
239 init_module(void)
241 root_pti_dev = NULL;
242 return ptifddi_sbus_probe(NULL);
245 void
246 cleanup_module(void)
248 struct ptifddi *pp;
250 /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
251 while (root_pti_dev) {
252 pp = root_pti_dev->next_module;
254 unregister_netdev(root_pti_dev->dev);
255 kfree(root_pti_dev->dev);
256 root_pti_dev = mp;
260 #endif /* MODULE */