root/drivers/net/a2065.c

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

DEFINITIONS

This source file includes following definitions.
  1. a2065_probe
  2. a2065_open
  3. a2065_init_ring
  4. a2065_close
  5. a2065_interrupt
  6. a2065_start_xmit
  7. a2065_rx
  8. a2065_get_stats
  9. set_multicast_list

   1 /*
   2  * Amiga Linux/68k A2065 Ethernet Driver
   3  *
   4  * (C) Copyright 1995 by Geert Uytterhoeven
   5  *                      (Geert.Uytterhoeven@cs.kuleuven.ac.be)
   6  *
   7  * Fixes and tips by:
   8  *      - Janos Farkas (CHEXUM@sparta.banki.hu)
   9  *      - Jes Degn Soerensen (jds@kom.auc.dk)
  10  *
  11  * ----------------------------------------------------------------------------
  12  *
  13  * This program is based on
  14  *
  15  *      ariadne.?:      Amiga Linux/68k Ariadne Ethernet Driver
  16  *                      (C) Copyright 1995 by Geert Uytterhoeven,
  17  *                                            Peter De Schrijver
  18  *
  19  *      lance.c:        An AMD LANCE ethernet driver for linux.
  20  *                      Written 1993-94 by Donald Becker.
  21  *
  22  *      Am79C960:       PCnet(tm)-ISA Single-Chip Ethernet Controller
  23  *                      Advanced Micro Devices
  24  *                      Publication #16907, Rev. B, Amendment/0, May 1994
  25  *
  26  * ----------------------------------------------------------------------------
  27  *
  28  * This file is subject to the terms and conditions of the GNU General Public
  29  * License.  See the file README.legal in the main directory of the Linux/68k
  30  * distribution for more details.
  31  *
  32  * ----------------------------------------------------------------------------
  33  *
  34  * The A2065 is a Zorro-II board made by Commodore/Ameristar. It contains:
  35  *
  36  *      - an Am7990 Local Area Network Controller for Ethernet (LANCE) with
  37  *        both 10BASE-2 (thin coax) and AUI (DB-15) connectors
  38  */
  39 
  40 #include <stddef.h>
  41 
  42 #include <linux/kernel.h>
  43 #include <linux/sched.h>
  44 #include <linux/string.h>
  45 #include <linux/ptrace.h>
  46 #include <linux/errno.h>
  47 #include <linux/ioport.h>
  48 #include <linux/malloc.h>
  49 #include <linux/interrupt.h>
  50 #include <linux/netdevice.h>
  51 #include <linux/etherdevice.h>
  52 #include <linux/skbuff.h>
  53 
  54 #include <asm/bitops.h>
  55 #include <asm/io.h>
  56 #include <asm/irq.h>
  57 
  58 #include <asm/bootinfo.h>
  59 #include <asm/amigaints.h>
  60 #include <asm/amigahw.h>
  61 #include <asm/zorro.h>
  62 
  63 #include "a2065.h"
  64 
  65 #ifdef A2065_DEBUG
  66 int a2065_debug = A2065_DEBUG;
  67 #else
  68 int a2065_debug = 1;
  69 #endif
  70 
  71 
  72         /*
  73          *              Transmit/Receive Ring Definitions
  74          */
  75 
  76 #define LANCE_LOG_TX_BUFFERS    (2)
  77 #define LANCE_LOG_RX_BUFFERS    (4)
  78 
  79 #define TX_RING_SIZE            (1<<LANCE_LOG_TX_BUFFERS)
  80 #define RX_RING_SIZE            (1<<LANCE_LOG_RX_BUFFERS)
  81 
  82 #define TX_RING_MOD_MASK        (TX_RING_SIZE-1)
  83 #define RX_RING_MOD_MASK        (RX_RING_SIZE-1)
  84 
  85 #define PKT_BUF_SIZE            (1520)
  86 
  87 
  88         /*
  89          *              Private Device Data
  90          */
  91 
  92 struct a2065_private {
  93         struct A2065Board *board;
  94         struct TDRE *tx_ring[TX_RING_SIZE];
  95         struct RDRE *rx_ring[RX_RING_SIZE];
  96         u_char *tx_buff[TX_RING_SIZE];
  97         u_char *rx_buff[RX_RING_SIZE];
  98         int cur_tx, cur_rx;             /* The next free ring entry */
  99         int dirty_tx;                   /* The ring entries to be free()ed. */
 100         struct enet_statistics stats;
 101         char tx_full;
 102         unsigned long lock;
 103 };
 104 
 105 
 106         /*
 107          *              Structure Created in the A2065's RAM Buffer
 108          */
 109 
 110 struct lancedata {
 111         struct InitBlock init;
 112         struct TDRE tx_ring[TX_RING_SIZE];
 113         struct RDRE rx_ring[RX_RING_SIZE];
 114         u_char tx_buff[TX_RING_SIZE][PKT_BUF_SIZE];
 115         u_char rx_buff[RX_RING_SIZE][PKT_BUF_SIZE];
 116 };
 117 
 118 
 119 static int a2065_open(struct device *dev);
 120 static void a2065_init_ring(struct device *dev);
 121 static int a2065_start_xmit(struct sk_buff *skb, struct device *dev);
 122 static int a2065_rx(struct device *dev);
 123 static void a2065_interrupt(int irq, struct pt_regs *fp, void *data);
 124 static int a2065_close(struct device *dev);
 125 static struct enet_statistics *a2065_get_stats(struct device *dev);
 126 static void set_multicast_list(struct device *dev);
 127 
 128 
 129 int a2065_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         int key1, key2;
 132         struct ConfigDev *cd;
 133         u_long board;
 134         u_long sn;
 135         struct a2065_private *priv;
 136 
 137         if ((key1 = zorro_find(MANUF_COMMODORE, PROD_A2065, 0, 0)) ||
 138             (key2 = zorro_find(MANUF_AMERISTAR, PROD_AMERISTAR2065, 0, 0))) {
 139                 cd = zorro_get_board(key1 ? key1 : key2);
 140                 if ((board = (u_long)cd->cd_BoardAddr)) {
 141                         sn = cd->cd_Rom.er_SerialNumber;
 142                         if (key1) {                     /* Commodore */
 143                                 dev->dev_addr[0] = 0x00;
 144                                 dev->dev_addr[1] = 0x80;
 145                                 dev->dev_addr[2] = 0x10;
 146                         } else {                        /* Ameristar */
 147                                 dev->dev_addr[0] = 0x00;
 148                                 dev->dev_addr[1] = 0x00;
 149                                 dev->dev_addr[2] = 0x9f;
 150                         }
 151                         dev->dev_addr[3] = (sn>>16) & 0xff;
 152                         dev->dev_addr[4] = (sn>>8) & 0xff;
 153                         dev->dev_addr[5] = sn & 0xff;
 154                         printk("%s: A2065 at 0x%08lx, Ethernet Address %02x:%02x:%02x:%02x:%02x:%02x\n",
 155                                dev->name, board, dev->dev_addr[0],
 156                                dev->dev_addr[1], dev->dev_addr[2],
 157                                dev->dev_addr[3], dev->dev_addr[4],
 158                                dev->dev_addr[5]);
 159 
 160                         init_etherdev(dev, 0);
 161 
 162                         dev->priv = kmalloc(sizeof(struct
 163                                                    a2065_private),
 164                                             GFP_KERNEL);
 165                         priv = (struct a2065_private *)dev->priv;
 166                         memset(priv, 0, sizeof(struct a2065_private));
 167 
 168                         priv->board = (struct A2065Board *)ZTWO_VADDR(board);
 169 
 170                         dev->open = &a2065_open;
 171                         dev->stop = &a2065_close;
 172                         dev->hard_start_xmit = &a2065_start_xmit;
 173                         dev->get_stats = &a2065_get_stats;
 174                         dev->set_multicast_list = &set_multicast_list;
 175 
 176                         zorro_config_board(key1 ? key1 : key2, 0);
 177                         return(0);
 178                 }
 179         }
 180         return(ENODEV);
 181 }
 182 
 183 
 184 static int a2065_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186         struct a2065_private *priv = (struct a2065_private *)dev->priv;
 187         struct A2065Board *board = priv->board;
 188         static int interruptinstalled = 0;
 189         struct lancedata *lancedata;            /* LANCE point of view */
 190         struct lancedata *alancedata;           /* Amiga point of view */
 191 
 192         lancedata = (struct lancedata *)offsetof(struct A2065Board, RAM);
 193         alancedata = (struct lancedata *)board->RAM;
 194 
 195         /* Stop the LANCE */
 196         board->Lance.RAP = CSR0;                /* LANCE Controller Status */
 197         board->Lance.RDP = STOP;
 198 
 199         /* Enable big endian byte ordering */
 200         board->Lance.RAP = CSR3;                /* CSR3 */
 201         board->Lance.RDP = BSWP;
 202 
 203         /* Set the Init Block Pointer */
 204         board->Lance.RAP = CSR1;                /* IADR[15:0] */
 205         board->Lance.RDP = (u_long)&lancedata->init;
 206         board->Lance.RAP = CSR2;                /* IADR[23:16] */
 207         board->Lance.RDP = 0x0000;
 208 
 209         /* Set the Mode */
 210         alancedata->init.Mode = 0;
 211 
 212         /* Set the Ethernet Hardware Address */
 213                             /* Physical Address Register */
 214         alancedata->init.PADR[0] = dev->dev_addr[1];
 215         alancedata->init.PADR[1] = dev->dev_addr[0];
 216         alancedata->init.PADR[2] = dev->dev_addr[3];
 217         alancedata->init.PADR[3] = dev->dev_addr[2];
 218         alancedata->init.PADR[4] = dev->dev_addr[5];
 219         alancedata->init.PADR[5] = dev->dev_addr[4];
 220 
 221         /* Set the Multicast Table */
 222                             /* Logical Address Filter, LADRF[31:0] */
 223         alancedata->init.LADRF[0] = 0x00000000;
 224                             /* Logical Address Filter, LADRF[63:32] */  
 225         alancedata->init.LADRF[1] = 0x00000000;
 226 
 227         /* Set the Receive and Transmit Descriptor Ring Pointers */
 228         alancedata->init.RDRA = (u_long)&lancedata->rx_ring;
 229         alancedata->init.RLEN = LANCE_LOG_RX_BUFFERS << 13;
 230         alancedata->init.TDRA = (u_long)&lancedata->tx_ring;
 231         alancedata->init.TLEN = LANCE_LOG_TX_BUFFERS << 13;
 232 
 233         /* Initialise the Rings */
 234         a2065_init_ring(dev);
 235 
 236 
 237         /* Install the Interrupt handler */
 238         if (!interruptinstalled) {
 239                 if (!add_isr(IRQ_AMIGA_PORTS, a2065_interrupt, 0, dev,
 240                                          "a2065 Ethernet"))
 241                         return(-EAGAIN);
 242                 interruptinstalled = 1;
 243         }
 244 
 245         /* Make the LANCE read the Init Block */
 246         board->Lance.RAP = CSR0;                /* LANCE Controller Status */
 247         board->Lance.RDP = INEA|INIT;
 248 
 249         dev->tbusy = 0;
 250         dev->interrupt = 0;
 251         dev->start = 1;
 252 
 253         return(0);
 254 }
 255 
 256 
 257 static void a2065_init_ring(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 258 {
 259         struct a2065_private *priv = (struct a2065_private *)dev->priv;
 260         struct A2065Board *board = priv->board;
 261         struct lancedata *lancedata;            /* LANCE point of view */
 262         struct lancedata *alancedata;           /* Amiga point of view */
 263         int i;
 264 
 265         priv->lock = 0, priv->tx_full = 0;
 266         priv->cur_rx = priv->cur_tx = 0;
 267         priv->dirty_tx = 0;
 268 
 269         lancedata = (struct lancedata *)offsetof(struct A2065Board, RAM);
 270         alancedata = (struct lancedata *)board->RAM;
 271 
 272         /* Set up TX Ring */
 273         for (i = 0; i < TX_RING_SIZE; i++) {
 274                 alancedata->tx_ring[i].TMD0 = (u_long)lancedata->tx_buff[i];
 275                 alancedata->tx_ring[i].TMD1 = TF_STP|TF_ENP;
 276                 alancedata->tx_ring[i].TMD2 = -PKT_BUF_SIZE;
 277                 alancedata->tx_ring[i].TMD3 = 0x0000;
 278                 priv->tx_ring[i] = &alancedata->tx_ring[i];
 279                 priv->tx_buff[i] = alancedata->tx_buff[i];
 280 #if 0
 281                 printk("TX Entry %2d @ 0x%08x (LANCE 0x%08x), Buf @ 0x%08x (LANCE 0x%08x)\n", i,
 282                        (int)&alancedata->tx_ring[i],
 283                        (int)&lancedata->tx_ring[i],
 284                        (int)alancedata->tx_buff[i],
 285                        (int)lancedata->tx_buff[i]);
 286 #endif
 287         }
 288 
 289         /* Set up RX Ring */
 290         for (i = 0; i < RX_RING_SIZE; i++) {
 291                 alancedata->rx_ring[i].RMD0 = (u_long)lancedata->rx_buff[i];
 292                 alancedata->rx_ring[i].RMD1 = RF_OWN;
 293                 alancedata->rx_ring[i].RMD2 = -PKT_BUF_SIZE;
 294                 alancedata->rx_ring[i].RMD3 = 0x0000;
 295                 priv->rx_ring[i] = &alancedata->rx_ring[i];
 296                 priv->rx_buff[i] = alancedata->rx_buff[i];
 297 #if 0
 298                 printk("RX Entry %2d @ 0x%08x (LANCE 0x%08x), Buf @ 0x%08x (LANCE 0x%08x)\n", i,
 299                        (int)&alancedata->rx_ring[i],
 300                        (int)&lancedata->rx_ring[i],
 301                        (int)alancedata->rx_buff[i],
 302                        (int)lancedata->rx_buff[i]);
 303 #endif
 304         }
 305 }
 306 
 307 
 308 static int a2065_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 309 {
 310         struct a2065_private *priv = (struct a2065_private *)dev->priv;
 311         struct A2065Board *board = priv->board;
 312 
 313         dev->start = 0;
 314         dev->tbusy = 1;
 315 
 316         board->Lance.RAP = CSR0;                /* LANCE Controller Status */
 317 
 318         if (a2065_debug > 1) {
 319           printk("%s: Shutting down ethercard, status was %2.2x.\n",
 320                  dev->name, board->Lance.RDP);
 321           printk("%s: %d packets missed\n", dev->name,
 322                  priv->stats.rx_missed_errors);
 323         }
 324 
 325         /* We stop the LANCE here - it occasionally polls memory if we don't */
 326         board->Lance.RDP = STOP;
 327 
 328         return(0);
 329 }
 330 
 331 
 332 static void a2065_interrupt(int irq, struct pt_regs *fp, void *data)
     /* [previous][next][first][last][top][bottom][index][help] */
 333 {
 334         struct device *dev = (struct device *)data;
 335         struct a2065_private *priv;
 336         struct A2065Board *board;
 337         int csr0, boguscnt = 10;
 338 
 339         if (dev == NULL) {
 340                 printk("a2065_interrupt(): irq for unknown device.\n");
 341                 return;
 342         }
 343 
 344         priv = (struct a2065_private *)dev->priv;
 345         board = priv->board;
 346 
 347         board->Lance.RAP = CSR0;        /* LANCE Controller Status */
 348 
 349         if (!(board->Lance.RDP & INTR)) /* Check if any interrupt has
 350                                            been generated by the board. */
 351                 return;
 352 
 353         if (dev->interrupt)
 354                 printk("%s: Re-entering the interrupt handler.\n", dev->name);
 355 
 356         dev->interrupt = 1;
 357 
 358         while ((csr0 = board->Lance.RDP) & (ERR|RINT|TINT) && --boguscnt >= 0){
 359                 /* Acknowledge all of the current interrupt sources ASAP. */
 360                 board->Lance.RDP = csr0 & ~(INEA|TDMD|STOP|STRT|INIT);
 361 
 362 #if 0
 363                 if (a2065_debug > 5) {
 364                   printk("%s: interrupt  csr0=%#2.2x new csr=%#2.2x.",
 365                          dev->name, csr0, board->Lance.RDP);
 366                   printk("[");
 367                   if (csr0 & INTR)
 368                     printk(" INTR");
 369                   if (csr0 & INEA)
 370                     printk(" INEA");
 371                   if (csr0 & RXON)
 372                     printk(" RXON");
 373                   if (csr0 & TXON)
 374                     printk(" TXON");
 375                   if (csr0 & TDMD)
 376                     printk(" TDMD");
 377                   if (csr0 & STOP)
 378                     printk(" STOP");
 379                   if (csr0 & STRT)
 380                     printk(" STRT");
 381                   if (csr0 & INIT)
 382                     printk(" INIT");
 383                   if (csr0 & ERR)
 384                     printk(" ERR");
 385                   if (csr0 & BABL)
 386                     printk(" BABL");
 387                   if (csr0 & CERR)
 388                     printk(" CERR");
 389                   if (csr0 & MISS)
 390                     printk(" MISS");
 391                   if (csr0 & MERR)
 392                     printk(" MERR");
 393                   if (csr0 & RINT)
 394                     printk(" RINT");
 395                   if (csr0 & TINT)
 396                     printk(" TINT");
 397                   if (csr0 & IDON)
 398                     printk(" IDON");
 399                   printk(" ]\n");
 400                 }
 401 #endif
 402 
 403                 if (csr0 & RINT)                        /* Rx interrupt */
 404                         a2065_rx(dev);
 405 
 406                 if (csr0 & TINT) {                      /* Tx-done interrupt */
 407                         int dirty_tx = priv->dirty_tx;
 408 
 409                         while (dirty_tx < priv->cur_tx) {
 410                                 int entry = dirty_tx % TX_RING_SIZE;
 411                                 int status =
 412                                   priv->tx_ring[entry]->TMD1 & 0xff00;
 413 
 414                                 if (status & TF_OWN)
 415                                         break;  /* It still hasn't been Txed */
 416 
 417                                 priv->tx_ring[entry]->TMD1 &= 0x00ff;
 418 
 419                                 if (status & TF_ERR) {
 420                                         /* There was an major error, log it. */
 421                                         int err_status =
 422                                           priv->tx_ring[entry]->TMD3;
 423                                         priv->stats.tx_errors++;
 424                                         if (err_status & EF_RTRY)
 425                                           priv->stats.tx_aborted_errors++;
 426                                         if (err_status & EF_LCAR)
 427                                           priv->stats.tx_carrier_errors++;
 428                                         if (err_status & EF_LCOL)
 429                                           priv->stats.tx_window_errors++;
 430                                         if (err_status & EF_UFLO) {
 431                          /* Ackk!  On FIFO errors the Tx unit is turned off! */
 432                                           priv->stats.tx_fifo_errors++;
 433                                           /* Remove this verbosity later! */
 434                                           printk("%s: Tx FIFO error! Status %4.4x.\n", dev->name, csr0);
 435                                           /* Restart the chip. */
 436                                           board->Lance.RDP = STRT;
 437                                         }
 438                                 } else {
 439                                         if (status & (TF_MORE|TF_ONE))
 440                                           priv->stats.collisions++;
 441                                         priv->stats.tx_packets++;
 442                                 }
 443                                 dirty_tx++;
 444                         }
 445 
 446 #ifndef final_version
 447                         if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
 448                                 printk("out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
 449                                        dirty_tx, priv->cur_tx, priv->tx_full);
 450                                 dirty_tx += TX_RING_SIZE;
 451                         }
 452 #endif
 453 
 454                         if (priv->tx_full && dev->tbusy && dirty_tx >
 455                             priv->cur_tx - TX_RING_SIZE + 2) {
 456                                 /* The ring is no longer full, clear tbusy. */
 457                                 priv->tx_full = 0;
 458                                 dev->tbusy = 0;
 459                                 mark_bh(NET_BH);
 460                         }
 461 
 462                         priv->dirty_tx = dirty_tx;
 463                 }
 464 
 465                 /* Log misc errors. */
 466                 if (csr0 & BABL)
 467                         priv->stats.tx_errors++;       /* Tx babble. */
 468                 if (csr0 & MISS)
 469                         priv->stats.rx_errors++;       /* Missed a Rx frame. */
 470                 if (csr0 & MERR) {
 471                         printk("%s: Bus master arbitration failure, status %4.4x.\n", dev->name, csr0);
 472                         /* Restart the chip. */
 473                         board->Lance.RDP = STRT;
 474                 }
 475         }
 476 
 477         /* Clear any other interrupt, and set interrupt enable. */
 478         board->Lance.RAP = CSR0;                /* LANCE Controller Status */
 479         board->Lance.RDP = INEA|BABL|CERR|MISS|MERR|IDON;
 480 
 481 #if 0
 482         if (a2065_debug > 4)
 483                 printk("%s: exiting interrupt, csr%d=%#4.4x.\n",
 484                        dev->name, board->Lance.RAP, board->Lance.RDP);
 485 #endif
 486 
 487         dev->interrupt = 0;
 488         return;
 489 }
 490 
 491 
 492 static int a2065_start_xmit(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 493 {
 494         struct a2065_private *priv = (struct a2065_private *)dev->priv;
 495         struct A2065Board *board = priv->board;
 496         int entry;
 497 
 498         /* Transmitter timeout, serious problems. */
 499         if (dev->tbusy) {
 500                 int tickssofar = jiffies - dev->trans_start;
 501                 if (tickssofar < 20)
 502                         return(1);
 503                 board->Lance.RAP = CSR0;        /* LANCE Controller Status */
 504                 printk("%s: transmit timed out, status %4.4x, resetting.\n", dev->name, board->Lance.RDP);
 505                 board->Lance.RDP = STOP;
 506 
 507                 /* Enable big endian byte ordering */
 508                 board->Lance.RAP = CSR3;                        /* CSR3 */
 509                 board->Lance.RDP = BSWP;
 510 
 511                 priv->stats.tx_errors++;
 512 #ifndef final_version
 513                 {
 514                   int i;
 515                   printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
 516                          priv->dirty_tx, priv->cur_tx, priv->tx_full ?
 517                          " (full)" : "", priv->cur_rx);
 518                   for (i = 0 ; i < RX_RING_SIZE; i++)
 519                     printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
 520                            ((priv->rx_ring[i]->RMD1)<<16) |
 521                            priv->rx_ring[i]->RMD0,
 522                            -priv->rx_ring[i]->RMD2, priv->rx_ring[i]->RMD3);
 523                   for (i = 0 ; i < TX_RING_SIZE; i++)
 524                     printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
 525                            ((priv->tx_ring[i]->TMD1)<<16) |
 526                            priv->tx_ring[i]->TMD0,
 527                            -priv->tx_ring[i]->TMD2, priv->tx_ring[i]->TMD3);
 528                         printk("\n");
 529                 }
 530 #endif
 531                 a2065_init_ring(dev);
 532                 board->Lance.RDP = INEA|INIT;
 533 
 534                 dev->tbusy = 0;
 535                 dev->trans_start = jiffies;
 536 
 537                 return(0);
 538         }
 539 
 540         if (skb == NULL) {
 541                 dev_tint(dev);
 542                 return(0);
 543         }
 544 
 545         if (skb->len <= 0)
 546                 return(0);
 547 
 548 #if 0
 549         if (a2065_debug > 3) {
 550                 board->Lance.RAP = CSR0;        /* LANCE Controller Status */
 551                 printk("%s: a2065_start_xmit() called, csr0 %4.4x.\n",
 552                        dev->name, board->Lance.RDP);
 553                 board->Lance.RDP = 0x0000;
 554         }
 555 #endif
 556 
 557         /*
 558          * Block a timer-based transmit from overlapping.  This could better be
 559          * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
 560          */
 561         if (set_bit(0, (void*)&dev->tbusy) != 0) {
 562                 printk("%s: Transmitter access conflict.\n", dev->name);
 563                 return(1);
 564         }
 565 
 566         if (set_bit(0, (void*)&priv->lock) != 0) {
 567                 if (a2065_debug > 0)
 568                         printk("%s: tx queue lock!.\n", dev->name);
 569                 /* don't clear dev->tbusy flag. */
 570                 return(1);
 571         }
 572 
 573         /* Fill in a Tx ring entry */
 574 
 575 #if 0
 576         printk("TX pkt type 0x%04x from ", ((u_short *)skb->data)[6]);
 577         {
 578                 int i;
 579                 u_char *ptr = &((u_char *)skb->data)[6];
 580                 for (i = 0; i < 6; i++)
 581                         printk("%02x", ptr[i]);
 582         }
 583         printk(" to ");
 584         {
 585                 int i;
 586                 u_char *ptr = (u_char *)skb->data;
 587                 for (i = 0; i < 6; i++)
 588                         printk("%02x", ptr[i]);
 589         }
 590         printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
 591 #endif
 592 
 593         entry = priv->cur_tx % TX_RING_SIZE;
 594 
 595         priv->tx_ring[entry]->TMD2 = -(ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
 596         priv->tx_ring[entry]->TMD3 = 0x0000;
 597         memcpy(priv->tx_buff[entry], skb->data, skb->len);
 598 
 599 #if 0
 600         {
 601                 int i, len;
 602 
 603                 len = skb->len > 64 ? 64 : skb->len;
 604                 for (i = 0; i < len; i += 8) {
 605                         int j;
 606                         printk("%02x:", i);
 607                         for (j = 0; (j < 16) && ((i+j) < len); j++) {
 608                                 if (!(j & 1))
 609                                         printk(" ");
 610                                 printk("%02x", priv->tx_buff[entry][i+j]);
 611                         }
 612                         printk("\n");
 613                 }
 614         }
 615 #endif
 616 
 617         priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1 &
 618                                       0x00ff)|TF_OWN|TF_STP|TF_ENP;
 619 
 620         dev_kfree_skb(skb, FREE_WRITE);
 621 
 622         priv->cur_tx++;
 623         if ((priv->cur_tx >= TX_RING_SIZE)&&(priv->dirty_tx >= TX_RING_SIZE)){
 624 
 625 #if 0
 626           printk("*** Subtracting TX_RING_SIZE from cur_tx (%d) and dirty_tx (%d)\n",
 627                  priv->cur_tx, priv->dirty_tx);
 628 #endif
 629 
 630                 priv->cur_tx -= TX_RING_SIZE;
 631                 priv->dirty_tx -= TX_RING_SIZE;
 632         }
 633 
 634         /* Trigger an immediate send poll. */
 635         board->Lance.RAP = CSR0;                /* LANCE Controller Status */
 636         board->Lance.RDP = INEA|TDMD;
 637 
 638         dev->trans_start = jiffies;
 639 
 640         cli();
 641         priv->lock = 0;
 642         if ((priv->tx_ring[(entry+1) % TX_RING_SIZE]->TMD1 & 0xff00) == 0)
 643                 dev->tbusy = 0;
 644         else
 645                 priv->tx_full = 1;
 646         sti();
 647 
 648         return(0);
 649 }
 650 
 651 
 652 static int a2065_rx(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 653 {
 654         struct a2065_private *priv = (struct a2065_private *)dev->priv;
 655         int entry = priv->cur_rx % RX_RING_SIZE;
 656         int i;
 657 
 658         /* If we own the next entry, it's a new packet. Send it up. */
 659         while (!(priv->rx_ring[entry]->RMD1 & RF_OWN)) {
 660                 int status = priv->rx_ring[entry]->RMD1 & 0xff00;
 661 
 662                 if (status != (RF_STP|RF_ENP)) {      /* There was an error. */
 663                   /* There is a tricky error noted by John Murphy,
 664                      <murf@perftech.com> to Russ Nelson: Even with full-sized
 665                      buffers it's possible for a jabber packet to use two
 666                      buffers, with only the last correctly noting the error. */
 667                         if (status & RF_ENP)
 668                           /* Only count a general error at the */
 669                                 priv->stats.rx_errors++; /* end of a packet.*/
 670                         if (status & RF_FRAM)
 671                                 priv->stats.rx_frame_errors++;
 672                         if (status & RF_OFLO)
 673                                 priv->stats.rx_over_errors++;
 674                         if (status & RF_CRC)
 675                                 priv->stats.rx_crc_errors++;
 676                         if (status & RF_BUFF)
 677                                 priv->stats.rx_fifo_errors++;
 678                         priv->rx_ring[entry]->RMD1 &= 0x00ff|RF_STP|RF_ENP;
 679                 } else {
 680                         /* Malloc up new buffer, compatible with net-3. */
 681                         short pkt_len = priv->rx_ring[entry]->RMD3;
 682                         struct sk_buff *skb;
 683 
 684                         if(pkt_len<60)
 685                         {
 686                                 printk("%s: Runt packet!\n",dev->name);
 687                                 priv->stats.rx_errors++;
 688                         }
 689                         else
 690                         {
 691                                 skb = dev_alloc_skb(pkt_len+2);
 692                                 if (skb == NULL) {
 693                                         printk("%s: Memory squeeze, deferring packet.\n", dev->name);
 694                                         for (i = 0; i < RX_RING_SIZE; i++)
 695                                                 if (priv->rx_ring[(entry+i) % RX_RING_SIZE]->RMD1 & RF_OWN)
 696                                                         break;
 697 
 698                                         if (i > RX_RING_SIZE-2) {
 699                                                 priv->stats.rx_dropped++;
 700                                                 priv->rx_ring[entry]->RMD1 |= RF_OWN;
 701                                                 priv->cur_rx++;
 702                                         }
 703                                         break;
 704                                 }
 705                                 skb->dev = dev;
 706                                 skb_reserve(skb,2);     /* 16 byte align */
 707                                 skb_put(skb,pkt_len);   /* Make room */
 708                                 eth_copy_and_sum(skb,
 709                                                  priv->rx_buff[entry],
 710                                                  pkt_len,0);
 711                                 skb->protocol=eth_type_trans(skb,dev);
 712 #if 0
 713                                 printk("RX pkt type 0x%04x from ", 
 714                                        ((u_short *)skb->data)[6]);
 715                                 {
 716                                   int i;
 717                                   u_char *ptr = &((u_char *)skb->data)[6];
 718                                   for (i = 0; i < 6; i++)
 719                                     printk("%02x", ptr[i]);
 720                                 }
 721                                 printk(" to ");
 722                                 {
 723                                   int i;
 724                                   u_char *ptr = (u_char *)skb->data;
 725                                   for (i = 0; i < 6; i++)
 726                                     printk("%02x", ptr[i]);
 727                                 }
 728                                 printk(" data 0x%08x len %d\n",
 729                                        (int)skb->data, (int)skb->len);
 730 #endif
 731 
 732                                 netif_rx(skb);
 733                                 priv->stats.rx_packets++;
 734                         }
 735                 }
 736                 priv->rx_ring[entry]->RMD1 |= RF_OWN;
 737                 entry = (++priv->cur_rx) % RX_RING_SIZE;
 738         }
 739 
 740         priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
 741 
 742         /* We should check that at least two ring entries are free.
 743            If not, we should free one and mark stats->rx_dropped++. */
 744 
 745         return(0);
 746 }
 747 
 748 
 749 static struct enet_statistics *a2065_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 750 {
 751         struct a2065_private *priv = (struct a2065_private *)dev->priv;
 752 
 753         return(&priv->stats);
 754 }
 755 
 756 
 757 /* Set or clear the multicast filter for this adaptor.
 758  */
 759 static void set_multicast_list(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 760 {
 761         struct a2065_private *priv = (struct a2065_private *)dev->priv;
 762         struct A2065Board *board = priv->board;
 763         struct lancedata *alancedata;         /* Amiga point of view */
 764         alancedata = (struct lancedata *)board->RAM;
 765 
 766         /* We take the simple way out and always enable promiscuous mode. */
 767         board->Lance.RAP = CSR0;              /* LANCE Controller Status */
 768         board->Lance.RDP = STOP;              /* Temporarily stop the lance. */
 769 
 770         /* Enable big endian byte ordering */
 771         board->Lance.RAP = CSR3;              /* CSR3 */
 772         board->Lance.RDP = BSWP;
 773 
 774         if (dev->flags&IFF_PROMISC) {
 775           /* Log any net taps. */
 776           printk("%s: Promiscuous mode enabled.\n", dev->name);
 777           alancedata->init.Mode = PROM;       /* Set promiscuous mode */
 778         } else {
 779           short multicast_table[4];
 780           int num_addrs=dev->mc_count;
 781           if(dev->flags&IFF_ALLMULTI)
 782                 num_addrs=1;
 783           /*
 784            * We don't use the multicast table,
 785            * but rely on upper-layer filtering.
 786            */
 787           memset(multicast_table, (num_addrs == 0) ? 0 : -1,
 788                  sizeof(multicast_table));
 789           alancedata->init.LADRF[0] = multicast_table[0]<<16 |
 790             multicast_table[1];
 791           alancedata->init.LADRF[1] = multicast_table[2]<<16 |
 792             multicast_table[3];
 793           alancedata->init.Mode = 0x0000;
 794         }
 795 
 796         board->Lance.RAP = CSR0;                /* LANCE Controller Status */
 797         board->Lance.RDP = INEA|STRT|IDON|INIT; /* Resume normal operation. */
 798 }

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