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
  10. init_module
  11. cleanup_module

   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 static const char *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 #ifdef MODULE
  43 #include <linux/module.h>
  44 #include <linux/version.h>
  45 #else
  46 #define  MOD_INC_USE_COUNT do {} while (0)
  47 #define  MOD_DEC_USE_COUNT do {} 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 static const char* 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 static unsigned int netcard_portlist[] =
  78    { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
  79 
  80 /* use 0 for production, 1 for verification, >2 for debug */
  81 #ifndef NET_DEBUG
  82 #define NET_DEBUG 2
  83 #endif
  84 static unsigned int net_debug = NET_DEBUG;
  85 
  86 /* The number of low I/O ports used by the ethercard. */
  87 #define NETCARD_IO_EXTENT       32
  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 station (ethernet) address prefix, used for IDing the board. */
  96 #define SA_ADDR0 0x00
  97 #define SA_ADDR1 0x42
  98 #define SA_ADDR2 0x65
  99 
 100 /* Index to functions, as function prototypes. */
 101 
 102 extern int netcard_probe(struct device *dev);
 103 
 104 static int netcard_probe1(struct device *dev, int ioaddr);
 105 static int net_open(struct device *dev);
 106 static int      net_send_packet(struct sk_buff *skb, struct device *dev);
 107 static void net_interrupt(int irq, struct pt_regs *regs);
 108 static void net_rx(struct device *dev);
 109 static int net_close(struct device *dev);
 110 static struct enet_statistics *net_get_stats(struct device *dev);
 111 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 112 
 113 /* Example routines you must write ;->. */
 114 #define tx_done(dev) 1
 115 extern void     hardware_send_packet(short ioaddr, char *buf, int length);
 116 extern void chipset_init(struct device *dev, int startp);
 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 #ifdef HAVE_DEVLIST
 126 /* Support for a alternate probe manager, which will eliminate the
 127    boilerplate below. */
 128 struct netdev_entry netcard_drv =
 129 {cardname, netcard_probe1, NETCARD_IO_EXTENT, netcard_portlist};
 130 #else
 131 int
 132 netcard_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 133 {
 134         int i;
 135         int base_addr = dev ? dev->base_addr : 0;
 136 
 137         if (base_addr > 0x1ff)          /* Check a single specified location. */
 138                 return netcard_probe1(dev, base_addr);
 139         else if (base_addr != 0)        /* Don't probe at all. */
 140                 return -ENXIO;
 141 
 142         for (i = 0; netcard_portlist[i]; i++) {
 143                 int ioaddr = 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 static int netcard_probe1(struct device *dev, int ioaddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160         static unsigned version_printed = 0;
 161         int i;
 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         else if (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         } else if (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                 int irqval = 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                 short dma_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(struct net_local), GFP_KERNEL);
 268                 if (dev->priv == NULL)
 269                         return -ENOMEM;
 270         }
 271 
 272         memset(dev->priv, 0, sizeof(struct net_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 static int
 298 net_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 299 {
 300         struct net_local *lp = (struct net_local *)dev->priv;
 301         int ioaddr = 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 static int
 331 net_send_packet(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 332 {
 333         struct net_local *lp = (struct net_local *)dev->priv;
 334         int ioaddr = 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                 int tickssofar = 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                 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 364                 unsigned char *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 static void
 381 net_interrupt(int irq, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 382 {
 383         struct device *dev = (struct device *)(irq2dev_map[irq]);
 384         struct net_local *lp;
 385         int ioaddr, 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 = (struct net_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 static void
 419 net_rx(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 420 {
 421         struct net_local *lp = (struct net_local *)dev->priv;
 422         int ioaddr = dev->base_addr;
 423         int boguscount = 10;
 424 
 425         do {
 426                 int status = inw(ioaddr);
 427                 int pkt_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                         struct sk_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 static int
 470 net_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 471 {
 472         struct net_local *lp = (struct net_local *)dev->priv;
 473         int ioaddr = 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 static struct enet_statistics *
 503 net_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 504 {
 505         struct net_local *lp = (struct net_local *)dev->priv;
 506         short ioaddr = 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 static void
 523 set_multicast_list(struct device *dev, int num_addrs, void *addrs)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525         short ioaddr = 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 #ifdef MODULE
 533 
 534 char kernel_version[] = UTS_RELEASE;
 535 static char devicename[9] = { 0, };
 536 static struct device this_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 int io = 0x300;
 543 int irq = 0;
 544 int dma = 0;
 545 int mem = 0;
 546 
 547 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 548 {
 549         int result;
 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                 return result;
 563 
 564         return 0;
 565 }
 566 
 567 void
 568 cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 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(struct net_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  */

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