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