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