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 staticchar *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 #ifndefHAVE_AUTOIRQ 64 /* From auto_irq.c, in ioport.h for later versions. */ 65 externvoidautoirq_setup(intwaittime);
66 externintautoirq_report(intwaittime);
67 /* The map from IRQ number (as passed to the interrupt handler) to 68 'struct device'. */ 69 externstructdevice *irq2dev_map[16];
70 #endif 71
72 #ifndefHAVE_PORTRESERVE 73 #definecheck_region(ioaddr, size) 0
74 #definesnarf_region(ioaddr, size); do ; while (0)
75 #endif 76
77 /* use 0 for production, 1 for verification, >2 for debug */ 78 #ifndefNET_DEBUG 79 #defineNET_DEBUG 2
80 #endif 81 staticunsignedintnet_debug = NET_DEBUG;
82
83 /* Information that need to be kept for each board. */ 84 structnet_local{ 85 structenet_statisticsstats;
86 longopen_time; /* Useless example local info. */ 87 };
88
89 /* The number of low I/O ports used by the ethercard. */ 90 #defineETHERCARD_TOTAL_SIZE 16
91
92 /* The station (ethernet) address prefix, used for IDing the board. */ 93 #defineSA_ADDR0 0x00
94 #defineSA_ADDR1 0x42
95 #defineSA_ADDR2 0x65
96
97 /* Index to functions, as function prototypes. */ 98
99 externintnetcard_probe(structdevice *dev);
100
101 staticintnetcard_probe1(structdevice *dev, shortioaddr);
102 staticintnet_open(structdevice *dev);
103 staticintnet_send_packet(structsk_buff *skb, structdevice *dev);
104 staticvoidnet_interrupt(intreg_ptr);
105 staticvoidnet_rx(structdevice *dev);
106 staticintnet_close(structdevice *dev);
107 staticstructenet_statistics *net_get_stats(structdevice *dev);
108 staticvoidset_multicast_list(structdevice *dev, intnum_addrs, void *addrs);
109
110 /* Example routines you must write ;->. */ 111 #definetx_done(dev) 1
112 externvoidhardware_send_packet(shortioaddr, char *buf, intlength);
113 externvoidchipset_init(structdevice *dev, intstartp);
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(structdevice *dev)
/* */ 124 { 125 int *port, ports[] = {0x300, 0x280, 0};
126 intbase_addr = dev->base_addr;
127
128 if (base_addr > 0x1ff) /* Check a single specified location. */ 129 returnnetcard_probe1(dev, base_addr);
130 elseif (base_addr > 0) /* Don't probe at all. */ 131 returnENXIO;
132
133 for (port = &ports[0]; *port; port++) { 134 intioaddr = *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 returnENODEV;
146 } 147
148 intnetcard_probe1(structdevice *dev, shortioaddr)
/* */ 149 { 150 unsignedcharstation_addr[6];
151 inti;
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 returnENODEV;
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 elseif (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 }elseif (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 {intirqval = 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 returnEAGAIN;
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(structnet_local), GFP_KERNEL);
202 memset(dev->priv, 0, sizeof(structnet_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 staticint 226 net_open(structdevice *dev)
/* */ 227 { 228 structnet_local *lp = (structnet_local *)dev->priv;
229 intioaddr = 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 staticint 257 net_send_packet(structsk_buff *skb, structdevice *dev)
/* */ 258 { 259 structnet_local *lp = (structnet_local *)dev->priv;
260 intioaddr = 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 inttickssofar = 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 shortlength = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
290 unsignedchar *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 staticvoid 307 net_interrupt(intreg_ptr)
/* */ 308 { 309 intirq = -(((structpt_regs *)reg_ptr)->orig_eax+2);
310 structdevice *dev = (structdevice *)(irq2dev_map[irq]);
311 structnet_local *lp;
312 intioaddr, 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 = (structnet_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 staticvoid 345 net_rx(structdevice *dev)
/* */ 346 { 347 structnet_local *lp = (structnet_local *)dev->priv;
348 intioaddr = dev->base_addr;
349 intboguscount = 10;
350
351 do{ 352 intstatus = inw(ioaddr);
353 intpkt_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 structsk_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 staticint 396 net_close(structdevice *dev)
/* */ 397 { 398 structnet_local *lp = (structnet_local *)dev->priv;
399 intioaddr = 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 staticstructenet_statistics *
427 net_get_stats(structdevice *dev)
/* */ 428 { 429 structnet_local *lp = (structnet_local *)dev->priv;
430 shortioaddr = 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 staticvoid 447 set_multicast_list(structdevice *dev, intnum_addrs, void *addrs)
/* */ 448 { 449 shortioaddr = 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 */