Import 2.3.13
[davej-history.git] / drivers / net / ptifddi.c
blob1905874392a5da2446205f3151bc22a06d8c1c93
1 /* $Id: ptifddi.c,v 1.8 1999/08/08 01:35:56 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 device *dev)
115 static inline void myri_rx(struct ptifddi *pp, struct device *dev)
119 static void pti_interrupt(int irq, void *dev_id, struct pt_regs *regs)
121 struct device *dev = (struct device *) dev_id;
122 struct ptifddi *pp = (struct ptifddi *) dev->priv;
126 static int pti_open(struct device *dev)
128 struct ptifddi *pp = (struct ptifddi *) dev->priv;
130 return pti_init(pp, in_interrupt());
133 static int pti_close(struct device *dev)
135 struct ptifddi *pp = (struct ptifddi *) dev->priv;
137 return 0;
140 static int pti_start_xmit(struct sk_buff *skb, struct device *dev)
142 struct ptifddi *pp = (struct ptifddi *) dev->priv;
145 static struct enet_statistics *pti_get_stats(struct device *dev)
146 { return &(((struct ptifddi *)dev->priv)->enet_stats); }
148 static void pti_set_multicast(struct device *dev)
152 static inline int pti_fddi_init(struct device *dev, struct linux_sbus_device *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 prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0],
164 sdev->num_registers, sdev);
166 /* Register 0 mapping contains DPRAM. */
167 pp->dpram = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
168 sdev->reg_addrs[0].reg_size,
169 "PTI FDDI DPRAM",
170 sdev->reg_addrs[0].which_io, 0);
171 if(!pp->dpram) {
172 printk("ptiFDDI: Cannot map DPRAM I/O area.\n");
173 return ENODEV;
176 /* Next, register 1 contains reset byte. */
177 pp->reset = sparc_alloc_io(sdev->reg_addrs[1].phys_addr, 0,
178 sdev->reg_addrs[1].reg_size,
179 "PTI FDDI RESET Byte",
180 sdev->reg_addrs[1].which_io, 0);
181 if(!pp->reset) {
182 printk("ptiFDDI: Cannot map RESET byte.\n");
183 return ENODEV;
186 /* Register 2 contains unreset byte. */
187 pp->unreset = sparc_alloc_io(sdev->reg_addrs[2].phys_addr, 0,
188 sdev->reg_addrs[2].reg_size,
189 "PTI FDDI UNRESET Byte",
190 sdev->reg_addrs[2].which_io, 0);
191 if(!pp->unreset) {
192 printk("ptiFDDI: Cannot map UNRESET byte.\n");
193 return ENODEV;
196 /* Reset the card. */
197 pti_reset(pp);
199 /* Run boot-up card tests. */
200 i = pti_card_test(pp);
201 if(i) {
202 printk("ptiFDDI: Bootup card test fails.\n");
203 return ENODEV;
206 /* Clear DPRAM, start afresh. */
207 pti_clear_dpram(pp);
209 /* Init the firmware loader. */
210 pti_init_firmware_loader(pp);
212 /* Now load main card FDDI firmware, using the loader. */
213 pti_load_main_firmware(pp);
216 int __init ptifddi_sbus_probe(struct device *dev)
218 struct linux_sbus *bus;
219 struct linux_sbus_device *sdev = 0;
220 static int called = 0;
221 int cards = 0, v;
223 if(called)
224 return ENODEV;
225 called++;
227 for_each_sbus(bus) {
228 for_each_sbusdev(sdev, bus) {
229 if(cards) dev = NULL;
230 if(!strcmp(sdev->prom_name, "PTI,sbs600") ||
231 !strcmp(sdev->prom_name, "DPV,fddid")) {
232 cards++;
233 DET(("Found PTI FDDI as %s\n", sdev->prom_name));
234 if((v = pti_fddi_init(dev, sdev, (cards - 1))))
235 return v;
239 if(!cards)
240 return ENODEV;
241 return 0;
245 #ifdef MODULE
248 init_module(void)
250 root_pti_dev = NULL;
251 return ptifddi_sbus_probe(NULL);
254 void
255 cleanup_module(void)
257 struct ptifddi *pp;
259 /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
260 while (root_pti_dev) {
261 pp = root_pti_dev->next_module;
263 unregister_netdev(root_pti_dev->dev);
264 kfree(root_pti_dev->dev);
265 root_pti_dev = mp;
269 #endif /* MODULE */