1 /* skeleton.c: A network driver outline for linux. */ 2 /* 3 Written 1993-94 by Donald Becker. 4
5 Copyright 1993 United States Government as represented by the 6 Director, National Security Agency. 7
8 This software may be used and distributed according to the terms 9 of the GNU Public License, incorporated herein by reference. 10
11 The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O 12 Center of Excellence in Space Data and Information Sciences 13 Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 14
15 This file is an outline for writing a network device driver for the 16 the Linux operating system. 17
18 To write (or understand) a driver, have a look at the "loopback.c" file to 19 get a feel of what is going on, and then use the code below as a skeleton 20 for the new driver. 21
22 */ 23
24 staticchar *version =
25 "skeleton.c:v1.51 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
26
27 /* Always include 'config.h' first in case the user wants to turn on 28 or override something. */ 29 #include <linux/config.h>
30
31 /* 32 Sources: 33 List your sources of programming information to document that 34 the driver is your own creation, and give due credit to others 35 that contributed to the work. Remember that GNU project code 36 cannot use proprietary or trade secret information. Interface 37 definitions are generally considered non-copyrightable to the 38 extent that the same names and structures must be used to be 39 compatible. 40
41 Finally, keep in mind that the Linux kernel is has an API, not 42 ABI. Proprietary object-code-only distributions are not permitted 43 under the GPL. 44 */ 45
46 #include <linux/kernel.h>
47 #include <linux/sched.h>
48 #include <linux/types.h>
49 #include <linux/fcntl.h>
50 #include <linux/interrupt.h>
51 #include <linux/ptrace.h>
52 #include <linux/ioport.h>
53 #include <linux/in.h>
54 #include <linux/malloc.h>
55 #include <linux/string.h>
56 #include <asm/system.h>
57 #include <asm/bitops.h>
58 #include <asm/io.h>
59 #include <asm/dma.h>
60 #include <linux/errno.h>
61
62 #include <linux/netdevice.h>
63 #include <linux/etherdevice.h>
64 #include <linux/skbuff.h>
65 externstructdevice *init_etherdev(structdevice *dev, intsizeof_private,
66 unsignedlong *mem_startp);
67
68 /* First, a few definitions that the brave might change. */ 69 /* A zero-terminated list of I/O addresses to be probed. */ 70 staticunsignedintnetcard_portlist[] =
71 { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
72
73 /* use 0 for production, 1 for verification, >2 for debug */ 74 #ifndefNET_DEBUG 75 #defineNET_DEBUG 2
76 #endif 77 staticunsignedintnet_debug = NET_DEBUG;
78
79 /* The number of low I/O ports used by the ethercard. */ 80 #defineNETCARD_IO_EXTENT 32
81
82 /* Information that need to be kept for each board. */ 83 structnet_local{ 84 structenet_statisticsstats;
85 longopen_time; /* Useless example local info. */ 86 };
87
88 /* The station (ethernet) address prefix, used for IDing the board. */ 89 #defineSA_ADDR0 0x00
90 #defineSA_ADDR1 0x42
91 #defineSA_ADDR2 0x65
92
93 /* Index to functions, as function prototypes. */ 94
95 externintnetcard_probe(structdevice *dev);
96
97 staticintnetcard_probe1(structdevice *dev, intioaddr);
98 staticintnet_open(structdevice *dev);
99 staticintnet_send_packet(structsk_buff *skb, structdevice *dev);
100 staticvoidnet_interrupt(intreg_ptr);
101 staticvoidnet_rx(structdevice *dev);
102 staticintnet_close(structdevice *dev);
103 staticstructenet_statistics *net_get_stats(structdevice *dev);
104 staticvoidset_multicast_list(structdevice *dev, intnum_addrs, void *addrs);
105
106 /* Example routines you must write ;->. */ 107 #definetx_done(dev) 1
108 externvoidhardware_send_packet(shortioaddr, char *buf, intlength);
109 externvoidchipset_init(structdevice *dev, intstartp);
110
111
112 /* Check for a network adaptor of this type, and return '0' iff one exists. 113 If dev->base_addr == 0, probe all likely locations. 114 If dev->base_addr == 1, always return failure. 115 If dev->base_addr == 2, allocate space for the device and return success 116 (detachable devices only). 117 */ 118 #ifdefHAVE_DEVLIST 119 /* Support for a alternate probe manager, which will eliminate the 120 boilerplate below. */ 121 structnetdev_entrynetcard_drv =
122 {"netcard", netcard_probe1, NETCARD_IO_EXTENT, netcard_portlist};
123 #else 124 int 125 netcard_probe(structdevice *dev)
/* */ 126 { 127 inti;
128 intbase_addr = dev ? dev->base_addr : 0;
129
130 if (base_addr > 0x1ff) /* Check a single specified location. */ 131 returnnetcard_probe1(dev, base_addr);
132 elseif (base_addr != 0) /* Don't probe at all. */ 133 returnENXIO;
134
135 for (i = 0; netcard_portlist[i]; i++) { 136 intioaddr = netcard_portlist[i];
137 if (check_region(ioaddr, NETCARD_IO_EXTENT))
138 continue;
139 if (netcard_probe1(dev, ioaddr) == 0)
140 return 0;
141 } 142
143 returnENODEV;
144 } 145 #endif 146
147 /* This is the real probe routine. Linux has a history of friendly device 148 probes on the ISA bus. A good device probes avoids doing writes, and 149 verifies that the correct device exists and functions. */ 150
151 staticintnetcard_probe1(structdevice *dev, intioaddr)
/* */ 152 { 153 staticunsignedversion_printed = 0;
154 inti;
155
156 /* For ethernet adaptors the first three octets of the station address contains 157 the manufacturer's unique code. That might be a good probe method. 158 Ideally you would add additional checks. */ 159 if (inb(ioaddr + 0) != SA_ADDR0 160 || inb(ioaddr + 1) != SA_ADDR1 161 || inb(ioaddr + 2) != SA_ADDR2) { 162 returnENODEV;
163 } 164
165 /* Allocate a new 'dev' if needed. */ 166 if (dev == NULL)
167 dev = init_etherdev(0, sizeof(structnet_local), 0);
168
169 if (net_debug && version_printed++ == 0)
170 printk(version);
171
172 printk("%s: %s found at %#3x, ", dev->name, "network card", ioaddr);
173
174 /* Fill in the 'dev' fields. */ 175 dev->base_addr = ioaddr;
176
177 /* Retrieve and print the ethernet address. */ 178 for (i = 0; i < 6; i++)
179 printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
180
181 #ifdef jumpered_interrupts
182 /* If this board has jumpered interrupts, snarf the interrupt vector 183 now. There is no point in waiting since no other device can use 184 the interrupt, and this marks the irq as busy. 185 Jumpered interrupts are typically not reported by the boards, and 186 we must used autoIRQ to find them. */ 187
188 if (dev->irq == -1)
189 ; /* Do nothing: a user-level program will set it. */ 190 elseif (dev->irq < 2) {/* "Auto-IRQ" */ 191 autoirq_setup(0);
192 /* Trigger an interrupt here. */ 193
194 dev->irq = autoirq_report(0);
195 if (net_debug >= 2)
196 printk(" autoirq is %d", dev->irq);
197 }elseif (dev->irq == 2)
198 /* Fixup for users that don't know that IRQ 2 is really IRQ 9, 199 or don't know which one to set. */ 200 dev->irq = 9;
201
202 {intirqval = request_irq(dev->irq, &net_interrupt, 0, "skeleton");
203 if (irqval) { 204 printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
205 dev->irq, irqval);
206 returnEAGAIN;
207 } 208 } 209 #endif/* jumpered interrupt */ 210 #ifdef jumpered_dma
211 /* If we use a jumpered DMA channel, that should be probed for and 212 allocated here as well. See lance.c for an example. */ 213 if (dev->dma == 0) { 214 if (request_dma(dev->dma, "netcard")) { 215 printk("DMA %d allocation failed.\n", dev->dma);
216 returnEAGAIN;
217 }else 218 printk(", assigned DMA %d.\n", dev->dma);
219 }else{ 220 shortdma_status, new_dma_status;
221
222 /* Read the DMA channel status registers. */ 223 dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
224 (inb(DMA2_STAT_REG) & 0xf0);
225 /* Trigger a DMA request, perhaps pause a bit. */ 226 outw(0x1234, ioaddr + 8);
227 /* Re-read the DMA status registers. */ 228 new_dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
229 (inb(DMA2_STAT_REG) & 0xf0);
230 /* Eliminate the old and floating requests and DMA4, the cascade. */ 231 new_dma_status ^= dma_status;
232 new_dma_status &= ~0x10;
233 for (i = 7; i > 0; i--)
234 if (test_bit(new_dma, &new_dma_status)) { 235 dev->dma = i;
236 break;
237 } 238 if (i <= 0) { 239 printk("DMA probe failed.\n");
240 returnEAGAIN;
241 } 242 if (request_dma(dev->dma, "netcard")) { 243 printk("probed DMA %d allocation failed.\n", dev->dma);
244 returnEAGAIN;
245 } 246 } 247 #endif/* jumpered DMA */ 248
249 /* Grab the region so we can find another board if autoIRQ fails. */ 250 snarf_region(ioaddr, NETCARD_IO_EXTENT);
251
252 /* Initialize the device structure. */ 253 if (dev->priv == NULL)
254 dev->priv = kmalloc(sizeof(structnet_local), GFP_KERNEL);
255 memset(dev->priv, 0, sizeof(structnet_local));
256
257 dev->open = net_open;
258 dev->stop = net_close;
259 dev->hard_start_xmit = net_send_packet;
260 dev->get_stats = net_get_stats;
261 dev->set_multicast_list = &set_multicast_list;
262
263 /* Fill in the fields of the device structure with ethernet values. */ 264 ether_setup(dev);
265
266 return 0;
267 } 268
269
270 /* Open/initialize the board. This is called (in the current kernel) 271 sometime after booting when the 'ifconfig' program is run. 272
273 This routine should set everything up anew at each open, even 274 registers that "should" only need to be set once at boot, so that 275 there is non-reboot way to recover if something goes wrong. 276 */ 277 staticint 278 net_open(structdevice *dev)
/* */ 279 { 280 structnet_local *lp = (structnet_local *)dev->priv;
281 intioaddr = dev->base_addr;
282
283 /* This is used if the interrupt line can turned off (shared). 284 See 3c503.c for an example of selecting the IRQ at config-time. */ 285 if (request_irq(dev->irq, &net_interrupt, 0, "skeleton")) { 286 return -EAGAIN;
287 } 288
289 /* Always snarf the DMA channel after the IRQ, and clean up on failure. */ 290 if (request_dma(dev->dma,"skeleton ethernet")) { 291 free_irq(dev->irq);
292 return -EAGAIN;
293 } 294 irq2dev_map[dev->irq] = dev;
295
296 /* Reset the hardware here. Don't forget to set the station address. */ 297 /*chipset_init(dev, 1);*/ 298 outb(0x00, ioaddr);
299 lp->open_time = jiffies;
300
301 dev->tbusy = 0;
302 dev->interrupt = 0;
303 dev->start = 1;
304 return 0;
305 } 306
307 staticint 308 net_send_packet(structsk_buff *skb, structdevice *dev)
/* */ 309 { 310 structnet_local *lp = (structnet_local *)dev->priv;
311 intioaddr = dev->base_addr;
312
313 if (dev->tbusy) { 314 /* If we get here, some higher level has decided we are broken. 315 There should really be a "kick me" function call instead. */ 316 inttickssofar = jiffies - dev->trans_start;
317 if (tickssofar < 5)
318 return 1;
319 printk("%s: transmit timed out, %s?\n", dev->name,
320 tx_done(dev) ? "IRQ conflict" : "network cable problem");
321 /* Try to restart the adaptor. */ 322 chipset_init(dev, 1);
323 dev->tbusy=0;
324 dev->trans_start = jiffies;
325 } 326
327 /* If some higher layer thinks we've missed an tx-done interrupt 328 we are passed NULL. Caution: dev_tint() handles the cli()/sti() 329 itself. */ 330 if (skb == NULL) { 331 dev_tint(dev);
332 return 0;
333 } 334
335 /* Block a timer-based transmit from overlapping. This could better be 336 done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ 337 if (set_bit(0, (void*)&dev->tbusy) != 0)
338 printk("%s: Transmitter access conflict.\n", dev->name);
339 else{ 340 shortlength = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
341 unsignedchar *buf = skb->data;
342
343 hardware_send_packet(ioaddr, buf, length);
344 dev->trans_start = jiffies;
345 } 346 dev_kfree_skb (skb, FREE_WRITE);
347
348 /* You might need to clean up and record Tx statistics here. */ 349 if (inw(ioaddr) == /*RU*/81)
350 lp->stats.tx_aborted_errors++;
351
352 return 0;
353 } 354
355 /* The typical workload of the driver: 356 Handle the network interface interrupts. */ 357 staticvoid 358 net_interrupt(intreg_ptr)
/* */ 359 { 360 intirq = -(((structpt_regs *)reg_ptr)->orig_eax+2);
361 structdevice *dev = (structdevice *)(irq2dev_map[irq]);
362 structnet_local *lp;
363 intioaddr, status, boguscount = 0;
364
365 if (dev == NULL) { 366 printk ("net_interrupt(): irq %d for unknown device.\n", irq);
367 return;
368 } 369 dev->interrupt = 1;
370
371 ioaddr = dev->base_addr;
372 lp = (structnet_local *)dev->priv;
373 status = inw(ioaddr + 0);
374
375 do{ 376 if (status/*& RX_INTR*/) { 377 /* Got a packet(s). */ 378 net_rx(dev);
379 } 380 if (status/*& TX_INTR*/) { 381 lp->stats.tx_packets++;
382 dev->tbusy = 0;
383 mark_bh(NET_BH); /* Inform upper layers. */ 384 } 385 if (status/*& COUNTERS_INTR*/) { 386 /* Increment the appropriate 'localstats' field. */ 387 lp->stats.tx_window_errors++;
388 } 389 }while (++boguscount < 20) ;
390
391 dev->interrupt = 0;
392 return;
393 } 394
395 /* We have a good packet(s), get it/them out of the buffers. */ 396 staticvoid 397 net_rx(structdevice *dev)
/* */ 398 { 399 structnet_local *lp = (structnet_local *)dev->priv;
400 intioaddr = dev->base_addr;
401 intboguscount = 10;
402
403 do{ 404 intstatus = inw(ioaddr);
405 intpkt_len = inw(ioaddr);
406
407 if (pkt_len == 0) /* Read all the frames? */ 408 break; /* Done for now */ 409
410 if (status & 0x40) {/* There was an error. */ 411 lp->stats.rx_errors++;
412 if (status & 0x20) lp->stats.rx_frame_errors++;
413 if (status & 0x10) lp->stats.rx_over_errors++;
414 if (status & 0x08) lp->stats.rx_crc_errors++;
415 if (status & 0x04) lp->stats.rx_fifo_errors++;
416 }else{ 417 /* Malloc up new buffer. */ 418 structsk_buff *skb;
419
420 skb = alloc_skb(pkt_len, GFP_ATOMIC);
421 if (skb == NULL) { 422 printk("%s: Memory squeeze, dropping packet.\n", dev->name);
423 lp->stats.rx_dropped++;
424 break;
425 } 426 skb->len = pkt_len;
427 skb->dev = dev;
428
429 /* 'skb->data' points to the start of sk_buff data area. */ 430 memcpy(skb->data, (void*)dev->rmem_start,
431 pkt_len);
432 /* or */ 433 insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
434
435 netif_rx(skb);
436 lp->stats.rx_packets++;
437 } 438 }while (--boguscount);
439
440 /* If any worth-while packets have been received, dev_rint() 441 has done a mark_bh(NET_BH) for us and will work on them 442 when we get to the bottom-half routine. */ 443 return;
444 } 445
446 /* The inverse routine to net_open(). */ 447 staticint 448 net_close(structdevice *dev)
/* */ 449 { 450 structnet_local *lp = (structnet_local *)dev->priv;
451 intioaddr = dev->base_addr;
452
453 lp->open_time = 0;
454
455 dev->tbusy = 1;
456 dev->start = 0;
457
458 /* Flush the Tx and disable Rx here. */ 459
460 disable_dma(dev->dma);
461
462 /* If not IRQ or DMA jumpered, free up the line. */ 463 outw(0x00, ioaddr+0); /* Release the physical interrupt line. */ 464
465 free_irq(dev->irq);
466 free_dma(dev->dma);
467
468 irq2dev_map[dev->irq] = 0;
469
470 /* Update the statistics here. */ 471
472 return 0;
473
474 } 475
476 /* Get the current statistics. This may be called with the card open or 477 closed. */ 478 staticstructenet_statistics *
479 net_get_stats(structdevice *dev)
/* */ 480 { 481 structnet_local *lp = (structnet_local *)dev->priv;
482 shortioaddr = dev->base_addr;
483
484 cli();
485 /* Update the statistics from the device registers. */ 486 lp->stats.rx_missed_errors = inw(ioaddr+1);
487 sti();
488
489 return &lp->stats;
490 } 491
492 /* Set or clear the multicast filter for this adaptor. 493 num_addrs == -1 Promiscuous mode, receive all packets 494 num_addrs == 0 Normal mode, clear multicast list 495 num_addrs > 0 Multicast mode, receive normal and MC packets, and do 496 best-effort filtering. 497 */ 498 staticvoid 499 set_multicast_list(structdevice *dev, intnum_addrs, void *addrs)
/* */ 500 { 501 shortioaddr = dev->base_addr;
502 if (num_addrs) { 503 outw(69, ioaddr); /* Enable promiscuous mode */ 504 }else 505 outw(99, ioaddr); /* Disable promiscuous mode, use normal mode */ 506 } 507
508 /* 509 * Local variables: 510 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c" 511 * version-control: t 512 * kept-new-versions: 5 513 * tab-width: 4 514 * End: 515 */