root/drivers/net/skeleton.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. netcard_probe
  2. netcard_probe1
  3. net_open
  4. net_send_packet
  5. net_interrupt
  6. net_rx
  7. net_close
  8. net_get_stats
  9. set_multicast_list

   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 static char *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 "dev.h"
  60 #include "eth.h"
  61 #include "skbuff.h"
  62 #include "arp.h"
  63 
  64 #ifndef HAVE_AUTOIRQ
  65 /* From auto_irq.c, in ioport.h for later versions. */
  66 extern void autoirq_setup(int waittime);
  67 extern int autoirq_report(int waittime);
  68 /* The map from IRQ number (as passed to the interrupt handler) to
  69    'struct device'. */
  70 extern struct device *irq2dev_map[16];
  71 #endif
  72 
  73 #ifndef HAVE_ALLOC_SKB
  74 #define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority)
  75 #define kfree_skbmem(addr, size) kfree_s(addr,size);
  76 #endif
  77 
  78 #ifndef HAVE_PORTRESERVE
  79 #define check_region(ioaddr, size)              0
  80 #define snarf_region(ioaddr, size);             do ; while (0)
  81 #endif
  82 
  83 /* use 0 for production, 1 for verification, >2 for debug */
  84 #ifndef NET_DEBUG
  85 #define NET_DEBUG 2
  86 #endif
  87 static unsigned int net_debug = NET_DEBUG;
  88 
  89 /* Information that need to be kept for each board. */
  90 struct net_local {
  91         struct enet_statistics stats;
  92         long open_time;                         /* Useless example local info. */
  93 };
  94 
  95 /* The number of low I/O ports used by the ethercard. */
  96 #define ETHERCARD_TOTAL_SIZE    16
  97 
  98 /* The station (ethernet) address prefix, used for IDing the board. */
  99 #define SA_ADDR0 0x00
 100 #define SA_ADDR1 0x42
 101 #define SA_ADDR2 0x65
 102 
 103 /* Index to functions, as function prototypes. */
 104 
 105 extern int netcard_probe(struct device *dev);
 106 
 107 static int netcard_probe1(struct device *dev, short ioaddr);
 108 static int net_open(struct device *dev);
 109 static int      net_send_packet(struct sk_buff *skb, struct device *dev);
 110 static void net_interrupt(int reg_ptr);
 111 static void net_rx(struct device *dev);
 112 static int net_close(struct device *dev);
 113 static struct enet_statistics *net_get_stats(struct device *dev);
 114 #ifdef HAVE_MULTICAST
 115 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 116 #endif
 117 
 118 /* Example routines you must write ;->. */
 119 #define tx_done(dev) 1
 120 extern void     hardware_send_packet(short ioaddr, char *buf, int length);
 121 extern void chipset_init(struct device *dev, int startp);
 122 
 123 
 124 /* Check for a network adaptor of this type, and return '0' iff one exists.
 125    If dev->base_addr == 0, probe all likely locations.
 126    If dev->base_addr == 1, always return failure.
 127    If dev->base_addr == 2, alloate space for the device and return success
 128    (detachable devices only).
 129    */
 130 int
 131 netcard_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 132 {
 133         int *port, ports[] = {0x300, 0x280, 0};
 134         int base_addr = dev->base_addr;
 135 
 136         if (base_addr > 0x1ff)          /* Check a single specified location. */
 137                 return netcard_probe1(dev, base_addr);
 138         else if (base_addr > 0)         /* Don't probe at all. */
 139                 return ENXIO;
 140 
 141         for (port = &ports[0]; *port; port++) {
 142                 int ioaddr = *port;
 143                 if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE))
 144                         continue;
 145                 if (inb(ioaddr) != 0x57)
 146                         continue;
 147                 dev->base_addr = ioaddr;
 148                 if (netcard_probe1(dev, ioaddr) == 0)
 149                         return 0;
 150         }
 151 
 152         dev->base_addr = base_addr;
 153         return ENODEV;
 154 }
 155 
 156 int netcard_probe1(struct device *dev, short ioaddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158         unsigned char station_addr[6];
 159         int i;
 160 
 161         /* Read the station address PROM.  */
 162         for (i = 0; i < 6; i++) {
 163                 station_addr[i] = inb(ioaddr + i);
 164         }
 165         /* Check the first three octets of the S.A. for the manufactor's code. */ 
 166         if (station_addr[0] != SA_ADDR0
 167                 ||       station_addr[1] != SA_ADDR1 || station_addr[2] != SA_ADDR2) {
 168                 return ENODEV;
 169         }
 170 
 171         printk("%s: %s found at %#3x, IRQ %d.\n", dev->name,
 172                    "network card", dev->base_addr, dev->irq);
 173 
 174 #ifdef jumpered_interrupts
 175         /* If this board has jumpered interrupts, snarf the interrupt vector
 176            now.  There is no point in waiting since no other device can use
 177            the interrupt, and this marks the 'irqaction' as busy. */
 178 
 179         if (dev->irq == -1)
 180                 ;                       /* Do nothing: a user-level program will set it. */
 181         else if (dev->irq < 2) {        /* "Auto-IRQ" */
 182                 autoirq_setup(0);
 183                 /* Trigger an interrupt here. */
 184 
 185                 dev->irq = autoirq_report(0);
 186                 if (net_debug >= 2)
 187                         printk(" autoirq is %d", dev->irq);
 188   } else if (dev->irq == 2)
 189           /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
 190          or don't know which one to set. */
 191           dev->irq = 9;
 192 
 193         {        int irqval = request_irq(dev->irq, &net_interrupt);
 194                  if (irqval) {
 195                          printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
 196                                          dev->irq, irqval);
 197                          return EAGAIN;
 198                  }
 199          }
 200 #endif  /* jumpered interrupt */
 201 
 202         /* Grab the region so we can find another board if autoIRQ fails. */
 203         snarf_region(ioaddr, ETHERCARD_TOTAL_SIZE);
 204 
 205         if (net_debug)
 206                 printk(version);
 207 
 208         /* Initialize the device structure. */
 209         dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
 210         memset(dev->priv, 0, sizeof(struct net_local));
 211 
 212         dev->open               = net_open;
 213         dev->stop               = net_close;
 214         dev->hard_start_xmit = net_send_packet;
 215         dev->get_stats  = net_get_stats;
 216 #ifdef HAVE_MULTICAST
 217         dev->set_multicast_list = &set_multicast_list;
 218 #endif
 219 
 220         /* Fill in the fields of the device structure with ethernet-generic values.
 221            This should be in a common file instead of per-driver.  */
 222         for (i = 0; i < DEV_NUMBUFFS; i++)
 223                 dev->buffs[i] = NULL;
 224 
 225         dev->hard_header        = eth_header;
 226         dev->add_arp            = eth_add_arp;
 227         dev->queue_xmit         = dev_queue_xmit;
 228         dev->rebuild_header     = eth_rebuild_header;
 229         dev->type_trans         = eth_type_trans;
 230 
 231         dev->type                       = ARPHRD_ETHER;
 232         dev->hard_header_len = ETH_HLEN;
 233         dev->mtu                        = 1500; /* eth_mtu */
 234         dev->addr_len           = ETH_ALEN;
 235         for (i = 0; i < ETH_ALEN; i++) {
 236                 dev->broadcast[i]=0xff;
 237         }
 238 
 239         /* New-style flags. */
 240         dev->flags                      = IFF_BROADCAST;
 241         dev->family                     = AF_INET;
 242         dev->pa_addr            = 0;
 243         dev->pa_brdaddr         = 0;
 244         dev->pa_mask            = 0;
 245         dev->pa_alen            = sizeof(unsigned long);
 246 
 247         return 0;
 248 }
 249 
 250 
 251 /* Open/initialize the board.  This is called (in the current kernel)
 252    sometime after booting when the 'ifconfig' program is run.
 253 
 254    This routine should set everything up anew at each open, even
 255    registers that "should" only need to be set once at boot, so that
 256    there is non-reboot way to recover if something goes wrong.
 257    */
 258 static int
 259 net_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 260 {
 261         struct net_local *lp = (struct net_local *)dev->priv;
 262         int ioaddr = dev->base_addr;
 263 
 264         /* This is used if the interrupt line can turned off (shared).
 265            See 3c503.c for an example of selecting the IRQ at config-time. */
 266         if (request_irq(dev->irq, &net_interrupt)) {
 267                 return -EAGAIN;
 268         }
 269 
 270 
 271         /* Always snarf a DMA channel after the IRQ. */
 272         if (request_dma(dev->dma)) {
 273                 free_irq(dev->irq);
 274                 return -EAGAIN;
 275         }
 276         irq2dev_map[dev->irq] = dev;
 277 
 278         /* Reset the hardware here. */
 279         /*chipset_init(dev, 1);*/
 280         outb(0x00, ioaddr);
 281         lp->open_time = jiffies;
 282 
 283         dev->tbusy = 0;
 284         dev->interrupt = 0;
 285         dev->start = 1;
 286         return 0;
 287 }
 288 
 289 static int
 290 net_send_packet(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 291 {
 292         struct net_local *lp = (struct net_local *)dev->priv;
 293         int ioaddr = dev->base_addr;
 294 
 295         if (dev->tbusy) {
 296                 /* If we get here, some higher level has decided we are broken.
 297                    There should really be a "kick me" function call instead. */
 298                 int tickssofar = jiffies - dev->trans_start;
 299                 if (tickssofar < 5)
 300                         return 1;
 301                 printk("%s: transmit timed out, %s?\n", dev->name,
 302                            tx_done(dev) ? "IRQ conflict" : "network cable problem");
 303                 /* Try to restart the adaptor. */
 304                 chipset_init(dev, 1);
 305                 dev->tbusy=0;
 306                 dev->trans_start = jiffies;
 307         }
 308 
 309         /* If some higher layer thinks we've missed an tx-done interrupt
 310            we are passed NULL. Caution: dev_tint() handles the cli()/sti()
 311            itself. */
 312         if (skb == NULL) {
 313                 dev_tint(dev);
 314                 return 0;
 315         }
 316 
 317         /* For ethernet, fill in the header.  This should really be done by a
 318            higher level, rather than duplicated for each ethernet adaptor. */
 319         if (!skb->arp  &&  dev->rebuild_header(skb->data, dev)) {
 320                 skb->dev = dev;
 321                 arp_queue (skb);
 322                 return 0;
 323         }
 324         skb->arp=1;
 325 
 326         /* Block a timer-based transmit from overlapping.  This could better be
 327            done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
 328         if (set_bit(0, (void*)&dev->tbusy) != 0)
 329                 printk("%s: Transmitter access conflict.\n", dev->name);
 330         else {
 331                 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 332                 unsigned char *buf = skb->data;
 333 
 334                 hardware_send_packet(ioaddr, buf, length);
 335                 dev->trans_start = jiffies;
 336         }
 337         if (skb->free)
 338                 kfree_skb (skb, FREE_WRITE);
 339 
 340         /* You might need to clean up and record Tx statistics here. */
 341         if (inw(ioaddr) == /*RU*/81)
 342                 lp->stats.tx_aborted_errors++;
 343 
 344         return 0;
 345 }
 346 
 347 /* The typical workload of the driver:
 348    Handle the network interface interrupts. */
 349 static void
 350 net_interrupt(int reg_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 351 {
 352         int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
 353         struct device *dev = (struct device *)(irq2dev_map[irq]);
 354         struct net_local *lp;
 355         int ioaddr, status, boguscount = 0;
 356 
 357         if (dev == NULL) {
 358                 printk ("net_interrupt(): irq %d for unknown device.\n", irq);
 359                 return;
 360         }
 361         dev->interrupt = 1;
 362 
 363         ioaddr = dev->base_addr;
 364         lp = (struct net_local *)dev->priv;
 365         status = inw(ioaddr + 0);
 366 
 367         do {
 368                 if (status /*& RX_INTR*/) {
 369                         /* Got a packet(s). */
 370                         net_rx(dev);
 371                 }
 372                 if (status /*& TX_INTR*/) {
 373                         lp->stats.tx_packets++;
 374                         dev->tbusy = 0;
 375                         mark_bh(INET_BH);       /* Inform upper layers. */
 376                 }
 377                 if (status /*& COUNTERS_INTR*/) {
 378                         /* Increment the appropriate 'localstats' field. */
 379                         lp->stats.tx_window_errors++;
 380                 }
 381         } while (++boguscount < 20) ;
 382 
 383         return;
 384 }
 385 
 386 /* We have a good packet(s), get it/them out of the buffers. */
 387 static void
 388 net_rx(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 389 {
 390         struct net_local *lp = (struct net_local *)dev->priv;
 391         int ioaddr = dev->base_addr;
 392         int boguscount = 10;
 393 
 394         do {
 395                 int status = inw(ioaddr);
 396                 int pkt_len = inw(ioaddr);
 397           
 398                 if (pkt_len == 0)               /* Read all the frames? */
 399                         break;                  /* Done for now */
 400 
 401                 if (status & 0x40) {    /* There was an error. */
 402                         lp->stats.rx_errors++;
 403                         if (status & 0x20) lp->stats.rx_frame_errors++;
 404                         if (status & 0x10) lp->stats.rx_over_errors++;
 405                         if (status & 0x08) lp->stats.rx_crc_errors++;
 406                         if (status & 0x04) lp->stats.rx_fifo_errors++;
 407                 } else {
 408                         /* Malloc up new buffer. */
 409                         int sksize = sizeof(struct sk_buff) + pkt_len;
 410                         struct sk_buff *skb;
 411 
 412                         skb = alloc_skb(sksize, GFP_ATOMIC);
 413                         if (skb == NULL) {
 414                                 printk("%s: Memory squeeze, dropping packet.\n", dev->name);
 415                                 lp->stats.rx_dropped++;
 416                                 break;
 417                         }
 418                         skb->mem_len = sksize;
 419                         skb->mem_addr = skb;
 420                         skb->len = pkt_len;
 421                         skb->dev = dev;
 422 
 423                         /* 'skb->data' points to the start of sk_buff data area. */
 424                         memcpy(skb->data, (void*)dev->rmem_start,
 425                                    pkt_len);
 426                         /* or */
 427                         insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
 428 
 429 #ifdef HAVE_NETIF_RX
 430                         netif_rx(skb);
 431 #else
 432                         skb->lock = 0;
 433                         if (dev_rint((unsigned char*)skb, pkt_len, IN_SKBUFF, dev) != 0) {
 434                                 kfree_s(skb, sksize);
 435                                 lp->stats.rx_dropped++;
 436                                 break;
 437                         }
 438 #endif
 439                         lp->stats.rx_packets++;
 440                 }
 441         } while (--boguscount);
 442 
 443         /* If any worth-while packets have been received, dev_rint()
 444            has done a mark_bh(INET_BH) for us and will work on them
 445            when we get to the bottom-half routine. */
 446         return;
 447 }
 448 
 449 /* The inverse routine to net_open(). */
 450 static int
 451 net_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 452 {
 453         struct net_local *lp = (struct net_local *)dev->priv;
 454         int ioaddr = dev->base_addr;
 455 
 456         lp->open_time = 0;
 457 
 458         dev->tbusy = 1;
 459         dev->start = 0;
 460 
 461         /* Flush the Tx and disable Rx here. */
 462 
 463         disable_dma(dev->dma);
 464 
 465         /* If not IRQ or DMA jumpered, free up the line. */
 466         outw(0x00, ioaddr+0);           /* Release the physical interrupt line. */
 467 
 468         free_irq(dev->irq);
 469         free_dma(dev->dma);
 470 
 471         irq2dev_map[dev->irq] = 0;
 472 
 473         /* Update the statistics here. */
 474 
 475         return 0;
 476 
 477 }
 478 
 479 /* Get the current statistics.  This may be called with the card open or
 480    closed. */
 481 static struct enet_statistics *
 482 net_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 483 {
 484         struct net_local *lp = (struct net_local *)dev->priv;
 485         short ioaddr = dev->base_addr;
 486 
 487         cli();
 488         /* Update the statistics from the device registers. */
 489         lp->stats.rx_missed_errors = inw(ioaddr+1);
 490         sti();
 491 
 492         return &lp->stats;
 493 }
 494 
 495 #ifdef HAVE_MULTICAST
 496 /* Set or clear the multicast filter for this adaptor.
 497    num_addrs == -1      Promiscuous mode, receive all packets
 498    num_addrs == 0       Normal mode, clear multicast list
 499    num_addrs > 0        Multicast mode, receive normal and MC packets, and do
 500                         best-effort filtering.
 501  */
 502 static void
 503 set_multicast_list(struct device *dev, int num_addrs, void *addrs)
     /* [previous][next][first][last][top][bottom][index][help] */
 504 {
 505         short ioaddr = dev->base_addr;
 506         if (num_addrs) {
 507                 outw(69, ioaddr);               /* Enable promiscuous mode */
 508         } else
 509                 outw(99, ioaddr);               /* Disable promiscuous mode, use normal mode */
 510 }
 511 #endif
 512 
 513 /*
 514  * Local variables:
 515  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c"
 516  *  version-control: t
 517  *  kept-new-versions: 5
 518  *  tab-width: 4
 519  * End:
 520  */

/* [previous][next][first][last][top][bottom][index][help] */