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