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