1 /* skeleton.c: A sample network driver core for linux. */
2 /*
3 Written 1993 by Donald Becker.
4 Copyright 1993 United States Government as represented by the Director,
5 National Security Agency. This software may only be used and distributed
6 according to the terms of the GNU Public License as modified by SRC,
7 incorporated herein by reference.
8
9 The author may be reached as becker@super.org or
10 C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
11
12 This file is an outline for writing a network device driver for the
13 the Linux operating system.
14
15 To write (or understand) a driver, have a look at the "loopback.c" file to
16 get a feel of what is going on, and then use the code below as a skeleton
17 for the new driver.
18
19 */
20
21 static char *version =
22 "skeleton.c:v0.05 11/16/93 Donald Becker (becker@super.org)\n";
23
24 /* Always include 'config.h' first in case the user wants to turn on
25 or override something. */
26 #include <linux/config.h>
27
28 /*
29 Sources:
30 List your sources of programming information to document that
31 the driver is your own creation, and give due credit to others
32 that contributed to the work. Remember that GNU project code
33 cannot use proprietary or trade secret information. Interface
34 definitions are generally considered non-copyrightable to the
35 extent that the same names and structures must be used to be
36 compatible.
37
38 Finally, keep in mind that the Linux kernel is has an API, not
39 ABI. Proprietary object-code-only distributions are not permitted
40 under the GPL.
41 */
42
43 #include <linux/kernel.h>
44 #include <linux/sched.h>
45 #include <linux/types.h>
46 #include <linux/fcntl.h>
47 #include <linux/interrupt.h>
48 #include <linux/ptrace.h>
49 #include <linux/ioport.h>
50 #include <linux/in.h>
51 #include <linux/malloc.h>
52 #include <linux/string.h>
53 #include <asm/system.h>
54 #include <asm/bitops.h>
55 #include <asm/io.h>
56 #include <asm/dma.h>
57 #include <errno.h>
58
59 #include <linux/netdevice.h>
60 #include <linux/etherdevice.h>
61 #include <linux/skbuff.h>
62
63 #ifndef HAVE_AUTOIRQ
64 /* From auto_irq.c, in ioport.h for later versions. */
65 extern void autoirq_setup(int waittime);
66 extern int autoirq_report(int waittime);
67 /* The map from IRQ number (as passed to the interrupt handler) to
68 'struct device'. */
69 extern struct device *irq2dev_map[16];
70 #endif
71
72 #ifndef HAVE_PORTRESERVE
73 #define check_region(ioaddr, size) 0
74 #define snarf_region(ioaddr, size); do ; while (0)
75 #endif
76
77 /* use 0 for production, 1 for verification, >2 for debug */
78 #ifndef NET_DEBUG
79 #define NET_DEBUG 2
80 #endif
81 static unsigned int net_debug = NET_DEBUG;
82
83 /* Information that need to be kept for each board. */
84 struct net_local {
85 struct enet_statistics stats;
86 long open_time; /* Useless example local info. */
87 };
88
89 /* The number of low I/O ports used by the ethercard. */
90 #define ETHERCARD_TOTAL_SIZE 16
91
92 /* The station (ethernet) address prefix, used for IDing the board. */
93 #define SA_ADDR0 0x00
94 #define SA_ADDR1 0x42
95 #define SA_ADDR2 0x65
96
97 /* Index to functions, as function prototypes. */
98
99 extern int netcard_probe(struct device *dev);
100
101 static int netcard_probe1(struct device *dev, short ioaddr);
102 static int net_open(struct device *dev);
103 static int net_send_packet(struct sk_buff *skb, struct device *dev);
104 static void net_interrupt(int reg_ptr);
105 static void net_rx(struct device *dev);
106 static int net_close(struct device *dev);
107 static struct enet_statistics *net_get_stats(struct device *dev);
108 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
109
110 /* Example routines you must write ;->. */
111 #define tx_done(dev) 1
112 extern void hardware_send_packet(short ioaddr, char *buf, int length);
113 extern void chipset_init(struct device *dev, int startp);
114
115
116 /* Check for a network adaptor of this type, and return '0' iff one exists.
117 If dev->base_addr == 0, probe all likely locations.
118 If dev->base_addr == 1, always return failure.
119 If dev->base_addr == 2, alloate space for the device and return success
120 (detachable devices only).
121 */
122 int
123 netcard_probe(struct device *dev)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
124 {
125 int *port, ports[] = {0x300, 0x280, 0};
126 int base_addr = dev->base_addr;
127
128 if (base_addr > 0x1ff) /* Check a single specified location. */
129 return netcard_probe1(dev, base_addr);
130 else if (base_addr > 0) /* Don't probe at all. */
131 return ENXIO;
132
133 for (port = &ports[0]; *port; port++) {
134 int ioaddr = *port;
135 if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE))
136 continue;
137 if (inb(ioaddr) != 0x57)
138 continue;
139 dev->base_addr = ioaddr;
140 if (netcard_probe1(dev, ioaddr) == 0)
141 return 0;
142 }
143
144 dev->base_addr = base_addr;
145 return ENODEV;
146 }
147
148 int netcard_probe1(struct device *dev, short ioaddr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
149 {
150 unsigned char station_addr[6];
151 int i;
152
153 /* Read the station address PROM. */
154 for (i = 0; i < 6; i++) {
155 station_addr[i] = inb(ioaddr + i);
156 }
157 /* Check the first three octets of the S.A. for the manufactor's code. */
158 if (station_addr[0] != SA_ADDR0
159 || station_addr[1] != SA_ADDR1 || station_addr[2] != SA_ADDR2) {
160 return ENODEV;
161 }
162
163 printk("%s: %s found at %#3x, IRQ %d.\n", dev->name,
164 "network card", dev->base_addr, dev->irq);
165
166 #ifdef jumpered_interrupts
167 /* If this board has jumpered interrupts, snarf the interrupt vector
168 now. There is no point in waiting since no other device can use
169 the interrupt, and this marks the 'irqaction' as busy. */
170
171 if (dev->irq == -1)
172 ; /* Do nothing: a user-level program will set it. */
173 else if (dev->irq < 2) { /* "Auto-IRQ" */
174 autoirq_setup(0);
175 /* Trigger an interrupt here. */
176
177 dev->irq = autoirq_report(0);
178 if (net_debug >= 2)
179 printk(" autoirq is %d", dev->irq);
180 } else if (dev->irq == 2)
181 /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
182 or don't know which one to set. */
183 dev->irq = 9;
184
185 { int irqval = request_irq(dev->irq, &net_interrupt);
186 if (irqval) {
187 printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
188 dev->irq, irqval);
189 return EAGAIN;
190 }
191 }
192 #endif /* jumpered interrupt */
193
194 /* Grab the region so we can find another board if autoIRQ fails. */
195 snarf_region(ioaddr, ETHERCARD_TOTAL_SIZE);
196
197 if (net_debug)
198 printk(version);
199
200 /* Initialize the device structure. */
201 dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
202 memset(dev->priv, 0, sizeof(struct net_local));
203
204 dev->open = net_open;
205 dev->stop = net_close;
206 dev->hard_start_xmit = net_send_packet;
207 dev->get_stats = net_get_stats;
208 dev->set_multicast_list = &set_multicast_list;
209
210 /* Fill in the fields of the device structure with ethernet-generic values. */
211
212 ether_setup(dev);
213
214 return 0;
215 }
216
217
218 /* Open/initialize the board. This is called (in the current kernel)
219 sometime after booting when the 'ifconfig' program is run.
220
221 This routine should set everything up anew at each open, even
222 registers that "should" only need to be set once at boot, so that
223 there is non-reboot way to recover if something goes wrong.
224 */
225 static int
226 net_open(struct device *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
227 {
228 struct net_local *lp = (struct net_local *)dev->priv;
229 int ioaddr = dev->base_addr;
230
231 /* This is used if the interrupt line can turned off (shared).
232 See 3c503.c for an example of selecting the IRQ at config-time. */
233 if (request_irq(dev->irq, &net_interrupt)) {
234 return -EAGAIN;
235 }
236
237
238 /* Always snarf a DMA channel after the IRQ. */
239 if (request_dma(dev->dma)) {
240 free_irq(dev->irq);
241 return -EAGAIN;
242 }
243 irq2dev_map[dev->irq] = dev;
244
245 /* Reset the hardware here. */
246 /*chipset_init(dev, 1);*/
247 outb(0x00, ioaddr);
248 lp->open_time = jiffies;
249
250 dev->tbusy = 0;
251 dev->interrupt = 0;
252 dev->start = 1;
253 return 0;
254 }
255
256 static int
257 net_send_packet(struct sk_buff *skb, struct device *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
258 {
259 struct net_local *lp = (struct net_local *)dev->priv;
260 int ioaddr = dev->base_addr;
261
262 if (dev->tbusy) {
263 /* If we get here, some higher level has decided we are broken.
264 There should really be a "kick me" function call instead. */
265 int tickssofar = jiffies - dev->trans_start;
266 if (tickssofar < 5)
267 return 1;
268 printk("%s: transmit timed out, %s?\n", dev->name,
269 tx_done(dev) ? "IRQ conflict" : "network cable problem");
270 /* Try to restart the adaptor. */
271 chipset_init(dev, 1);
272 dev->tbusy=0;
273 dev->trans_start = jiffies;
274 }
275
276 /* If some higher layer thinks we've missed an tx-done interrupt
277 we are passed NULL. Caution: dev_tint() handles the cli()/sti()
278 itself. */
279 if (skb == NULL) {
280 dev_tint(dev);
281 return 0;
282 }
283
284 /* Block a timer-based transmit from overlapping. This could better be
285 done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
286 if (set_bit(0, (void*)&dev->tbusy) != 0)
287 printk("%s: Transmitter access conflict.\n", dev->name);
288 else {
289 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
290 unsigned char *buf = skb->data;
291
292 hardware_send_packet(ioaddr, buf, length);
293 dev->trans_start = jiffies;
294 }
295 dev_kfree_skb (skb, FREE_WRITE);
296
297 /* You might need to clean up and record Tx statistics here. */
298 if (inw(ioaddr) == /*RU*/81)
299 lp->stats.tx_aborted_errors++;
300
301 return 0;
302 }
303
304 /* The typical workload of the driver:
305 Handle the network interface interrupts. */
306 static void
307 net_interrupt(int reg_ptr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
308 {
309 int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
310 struct device *dev = (struct device *)(irq2dev_map[irq]);
311 struct net_local *lp;
312 int ioaddr, status, boguscount = 0;
313
314 if (dev == NULL) {
315 printk ("net_interrupt(): irq %d for unknown device.\n", irq);
316 return;
317 }
318 dev->interrupt = 1;
319
320 ioaddr = dev->base_addr;
321 lp = (struct net_local *)dev->priv;
322 status = inw(ioaddr + 0);
323
324 do {
325 if (status /*& RX_INTR*/) {
326 /* Got a packet(s). */
327 net_rx(dev);
328 }
329 if (status /*& TX_INTR*/) {
330 lp->stats.tx_packets++;
331 dev->tbusy = 0;
332 mark_bh(NET_BH); /* Inform upper layers. */
333 }
334 if (status /*& COUNTERS_INTR*/) {
335 /* Increment the appropriate 'localstats' field. */
336 lp->stats.tx_window_errors++;
337 }
338 } while (++boguscount < 20) ;
339
340 return;
341 }
342
343 /* We have a good packet(s), get it/them out of the buffers. */
344 static void
345 net_rx(struct device *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
346 {
347 struct net_local *lp = (struct net_local *)dev->priv;
348 int ioaddr = dev->base_addr;
349 int boguscount = 10;
350
351 do {
352 int status = inw(ioaddr);
353 int pkt_len = inw(ioaddr);
354
355 if (pkt_len == 0) /* Read all the frames? */
356 break; /* Done for now */
357
358 if (status & 0x40) { /* There was an error. */
359 lp->stats.rx_errors++;
360 if (status & 0x20) lp->stats.rx_frame_errors++;
361 if (status & 0x10) lp->stats.rx_over_errors++;
362 if (status & 0x08) lp->stats.rx_crc_errors++;
363 if (status & 0x04) lp->stats.rx_fifo_errors++;
364 } else {
365 /* Malloc up new buffer. */
366 struct sk_buff *skb;
367
368 skb = alloc_skb(pkt_len, GFP_ATOMIC);
369 if (skb == NULL) {
370 printk("%s: Memory squeeze, dropping packet.\n", dev->name);
371 lp->stats.rx_dropped++;
372 break;
373 }
374 skb->len = pkt_len;
375 skb->dev = dev;
376
377 /* 'skb->data' points to the start of sk_buff data area. */
378 memcpy(skb->data, (void*)dev->rmem_start,
379 pkt_len);
380 /* or */
381 insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
382
383 netif_rx(skb);
384 lp->stats.rx_packets++;
385 }
386 } while (--boguscount);
387
388 /* If any worth-while packets have been received, dev_rint()
389 has done a mark_bh(NET_BH) for us and will work on them
390 when we get to the bottom-half routine. */
391 return;
392 }
393
394 /* The inverse routine to net_open(). */
395 static int
396 net_close(struct device *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
397 {
398 struct net_local *lp = (struct net_local *)dev->priv;
399 int ioaddr = dev->base_addr;
400
401 lp->open_time = 0;
402
403 dev->tbusy = 1;
404 dev->start = 0;
405
406 /* Flush the Tx and disable Rx here. */
407
408 disable_dma(dev->dma);
409
410 /* If not IRQ or DMA jumpered, free up the line. */
411 outw(0x00, ioaddr+0); /* Release the physical interrupt line. */
412
413 free_irq(dev->irq);
414 free_dma(dev->dma);
415
416 irq2dev_map[dev->irq] = 0;
417
418 /* Update the statistics here. */
419
420 return 0;
421
422 }
423
424 /* Get the current statistics. This may be called with the card open or
425 closed. */
426 static struct enet_statistics *
427 net_get_stats(struct device *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
428 {
429 struct net_local *lp = (struct net_local *)dev->priv;
430 short ioaddr = dev->base_addr;
431
432 cli();
433 /* Update the statistics from the device registers. */
434 lp->stats.rx_missed_errors = inw(ioaddr+1);
435 sti();
436
437 return &lp->stats;
438 }
439
440 /* Set or clear the multicast filter for this adaptor.
441 num_addrs == -1 Promiscuous mode, receive all packets
442 num_addrs == 0 Normal mode, clear multicast list
443 num_addrs > 0 Multicast mode, receive normal and MC packets, and do
444 best-effort filtering.
445 */
446 static void
447 set_multicast_list(struct device *dev, int num_addrs, void *addrs)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
448 {
449 short ioaddr = dev->base_addr;
450 if (num_addrs) {
451 outw(69, ioaddr); /* Enable promiscuous mode */
452 } else
453 outw(99, ioaddr); /* Disable promiscuous mode, use normal mode */
454 }
455
456 /*
457 * Local variables:
458 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c"
459 * version-control: t
460 * kept-new-versions: 5
461 * tab-width: 4
462 * End:
463 */