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 <linux/netdevice.h>
  60 #include <linux/etherdevice.h>
  61 #include <linux/skbuff.h>
  62 
  63 #ifndef HAVE_AUTOIRQ
  64 /* From auto_irq.c, in ioport.h for later versions. */
  65 extern void autoirq_setup(int waittime);
  66 extern int autoirq_report(int waittime);
  67 /* The map from IRQ number (as passed to the interrupt handler) to
  68    'struct device'. */
  69 extern struct device *irq2dev_map[16];
  70 #endif
  71 
  72 #ifndef HAVE_PORTRESERVE
  73 #define check_region(ioaddr, size)              0
  74 #define snarf_region(ioaddr, size);             do ; while (0)
  75 #endif
  76 
  77 /* use 0 for production, 1 for verification, >2 for debug */
  78 #ifndef NET_DEBUG
  79 #define NET_DEBUG 2
  80 #endif
  81 static unsigned int net_debug = NET_DEBUG;
  82 
  83 /* Information that need to be kept for each board. */
  84 struct net_local {
  85         struct enet_statistics stats;
  86         long open_time;                         /* Useless example local info. */
  87 };
  88 
  89 /* The number of low I/O ports used by the ethercard. */
  90 #define ETHERCARD_TOTAL_SIZE    16
  91 
  92 /* The station (ethernet) address prefix, used for IDing the board. */
  93 #define SA_ADDR0 0x00
  94 #define SA_ADDR1 0x42
  95 #define SA_ADDR2 0x65
  96 
  97 /* Index to functions, as function prototypes. */
  98 
  99 extern int netcard_probe(struct device *dev);
 100 
 101 static int netcard_probe1(struct device *dev, short ioaddr);
 102 static int net_open(struct device *dev);
 103 static int      net_send_packet(struct sk_buff *skb, struct device *dev);
 104 static void net_interrupt(int reg_ptr);
 105 static void net_rx(struct device *dev);
 106 static int net_close(struct device *dev);
 107 static struct enet_statistics *net_get_stats(struct device *dev);
 108 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 109 
 110 /* Example routines you must write ;->. */
 111 #define tx_done(dev) 1
 112 extern void     hardware_send_packet(short ioaddr, char *buf, int length);
 113 extern void chipset_init(struct device *dev, int startp);
 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(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125         int *port, ports[] = {0x300, 0x280, 0};
 126         int base_addr = dev->base_addr;
 127 
 128         if (base_addr > 0x1ff)          /* Check a single specified location. */
 129                 return netcard_probe1(dev, base_addr);
 130         else if (base_addr > 0)         /* Don't probe at all. */
 131                 return ENXIO;
 132 
 133         for (port = &ports[0]; *port; port++) {
 134                 int ioaddr = *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         return ENODEV;
 146 }
 147 
 148 int netcard_probe1(struct device *dev, short ioaddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 149 {
 150         unsigned char station_addr[6];
 151         int i;
 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                 return ENODEV;
 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         else if (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   } else if (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         {        int irqval = 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                          return EAGAIN;
 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(struct net_local), GFP_KERNEL);
 202         memset(dev->priv, 0, sizeof(struct net_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 static int
 226 net_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 227 {
 228         struct net_local *lp = (struct net_local *)dev->priv;
 229         int ioaddr = 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 static int
 257 net_send_packet(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 258 {
 259         struct net_local *lp = (struct net_local *)dev->priv;
 260         int ioaddr = 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                 int tickssofar = 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                 short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 290                 unsigned char *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 static void
 308 net_interrupt(int reg_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 309 {
 310         int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
 311         struct device *dev = (struct device *)(irq2dev_map[irq]);
 312         struct net_local *lp;
 313         int ioaddr, 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 = (struct net_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 static void
 346 net_rx(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 347 {
 348         struct net_local *lp = (struct net_local *)dev->priv;
 349         int ioaddr = dev->base_addr;
 350         int boguscount = 10;
 351 
 352         do {
 353                 int status = inw(ioaddr);
 354                 int pkt_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                         struct sk_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 static int
 397 net_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 398 {
 399         struct net_local *lp = (struct net_local *)dev->priv;
 400         int ioaddr = 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 static struct enet_statistics *
 428 net_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 429 {
 430         struct net_local *lp = (struct net_local *)dev->priv;
 431         short ioaddr = 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 static void
 448 set_multicast_list(struct device *dev, int num_addrs, void *addrs)
     /* [previous][next][first][last][top][bottom][index][help] */
 449 {
 450         short ioaddr = 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  */

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