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

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