File: /usr/src/linux/drivers/net/ptifddi.c

1     /* $Id: ptifddi.c,v 1.14 2001/04/14 01:12:04 davem Exp $
2      * ptifddi.c: Network driver for Performance Technologies single-attach
3      *            and dual-attach FDDI sbus cards.
4      *
5      * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
6      */
7     
8     static char *version =
9             "ptifddi.c:v1.0 10/Dec/96 David S. Miller (davem@caipfs.rutgers.edu)\n";
10     
11     #include <linux/string.h>
12     #include <linux/init.h>
13     
14     #include "ptifddi.h"
15     
16     #include "ptifddi_asm.h"
17     
18     #ifdef MODULE
19     static struct ptifddi *root_pti_dev;
20     #endif
21     
22     static inline void pti_reset(struct ptifddi *pp)
23     {
24     	pp->reset = 1;
25     }
26     
27     static inline void pti_unreset(struct ptifddi *pp)
28     {
29     	pp->unreset = 1;
30     }
31     
32     static inline void pti_load_code_base(struct dfddi_ram *rp, unsigned short addr)
33     {
34     	rp->loader_addr = ((addr << 8) & 0xff00) | ((addr >> 8) & 0x00ff);
35     }
36     
37     static inline void pti_clear_dpram(struct ptifddi *pp)
38     {
39     	memset(pp->dpram, 0, DPRAM_SIZE);
40     }
41     
42     #define CARD_TEST_TIMEOUT	100000
43     
44     static inline int pti_card_test(struct ptifddi *pp)
45     {
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;
50     
51     	/* Clear it out. */
52     	pti_clear_dpram(pp);
53     
54     	/* Load test data. */
55     	for(i = 0; i < test_firmware_size; i++)
56     		code[i] = test_firmware[i];
57     
58     	/* Tell card where to execute the code. */
59     	pti_load_code_base(pp, test_firmware_dev_addr);
60     
61     	/* Clear test run status in dpram. */
62     	*status = 0;
63     
64     	/* Reset single attach state machine before the test. */
65     	rp->reset = 1;
66     
67     	/* Unreset, to get the test code running. */
68     	pti_unreset(pp);
69     
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;
75     		}
76     		udelay(20);
77     	}
78     	return 1;
79     }
80     
81     static inline void pti_init_firmware_loader(struct ptifddi *pp)
82     {
83     	struct dfddi_ram *rp = pp->dpram;
84     	int i;
85     
86     	for(i = 0; i < firmware_loader_size; i++)
87     		rp->loader.loader_firmware[i] = firmware_loader[i];
88     }
89     
90     static inline void pti_load_main_firmware(struct ptifddi *pp)
91     {
92     	struct dfddi_ram *rp		= pp->dpram;
93     	struct dpram_loader *lp		= &rp.loader;
94     	int i;
95     
96     
97     }
98     
99     static void pti_init_rings(struct ptifddi *pp, int from_irq)
100     {
101     }
102     
103     static int pti_init(struct ptifddi *pp, int from_irq)
104     {
105     }
106     
107     static void pti_is_not_so_happy(struct ptifddi *pp)
108     {
109     }
110     
111     static inline void pti_tx(struct ptifddi *pp, struct net_device *dev)
112     {
113     }
114     
115     static inline void myri_rx(struct ptifddi *pp, struct net_device *dev)
116     {
117     }
118     
119     static void pti_interrupt(int irq, void *dev_id, struct pt_regs *regs)
120     {
121     	struct net_device *dev		= (struct net_device *) dev_id;
122     	struct ptifddi *pp		= (struct ptifddi *) dev->priv;
123     
124     }
125     
126     static int pti_open(struct net_device *dev)
127     {
128     	struct ptifddi *pp = (struct ptifddi *) dev->priv;
129     
130     	return pti_init(pp, in_interrupt());
131     }
132     
133     static int pti_close(struct net_device *dev)
134     {
135     	struct ptifddi *pp = (struct ptifddi *) dev->priv;
136     
137     	return 0;
138     }
139     
140     static int pti_start_xmit(struct sk_buff *skb, struct net_device *dev)
141     {
142     	struct ptifddi *pp = (struct ptifddi *) dev->priv;
143     }
144     
145     static struct net_device_stats *pti_get_stats(struct net_device *dev)
146     { return &(((struct ptifddi *)dev->priv)->enet_stats); }
147     
148     static void pti_set_multicast(struct net_device *dev)
149     {
150     }
151     
152     static inline int pti_fddi_init(struct net_device *dev, struct sbus_dev *sdev, int num)
153     {
154     	static unsigned version_printed;
155     	struct ptifddi *pp;
156     	int i;
157     
158     	dev = init_fddidev(0, sizeof(struct ptifddi));
159     
160     	if(version_printed++ == 0)
161     		printk(version);
162     
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;
169     	}
170     
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;
177     	}
178     
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;
185     	}
186     
187     	/* Reset the card. */
188     	pti_reset(pp);
189     
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;
195     	}
196     
197     	/* Clear DPRAM, start afresh. */
198     	pti_clear_dpram(pp);
199     
200     	/* Init the firmware loader. */
201     	pti_init_firmware_loader(pp);
202     
203     	/* Now load main card FDDI firmware, using the loader. */
204     	pti_load_main_firmware(pp);
205     }
206     
207     int __init ptifddi_sbus_probe(struct net_device *dev)
208     {
209     	struct sbus_bus *bus;
210     	struct sbus_dev *sdev = 0;
211     	static int called;
212     	int cards = 0, v;
213     
214     	if(called)
215     		return -ENODEV;
216     	called++;
217     
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;
227     			}
228     		}
229     	}
230     	if(!cards)
231     		return -ENODEV;
232     	return 0;
233     }
234     
235     
236     #ifdef MODULE
237     
238     int
239     init_module(void)
240     {
241     	root_pti_dev = NULL;
242     	return ptifddi_sbus_probe(NULL);
243     }
244     
245     void
246     cleanup_module(void)
247     {
248     	struct ptifddi *pp;
249     
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;
253     
254     		unregister_netdev(root_pti_dev->dev);
255     		kfree(root_pti_dev->dev);
256     		root_pti_dev = mp;
257     	}
258     }
259     
260     #endif /* MODULE */
261