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

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