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(intirq, structpt_regs *regs);
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 request_region(ioaddr, NETCARD_IO_EXTENT,"skeleton");
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(intirq, structpt_regs * regs)
/* */ 359 { 360 structdevice *dev = (structdevice *)(irq2dev_map[irq]);
361 structnet_local *lp;
362 intioaddr, status, boguscount = 0;
363
364 if (dev == NULL) { 365 printk ("net_interrupt(): irq %d for unknown device.\n", irq);
366 return;
367 } 368 dev->interrupt = 1;
369
370 ioaddr = dev->base_addr;
371 lp = (structnet_local *)dev->priv;
372 status = inw(ioaddr + 0);
373
374 do{ 375 if (status/*& RX_INTR*/) { 376 /* Got a packet(s). */ 377 net_rx(dev);
378 } 379 if (status/*& TX_INTR*/) { 380 lp->stats.tx_packets++;
381 dev->tbusy = 0;
382 mark_bh(NET_BH); /* Inform upper layers. */ 383 } 384 if (status/*& COUNTERS_INTR*/) { 385 /* Increment the appropriate 'localstats' field. */ 386 lp->stats.tx_window_errors++;
387 } 388 }while (++boguscount < 20) ;
389
390 dev->interrupt = 0;
391 return;
392 } 393
394 /* We have a good packet(s), get it/them out of the buffers. */ 395 staticvoid 396 net_rx(structdevice *dev)
/* */ 397 { 398 structnet_local *lp = (structnet_local *)dev->priv;
399 intioaddr = dev->base_addr;
400 intboguscount = 10;
401
402 do{ 403 intstatus = inw(ioaddr);
404 intpkt_len = inw(ioaddr);
405
406 if (pkt_len == 0) /* Read all the frames? */ 407 break; /* Done for now */ 408
409 if (status & 0x40) {/* There was an error. */ 410 lp->stats.rx_errors++;
411 if (status & 0x20) lp->stats.rx_frame_errors++;
412 if (status & 0x10) lp->stats.rx_over_errors++;
413 if (status & 0x08) lp->stats.rx_crc_errors++;
414 if (status & 0x04) lp->stats.rx_fifo_errors++;
415 }else{ 416 /* Malloc up new buffer. */ 417 structsk_buff *skb;
418
419 skb = dev_alloc_skb(pkt_len);
420 if (skb == NULL) { 421 printk("%s: Memory squeeze, dropping packet.\n", dev->name);
422 lp->stats.rx_dropped++;
423 break;
424 } 425 skb->dev = dev;
426
427 /* 'skb->data' points to the start of sk_buff data area. */ 428 memcpy(skb_put(skb,pkt_len), (void*)dev->rmem_start,
429 pkt_len);
430 /* or */ 431 insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
432
433 netif_rx(skb);
434 lp->stats.rx_packets++;
435 } 436 }while (--boguscount);
437
438 /* If any worth-while packets have been received, dev_rint() 439 has done a mark_bh(NET_BH) for us and will work on them 440 when we get to the bottom-half routine. */ 441 return;
442 } 443
444 /* The inverse routine to net_open(). */ 445 staticint 446 net_close(structdevice *dev)
/* */ 447 { 448 structnet_local *lp = (structnet_local *)dev->priv;
449 intioaddr = dev->base_addr;
450
451 lp->open_time = 0;
452
453 dev->tbusy = 1;
454 dev->start = 0;
455
456 /* Flush the Tx and disable Rx here. */ 457
458 disable_dma(dev->dma);
459
460 /* If not IRQ or DMA jumpered, free up the line. */ 461 outw(0x00, ioaddr+0); /* Release the physical interrupt line. */ 462
463 free_irq(dev->irq);
464 free_dma(dev->dma);
465
466 irq2dev_map[dev->irq] = 0;
467
468 /* Update the statistics here. */ 469
470 return 0;
471
472 } 473
474 /* Get the current statistics. This may be called with the card open or 475 closed. */ 476 staticstructenet_statistics *
477 net_get_stats(structdevice *dev)
/* */ 478 { 479 structnet_local *lp = (structnet_local *)dev->priv;
480 shortioaddr = dev->base_addr;
481
482 cli();
483 /* Update the statistics from the device registers. */ 484 lp->stats.rx_missed_errors = inw(ioaddr+1);
485 sti();
486
487 return &lp->stats;
488 } 489
490 /* Set or clear the multicast filter for this adaptor. 491 num_addrs == -1 Promiscuous mode, receive all packets 492 num_addrs == 0 Normal mode, clear multicast list 493 num_addrs > 0 Multicast mode, receive normal and MC packets, and do 494 best-effort filtering. 495 */ 496 staticvoid 497 set_multicast_list(structdevice *dev, intnum_addrs, void *addrs)
/* */ 498 { 499 shortioaddr = dev->base_addr;
500 if (num_addrs) { 501 outw(69, ioaddr); /* Enable promiscuous mode */ 502 }else 503 outw(99, ioaddr); /* Disable promiscuous mode, use normal mode */ 504 } 505
506 /* 507 * Local variables: 508 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c" 509 * version-control: t 510 * kept-new-versions: 5 511 * tab-width: 4 512 * End: 513 */