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 "dev.h"
60 #include "iow.h"
61 #include "eth.h"
62 #include "skbuff.h"
63 #include "arp.h"
64
65 #ifndef HAVE_AUTOIRQ
66 /* From auto_irq.c, in ioport.h for later versions. */
67 extern void autoirq_setup(int waittime);
68 extern int autoirq_report(int waittime);
69 /* The map from IRQ number (as passed to the interrupt handler) to
70 'struct device'. */
71 extern struct device *irq2dev_map[16];
72 #endif
73
74 #ifndef HAVE_ALLOC_SKB
75 #define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority)
76 #define kfree_skbmem(addr, size) kfree_s(addr,size);
77 #endif
78
79 #ifndef HAVE_PORTRESERVE
80 #define check_region(ioaddr, size) 0
81 #define snarf_region(ioaddr, size); do ; while (0)
82 #endif
83
84 /* use 0 for production, 1 for verification, >2 for debug */
85 #ifndef NET_DEBUG
86 #define NET_DEBUG 2
87 #endif
88 static unsigned int net_debug = NET_DEBUG;
89
90 /* Information that need to be kept for each board. */
91 struct net_local {
92 struct enet_statistics stats;
93 long open_time; /* Useless example local info. */
94 };
95
96 /* The number of low I/O ports used by the ethercard. */
97 #define ETHERCARD_TOTAL_SIZE 16
98
99 /* The station (ethernet) address prefix, used for IDing the board. */
100 #define SA_ADDR0 0x00
101 #define SA_ADDR1 0x42
102 #define SA_ADDR2 0x65
103
104 /* Index to functions, as function prototypes. */
105
106 extern int netcard_probe(struct device *dev);
107
108 static int netcard_probe1(struct device *dev, short ioaddr);
109 static int net_open(struct device *dev);
110 static int net_send_packet(struct sk_buff *skb, struct device *dev);
111 static void net_interrupt(int reg_ptr);
112 static void net_rx(struct device *dev);
113 static int net_close(struct device *dev);
114 static struct enet_statistics *net_get_stats(struct device *dev);
115 #ifdef HAVE_MULTICAST
116 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
117 #endif
118
119 /* Example routines you must write ;->. */
120 #define tx_done(dev) 1
121 extern void hardware_send_packet(short ioaddr, char *buf, int length);
122 extern void chipset_init(struct device *dev, int startp);
123
124
125 /* Check for a network adaptor of this type, and return '0' iff one exists.
126 If dev->base_addr == 0, probe all likely locations.
127 If dev->base_addr == 1, always return failure.
128 If dev->base_addr == 2, alloate space for the device and return success
129 (detachable devices only).
130 */
131 int
132 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)
*/
133 {
134 int *port, ports[] = {0x300, 0x280, 0};
135 int base_addr = dev->base_addr;
136
137 if (base_addr > 0x1ff) /* Check a single specified location. */
138 return netcard_probe1(dev, base_addr);
139 else if (base_addr > 0) /* Don't probe at all. */
140 return ENXIO;
141
142 for (port = &ports[0]; *port; port++) {
143 int ioaddr = *port;
144 if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE))
145 continue;
146 if (inb(ioaddr) != 0x57)
147 continue;
148 dev->base_addr = ioaddr;
149 if (netcard_probe1(dev, ioaddr) == 0)
150 return 0;
151 }
152
153 dev->base_addr = base_addr;
154 return ENODEV;
155 }
156
157 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)
*/
158 {
159 unsigned char station_addr[6];
160 int i;
161
162 /* Read the station address PROM. */
163 for (i = 0; i < 6; i++) {
164 station_addr[i] = inb(ioaddr + i);
165 }
166 /* Check the first three octets of the S.A. for the manufactor's code. */
167 if (station_addr[0] != SA_ADDR0
168 || station_addr[1] != SA_ADDR1 || station_addr[2] != SA_ADDR2) {
169 return ENODEV;
170 }
171
172 printk("%s: %s found at %#3x, IRQ %d.\n", dev->name,
173 "network card", dev->base_addr, dev->irq);
174
175 #ifdef jumpered_interrupts
176 /* If this board has jumpered interrupts, snarf the interrupt vector
177 now. There is no point in waiting since no other device can use
178 the interrupt, and this marks the 'irqaction' as busy. */
179
180 if (dev->irq == -1)
181 ; /* Do nothing: a user-level program will set it. */
182 else if (dev->irq < 2) { /* "Auto-IRQ" */
183 autoirq_setup(0);
184 /* Trigger an interrupt here. */
185
186 dev->irq = autoirq_report(0);
187 if (net_debug >= 2)
188 printk(" autoirq is %d", dev->irq);
189 } else if (dev->irq == 2)
190 /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
191 or don't know which one to set. */
192 dev->irq = 9;
193
194 { int irqval = request_irq(dev->irq, &net_interrupt);
195 if (irqval) {
196 printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
197 dev->irq, irqval);
198 return EAGAIN;
199 }
200 }
201 #endif /* jumpered interrupt */
202
203 /* Grab the region so we can find another board if autoIRQ fails. */
204 snarf_region(ioaddr, ETHERCARD_TOTAL_SIZE);
205
206 if (net_debug)
207 printk(version);
208
209 /* Initialize the device structure. */
210 dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
211 memset(dev->priv, 0, sizeof(struct net_local));
212
213 dev->open = net_open;
214 dev->stop = net_close;
215 dev->hard_start_xmit = net_send_packet;
216 dev->get_stats = net_get_stats;
217 #ifdef HAVE_MULTICAST
218 dev->set_multicast_list = &set_multicast_list;
219 #endif
220
221 /* Fill in the fields of the device structure with ethernet-generic values.
222 This should be in a common file instead of per-driver. */
223 for (i = 0; i < DEV_NUMBUFFS; i++)
224 dev->buffs[i] = NULL;
225
226 dev->hard_header = eth_header;
227 dev->add_arp = eth_add_arp;
228 dev->queue_xmit = dev_queue_xmit;
229 dev->rebuild_header = eth_rebuild_header;
230 dev->type_trans = eth_type_trans;
231
232 dev->type = ARPHRD_ETHER;
233 dev->hard_header_len = ETH_HLEN;
234 dev->mtu = 1500; /* eth_mtu */
235 dev->addr_len = ETH_ALEN;
236 for (i = 0; i < ETH_ALEN; i++) {
237 dev->broadcast[i]=0xff;
238 }
239
240 /* New-style flags. */
241 dev->flags = IFF_BROADCAST;
242 dev->family = AF_INET;
243 dev->pa_addr = 0;
244 dev->pa_brdaddr = 0;
245 dev->pa_mask = 0;
246 dev->pa_alen = sizeof(unsigned long);
247
248 return 0;
249 }
250
251
252 /* Open/initialize the board. This is called (in the current kernel)
253 sometime after booting when the 'ifconfig' program is run.
254
255 This routine should set everything up anew at each open, even
256 registers that "should" only need to be set once at boot, so that
257 there is non-reboot way to recover if something goes wrong.
258 */
259 static int
260 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)
*/
261 {
262 struct net_local *lp = (struct net_local *)dev->priv;
263 int ioaddr = dev->base_addr;
264
265 /* This is used if the interrupt line can turned off (shared).
266 See 3c503.c for an example of selecting the IRQ at config-time. */
267 if (request_irq(dev->irq, &net_interrupt)) {
268 return -EAGAIN;
269 }
270
271
272 /* Always snarf a DMA channel after the IRQ. */
273 if (request_dma(dev->dma)) {
274 free_irq(dev->irq);
275 return -EAGAIN;
276 }
277 irq2dev_map[dev->irq] = dev;
278
279 /* Reset the hardware here. */
280 /*chipset_init(dev, 1);*/
281 outb(0x00, ioaddr);
282 lp->open_time = jiffies;
283
284 dev->tbusy = 0;
285 dev->interrupt = 0;
286 dev->start = 1;
287 return 0;
288 }
289
290 static int
291 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)
*/
292 {
293 struct net_local *lp = (struct net_local *)dev->priv;
294 int ioaddr = dev->base_addr;
295
296 if (dev->tbusy) {
297 /* If we get here, some higher level has decided we are broken.
298 There should really be a "kick me" function call instead. */
299 int tickssofar = jiffies - dev->trans_start;
300 if (tickssofar < 5)
301 return 1;
302 printk("%s: transmit timed out, %s?\n", dev->name,
303 tx_done(dev) ? "IRQ conflict" : "network cable problem");
304 /* Try to restart the adaptor. */
305 chipset_init(dev, 1);
306 dev->tbusy=0;
307 dev->trans_start = jiffies;
308 }
309
310 /* If some higher layer thinks we've missed an tx-done interrupt
311 we are passed NULL. Caution: dev_tint() handles the cli()/sti()
312 itself. */
313 if (skb == NULL) {
314 dev_tint(dev);
315 return 0;
316 }
317
318 /* For ethernet, fill in the header. This should really be done by a
319 higher level, rather than duplicated for each ethernet adaptor. */
320 if (!skb->arp && dev->rebuild_header(skb+1, dev)) {
321 skb->dev = dev;
322 arp_queue (skb);
323 return 0;
324 }
325 skb->arp=1;
326
327 /* Block a timer-based transmit from overlapping. This could better be
328 done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
329 if (set_bit(0, (void*)&dev->tbusy) != 0)
330 printk("%s: Transmitter access conflict.\n", dev->name);
331 else {
332 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
333 unsigned char *buf = (void *)(skb+1);
334
335 hardware_send_packet(ioaddr, buf, length);
336 dev->trans_start = jiffies;
337 }
338 if (skb->free)
339 kfree_skb (skb, FREE_WRITE);
340
341 /* You might need to clean up and record Tx statistics here. */
342 if (inw(ioaddr) == /*RU*/81)
343 lp->stats.tx_aborted_errors++;
344
345 return 0;
346 }
347
348 /* The typical workload of the driver:
349 Handle the network interface interrupts. */
350 static void
351 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)
*/
352 {
353 int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
354 struct device *dev = (struct device *)(irq2dev_map[irq]);
355 struct net_local *lp;
356 int ioaddr, status, boguscount = 0;
357
358 if (dev == NULL) {
359 printk ("net_interrupt(): irq %d for unknown device.\n", irq);
360 return;
361 }
362 dev->interrupt = 1;
363
364 ioaddr = dev->base_addr;
365 lp = (struct net_local *)dev->priv;
366 status = inw(ioaddr + 0);
367
368 do {
369 if (status /*& RX_INTR*/) {
370 /* Got a packet(s). */
371 net_rx(dev);
372 }
373 if (status /*& TX_INTR*/) {
374 lp->stats.tx_packets++;
375 dev->tbusy = 0;
376 mark_bh(INET_BH); /* Inform upper layers. */
377 }
378 if (status /*& COUNTERS_INTR*/) {
379 /* Increment the appropriate 'localstats' field. */
380 lp->stats.tx_window_errors++;
381 }
382 } while (++boguscount < 20) ;
383
384 return;
385 }
386
387 /* We have a good packet(s), get it/them out of the buffers. */
388 static void
389 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)
*/
390 {
391 struct net_local *lp = (struct net_local *)dev->priv;
392 int ioaddr = dev->base_addr;
393 int boguscount = 10;
394
395 do {
396 int status = inw(ioaddr);
397 int pkt_len = inw(ioaddr);
398
399 if (pkt_len == 0) /* Read all the frames? */
400 break; /* Done for now */
401
402 if (status & 0x40) { /* There was an error. */
403 lp->stats.rx_errors++;
404 if (status & 0x20) lp->stats.rx_frame_errors++;
405 if (status & 0x10) lp->stats.rx_over_errors++;
406 if (status & 0x08) lp->stats.rx_crc_errors++;
407 if (status & 0x04) lp->stats.rx_fifo_errors++;
408 } else {
409 /* Malloc up new buffer. */
410 int sksize = sizeof(struct sk_buff) + pkt_len;
411 struct sk_buff *skb;
412
413 skb = alloc_skb(sksize, GFP_ATOMIC);
414 if (skb == NULL) {
415 printk("%s: Memory squeeze, dropping packet.\n", dev->name);
416 lp->stats.rx_dropped++;
417 break;
418 }
419 skb->mem_len = sksize;
420 skb->mem_addr = skb;
421 skb->len = pkt_len;
422 skb->dev = dev;
423
424 /* 'skb+1' points to the start of sk_buff data area. */
425 memcpy((unsigned char *) (skb + 1), (void*)dev->rmem_start,
426 pkt_len);
427 /* or */
428 port_read(ioaddr, (void *)(skb+1), (pkt_len + 1) >> 1);
429
430 #ifdef HAVE_NETIF_RX
431 netif_rx(skb);
432 #else
433 skb->lock = 0;
434 if (dev_rint((unsigned char*)skb, pkt_len, IN_SKBUFF, dev) != 0) {
435 kfree_s(skb, sksize);
436 lp->stats.rx_dropped++;
437 break;
438 }
439 #endif
440 lp->stats.rx_packets++;
441 }
442 } while (--boguscount);
443
444 /* If any worth-while packets have been received, dev_rint()
445 has done a mark_bh(INET_BH) for us and will work on them
446 when we get to the bottom-half routine. */
447 return;
448 }
449
450 /* The inverse routine to net_open(). */
451 static int
452 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)
*/
453 {
454 struct net_local *lp = (struct net_local *)dev->priv;
455 int ioaddr = dev->base_addr;
456
457 lp->open_time = 0;
458
459 dev->tbusy = 1;
460 dev->start = 0;
461
462 /* Flush the Tx and disable Rx here. */
463
464 disable_dma(dev->dma);
465
466 /* If not IRQ or DMA jumpered, free up the line. */
467 outw(0x00, ioaddr+0); /* Release the physical interrupt line. */
468
469 free_irq(dev->irq);
470 free_dma(dev->dma);
471
472 irq2dev_map[dev->irq] = 0;
473
474 /* Update the statistics here. */
475
476 return 0;
477
478 }
479
480 /* Get the current statistics. This may be called with the card open or
481 closed. */
482 static struct enet_statistics *
483 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)
*/
484 {
485 struct net_local *lp = (struct net_local *)dev->priv;
486 short ioaddr = dev->base_addr;
487
488 cli();
489 /* Update the statistics from the device registers. */
490 lp->stats.rx_missed_errors = inw(ioaddr+1);
491 sti();
492
493 return &lp->stats;
494 }
495
496 #ifdef HAVE_MULTICAST
497 /* Set or clear the multicast filter for this adaptor.
498 num_addrs == -1 Promiscuous mode, receive all packets
499 num_addrs == 0 Normal mode, clear multicast list
500 num_addrs > 0 Multicast mode, receive normal and MC packets, and do
501 best-effort filtering.
502 */
503 static void
504 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)
*/
505 {
506 short ioaddr = dev->base_addr;
507 if (num_addrs) {
508 outw(69, ioaddr); /* Enable promiscuous mode */
509 } else
510 outw(99, ioaddr); /* Disable promiscuous mode, use normal mode */
511 }
512 #endif
513
514 /*
515 * Local variables:
516 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c"
517 * version-control: t
518 * kept-new-versions: 5
519 * tab-width: 4
520 * End:
521 */