root/net/tcp/we.c

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

DEFINITIONS

This source file includes following definitions.
  1. max
  2. wd_start
  3. wd8003_open
  4. wdget
  5. wd8003_start_xmit
  6. wd_put_bnd
  7. wd_get_bnd
  8. wd_get_cur
  9. wd_rcv
  10. wd_rx_over
  11. wd_trs
  12. wd8003_interrupt
  13. wd8003_init

   1 /* we.c an wd8003 and wd8013 ethernet driver for linux. */
   2 /*
   3     Copyright (C) 1992  Ross Biro
   4 
   5     This program is free software; you can redistribute it and/or modify
   6     it under the terms of the GNU General Public License as published by
   7     the Free Software Foundation; either version 2, or (at your option)
   8     any later version.
   9 
  10     This program is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13     GNU General Public License for more details.
  14 
  15     You should have received a copy of the GNU General Public License
  16     along with this program; if not, write to the Free Software
  17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  18 
  19     The Author may be reached as bir7@leland.stanford.edu or
  20     C/O Department of Mathematics; Stanford University; Stanford, CA 94305
  21 */
  22 /* The bsd386 version was used as an example in order to write this
  23    code */
  24 
  25 /*
  26         The driver was significantly modified by Bob Harris to allow the
  27         software to operate with either the wd8003 or wd8013 boards.  The
  28         wd8013 boards will operate using full memory on board (as specified
  29         by the user in Space.c) and the 16 bit wide interface.  The driver
  30         will autodetect which board it is using on boot (i.e. "using 16 bit I/F").
  31         In addition, the interrupts structure was significantly modified to 
  32         respond to all the chips interrupts and to keep track of statistics.
  33         The statistics are not currently used.  Debug messages can be toggled
  34         by setting the wd_debug variable to a non-zero number.   The driver 
  35         can detect an open or shorted cable - the wd8013 board functions after
  36         the problem is corrected, but the wd8003 board does not always recover.
  37         The driver is gradually being migrated toward the National Semiconductor
  38         recommendations.  Constructive comments or suggestions can be sent to:
  39 
  40                 Bob Harris, rth@sparta.com
  41                 7926 Jones Branch Drive, Suite 900
  42                 McLean, Va. 22102
  43 */
  44 /* Note:  My driver was full of bugs.  Basically if it works, credit
  45    Bob Harris.  If it's broken blame me.  -RAB */
  46 
  47 #include <linux/config.h>
  48 #include <linux/kernel.h>
  49 #include <linux/sched.h>
  50 #include <linux/fs.h>
  51 #include <linux/tty.h>
  52 #include <linux/types.h>
  53 #include <linux/ptrace.h>
  54 #include <asm/system.h>
  55 #include <asm/segment.h>
  56 #include <asm/io.h>
  57 #include <asm/memory.h>
  58 #include <errno.h>
  59 #include <linux/fcntl.h>
  60 #include <netinet/in.h>
  61 
  62 #include "dev.h"
  63 #include "eth.h"
  64 #include "timer.h"
  65 #include "ip.h"
  66 #include "tcp.h"
  67 #include "sock.h"
  68 #include "arp.h"
  69 
  70 #include "wereg.h"
  71 
  72 static unsigned char interrupt_mask;
  73 /* format of status byte. 
  74    bit 
  75     0   start
  76     1   open
  77     2   transmitter in use */
  78 
  79 #define START 1
  80 #define OPEN  2
  81 #define TRS_BUSY 0x400
  82 #define IN_INT 8
  83 
  84 /* We need to get rid of all these statics and move them into the
  85    device structure that way we can have more than one wd8003 board
  86    in the system at once. */
  87 
  88 static volatile unsigned int status;
  89 
  90 static struct enet_statistics stats;    /* Statistics collection */
  91 static unsigned char max_pages;         /* Board memory/256 */
  92 static unsigned char wd_debug = 0;      /* turns on/off debug messages */
  93 static unsigned char dconfig = WD_DCONFIG;      /* default data configuration */
  94 static int tx_aborted = 0;                      /* Empties tx bit bucket */
  95 
  96 static  int
  97 max(int a, int b)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99   if (a>b) return (a);
 100   return (b);
 101 }
 102 
 103 static  void
 104 wd_start(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 105 {
 106   unsigned char cmd;
 107   interrupt_mask=RECV_MASK|TRANS_MASK;
 108   cli();
 109   cmd = inb_p(WD_COMM);
 110   cmd &= ~(CSTOP|CPAGE);
 111   cmd |= CSTART;
 112   outb_p(cmd, WD_COMM);
 113   outb_p(interrupt_mask,WD_IMR);
 114   sti();
 115   status |= START;
 116 }
 117 
 118 int
 119 wd8003_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121   unsigned char cmd;
 122   int i;
 123   /* we probably don't want to be interrupted here. */
 124   cli();
 125   /* This section of code is mostly copied from the bsd driver which is
 126      mostly copied from somewhere else. */
 127   /* The somewhere else is probably the cmwymr(sp?) dos packet driver */
 128 
 129   cmd=inb_p(WD_COMM);
 130   cmd|=CSTOP;
 131   cmd &= ~(CSTART|CPAGE);
 132   outb_p(cmd, WD_COMM);
 133   outb_p(0, WD_IMR);
 134   sti();
 135   outb_p( dconfig,WD_DCR);
 136   /*Zero the remote byte count. */
 137   outb_p(0, WD_RBY0);
 138   outb_p(0, WD_RBY1);
 139   outb_p(WD_MCONFIG,WD_RCC);
 140   outb_p(WD_TCONFIG,WD_TRC);
 141   outb_p(0,WD_TRPG);             /* Set the transmit page start = 0 */
 142   outb_p( max_pages,WD_PSTOP); /* (read) page stop = top of board memory */
 143   outb_p(WD_TXBS,WD_PSTRT);     /* (read) page start = cur = bnd = top of tx memory */
 144   outb_p(WD_TXBS,WD_BNDR);
 145   /* clear interrupt status. */
 146   outb_p(0xff,WD_ISR);
 147   /* we don't want no stinking interrupts. */
 148   outb_p(0 ,WD_IMR);
 149   cmd|=1<<CPAGE_SHIFT;
 150   outb_p(cmd,WD_COMM);
 151   /* set the ether address. */
 152   for (i=0; i < ETHER_ADDR_LEN; i++)
 153     {
 154       outb_p(dev->dev_addr[i],WD_PAR0+i);
 155     }
 156   /* National recommends setting the boundry < current page register */
 157   outb_p(WD_TXBS+1,WD_CUR);     /* Set the current page = page start + 1 */
 158   /* set the multicast address. */
 159   for (i=0; i < ETHER_ADDR_LEN; i++)
 160     {
 161       outb_p(dev->broadcast[i],WD_MAR0+i);
 162     }
 163 
 164   cmd&=~(CPAGE|CRDMA);
 165   cmd|= 4<<CRDMA_SHIFT;
 166   outb_p(cmd, WD_COMM);
 167   outb_p(WD_RCONFIG,WD_RCC);
 168   status = OPEN;
 169   wd_start(dev); 
 170   return (0);
 171 }
 172 
 173 /* This routine just calls the ether rcv_int. */
 174 static  int
 175 wdget(struct wd_ring *ring, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177   unsigned char *fptr;
 178   unsigned long len;
 179   fptr = (unsigned char *)(ring +1);
 180   len = ring->count-4;
 181   return (dev_rint(fptr, len, 0, dev));
 182 }
 183 
 184 int
 185 wd8003_start_xmit(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187   unsigned char cmd;
 188   int len;
 189   cli();
 190   if (status & TRS_BUSY)
 191     {
 192        /* put in a time out. */
 193        if (jiffies - dev->trans_start < 30)
 194          return (1);
 195        printk ("wd8003 transmit timed out. \n");
 196     }
 197   status |= TRS_BUSY;
 198   sti();
 199 
 200   if (!skb->arp)
 201     {
 202       if ( dev->rebuild_header (skb+1, dev)) 
 203         {
 204            skb->dev = dev;
 205            arp_queue (skb);
 206            status &= ~TRS_BUSY;
 207            return (0);
 208         }
 209     }
 210 
 211   memcpy ((unsigned char *)dev->mem_start, skb+1, skb->len);
 212 
 213   len = skb->len;
 214 
 215   /* now we need to set up the card info. */
 216   dev->trans_start = jiffies;
 217   len=max(len, ETHER_MIN_LEN); /* actually we should zero out
 218                                   the extra memory. */
 219 /*  printk ("start_xmit len - %d\n", len);*/
 220   cli();
 221   cmd=inb_p(WD_COMM);
 222   cmd &= ~CPAGE;
 223   outb_p(cmd, WD_COMM);
 224 
 225   interrupt_mask |= TRANS_MASK;
 226   if (!(status & IN_INT))
 227     outb (interrupt_mask, WD_IMR);
 228 
 229   outb_p(len&0xff,WD_TB0);
 230   outb_p(len>>8,WD_TB1);
 231   cmd |= CTRANS;
 232   outb_p(cmd,WD_COMM);
 233   sti();
 234   
 235   if (skb->free)
 236     {
 237             free_skb (skb, FREE_WRITE);
 238     }
 239 
 240   return (0);
 241 }
 242 
 243 /* tell the card about the new boundary. */
 244 
 245 static  void
 246 wd_put_bnd(unsigned char bnd, struct device *dev )
     /* [previous][next][first][last][top][bottom][index][help] */
 247 {
 248 
 249         unsigned char cmd;
 250 
 251         /* Ensure page 0 selected */
 252         cmd = inb_p( CR );
 253         if (cmd & 0x40) {
 254                 outb_p(cmd & (~CPAGE1), WD_COMM);       /* select page 0 */
 255                 outb_p(bnd, WD_BNDR);
 256                 outb_p(cmd | CPAGE1, WD_COMM);  /* reselect page 1 */
 257         } else {
 258                 outb_p(bnd, WD_BNDR);
 259         }
 260 }
 261 
 262 static  unsigned char
 263 wd_get_bnd( struct device *dev )
     /* [previous][next][first][last][top][bottom][index][help] */
 264 {
 265 
 266         unsigned char   cmd, bnd;
 267 
 268         /* Ensure page 0 selected */
 269         cmd = inb_p(WD_COMM);
 270         if (cmd & 0x40) {
 271                 outb_p(cmd & (~CPAGE1), WD_COMM);       /* select page 0 */
 272                 bnd = inb_p(WD_BNDR);
 273                 outb_p(cmd | CPAGE1, WD_COMM);  /* reselect page 1 */
 274                 return (bnd);
 275         } else {
 276                 return (inb_p(WD_BNDR));
 277         }
 278 }
 279 
 280 static  unsigned char
 281 wd_get_cur( struct device *dev )
     /* [previous][next][first][last][top][bottom][index][help] */
 282 {
 283 
 284         unsigned char   cmd, cur;
 285 
 286         /* Ensure page 1 selected */
 287         cmd = inb_p(WD_COMM);
 288         if (cmd & 0x40) {
 289                 return (inb_p(WD_CUR));
 290         } else {
 291                 outb_p(cmd | CPAGE1, WD_COMM);  /* select page 1 */
 292                 cur = inb_p(WD_CUR);
 293                 outb_p(cmd & (~CPAGE1), WD_COMM);       /* reselect page 0 */
 294                 return (cur);
 295         }
 296 }
 297 
 298 /* This routine handles the packet recieved interrupt. */
 299 /* Debug routines slow things down, but reveal bugs... */
 300 /* Modified Boundry Page Register to follow Current Page */
 301 
 302 static  void
 303 wd_rcv( struct device *dev )
     /* [previous][next][first][last][top][bottom][index][help] */
 304 {
 305    
 306    unsigned char   pkt; /* Next packet page start */
 307    unsigned char   bnd; /* Last packet page end */
 308    unsigned char   cur; /* Future packet page start */
 309    unsigned char   cmd; /* Command register save */
 310    struct wd_ring *ring;
 311    int             done=0;
 312    
 313    /* Calculate next packet location */
 314    cur = wd_get_cur( dev );
 315    bnd = wd_get_bnd( dev );
 316    if( (pkt = bnd + 1) == max_pages )
 317      pkt = WD_TXBS;
 318    
 319    while( done != 1)
 320      {
 321         if (pkt != cur)
 322           {
 323 
 324              /* Position pointer to packet in card ring buffer */
 325              ring = (struct wd_ring *) (dev->mem_start + (pkt << 8));
 326              
 327              /* Ensure a valid packet */
 328              if( ring->status & 1 )
 329                { 
 330                   /* Too small and too big packets are
 331                      filtered by the board */
 332                   if( wd_debug )
 333                     printk("\nwd8013 - wdget: bnd = %d, pkt = %d, "
 334                            "cur = %d, status = %d, len = %d, next = %d",
 335                            bnd, pkt, cur, ring->status, ring->count,
 336                            ring->next);
 337                   
 338                   stats.rx_packets++; /* count all receives */
 339                   done = wdget( ring, dev ); /* get the packet */
 340                   
 341                   /* see if we need to process this packet again. */
 342                   if (done == -1) continue;
 343 
 344                   /* Calculate next packet location */
 345                   pkt = ring->next;
 346                   
 347                   /* Compute new boundry - tell the chip */
 348                   if( (bnd = pkt - 1) < WD_TXBS )
 349                     bnd = max_pages - 1;
 350                   wd_put_bnd(bnd, dev);
 351                   
 352                   /* update our copy of cur. */
 353                   cur = wd_get_cur(dev);
 354                }
 355              else 
 356                {        /* Bad packet in ring buffer -
 357                            should not happen due to hardware filtering */
 358                   printk("wd8013 - bad packet: len = %d, status = x%x, "
 359                          "bnd = %d, pkt = %d, cur = %d\n"
 360                          "trashing receive buffer!",
 361                          ring->count, ring->status, bnd, pkt,
 362                          cur);
 363                   /* Reset bnd = cur-1 */
 364                   if( ( bnd = wd_get_cur( dev ) - 1 ) < WD_TXBS )
 365                     bnd = max_pages - 1;
 366                   wd_put_bnd( bnd, dev );
 367                   break; /* return */
 368                }
 369              
 370           }
 371         else
 372           {
 373              done = dev_rint(NULL, 0,0, dev);
 374           }
 375      }
 376    
 377    /* reset to page 0 */
 378    cmd = inb_p(WD_COMM);
 379    if (cmd & 0x40)
 380      {
 381         outb_p(cmd & ~(CPAGE1), WD_COMM);       /* select page 0 */
 382      }
 383 }
 384 
 385 /* This routine handles the interrupt case of receiver overruns */
 386 
 387 static  void
 388 wd_rx_over( struct device *dev )
     /* [previous][next][first][last][top][bottom][index][help] */
 389 {
 390         unsigned char cmd, dummy;
 391 
 392         /* Nothing actually has been overwritten */
 393         /* the chip has stopped at the boundry */
 394         /* but we must get it going again - according to National Semiconductor */
 395         printk ("wd_rx_over\n");
 396         cmd = inb_p( CR ); /* get current command register */
 397         cmd = (cmd&~(STA|PS0|PS1))|STOP; /* toggle start and stop bits, select page 0 */
 398         outb_p( cmd, CR );
 399         dummy = inb_p( RBCR0 ); /* required to detect reset status */
 400         dummy = inb_p( RBCR1 );
 401         wd_rcv( dev );  /* clear out received packets */
 402         
 403         if( inb_p( ISR ) & PRX )
 404                 outb_p( PRX, ISR ); /* acknowledge RX interrupt */
 405         while( ( inb_p( ISR ) & RST ) == 0 ); /* wait for reset to be completed */
 406         outb_p( RST, ISR ); /* acknowledge RST interrupt */
 407         outb_p( (cmd&~STOP)|STA, CR ); /* Start NIC */  
 408         outb_p( WD_TCONFIG, TCR ); /* resume normal mode */
 409 }
 410 
 411 /*
 412  * This get's the transmit interrupts. It assumes command page 0 is set, and
 413  * returns with command page 0 set.
 414  */
 415 
 416 static  void
 417 wd_trs( struct device *dev )
     /* [previous][next][first][last][top][bottom][index][help] */
 418 {
 419         unsigned char cmd, errors;
 420         int len;
 421 
 422         if( wd_debug )
 423                 printk("\nwd_trs() - TX complete, status = x%x", inb_p(TSR));
 424 
 425         if( ( errors = inb_p( TSR ) & PTXOK  ) || tx_aborted ){
 426                 if( (errors&~0x02) == 0 ){
 427                         stats.tx_packets++;
 428                         tx_aborted = 0;
 429                 }
 430                 
 431                 /* attempt to start a new transmission. */
 432                 len = dev_tint( (unsigned char *)dev->mem_start, dev );
 433                 if( len != 0 ){
 434                         len=max(len, ETHER_MIN_LEN);
 435                         cmd=inb_p(WD_COMM);
 436                         outb_p(len&0xff,WD_TB0);
 437                         outb_p(len>>8,WD_TB1);
 438                         cmd |= CTRANS;
 439                         outb_p(cmd,WD_COMM);
 440                         interrupt_mask |= TRANS_MASK;
 441                 }
 442                 else
 443                 {
 444                         status &= ~TRS_BUSY;
 445                         interrupt_mask &= ~TRANS_MASK;
 446                         return;
 447                 }
 448         }
 449         else{ /* TX error occurred! - H/W will reschedule */
 450                 if( errors & CRS ){
 451                         stats.tx_carrier_errors++;
 452                         printk("\nwd8013 - network cable short!");
 453                 }
 454                 if (errors & COL )
 455                         stats.collisions += inb_p( NCR );
 456                 if (errors & CDH )
 457                         stats.tx_heartbeat_errors++;
 458                 if (errors & OWC )
 459                         stats.tx_window_errors++;
 460         }
 461 }
 462 
 463 void
 464 wd8003_interrupt(int reg_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 465 {
 466         unsigned char   cmd;
 467         unsigned char   errors;
 468         unsigned char   isr;
 469         struct device *dev;
 470         struct pt_regs *ptr;
 471         int irq;
 472         int count = 0;
 473 
 474         ptr = (struct pt_regs *)reg_ptr;
 475         irq = -(ptr->orig_eax+2);
 476         for (dev = dev_base; dev != NULL; dev = dev->next)
 477           {
 478              if (dev->irq == irq) break;
 479           }
 480         if (dev == NULL) 
 481           {
 482              printk ("we.c: irq %d for unknown device\n", irq);
 483              return;
 484           }
 485         sti(); /* this could take a long time, we should have interrupts on. */
 486 
 487         cmd = inb_p( CR );/* Select page 0 */  
 488         if( cmd & (PS0|PS1 ) ){
 489                 cmd &= ~(PS0|PS1);
 490                 outb_p(cmd, CR );
 491         }
 492         
 493         if (wd_debug)
 494                 printk("\nwd8013 - interrupt isr = x%x", inb_p( ISR ) );
 495 
 496         status |= IN_INT;
 497 
 498         do{ /* find out who called */ 
 499 
 500                 /* Check for overrunning receive buffer first */
 501                 if ( ( isr = inb_p( ISR ) ) & OVW ) {   /* Receiver overwrite warning */
 502                         stats.rx_over_errors++;
 503                         if( wd_debug )
 504                                 printk("\nwd8013 overrun bnd = %d, cur = %d", wd_get_bnd( dev ), wd_get_cur( dev ) );
 505                         wd_rx_over( dev ); /* performs wd_rcv() as well */
 506                         outb_p( OVW, ISR ); /* acknowledge interrupt */
 507                 } 
 508                 else if ( isr & PRX ) { /* got a packet. */
 509                         wd_rcv( dev );
 510                         outb_p( PRX, ISR ); /* acknowledge interrupt */
 511                 }
 512                 /* This completes rx processing... whats next */
 513 
 514                 if ( inb_p( ISR ) & PTX ) {     /* finished sending a packet. */
 515                         wd_trs( dev );
 516                         outb_p( PTX, ISR ); /* acknowledge interrupt */
 517                 }
 518 
 519                 if (inb_p( ISR ) & RXE ) {      /* recieve error */
 520                         stats.rx_errors++; /* general errors */
 521                         errors = inb_p( RSR ); /* detailed errors */
 522                         if (errors & CRC )
 523                                 stats.rx_crc_errors++;
 524                         if (errors & FAE )
 525                                 stats.rx_frame_errors++;
 526                         if (errors & FO )
 527                                 stats.rx_fifo_errors++;
 528                         if (errors & MPA )
 529                                 stats.rx_missed_errors++;
 530                         outb_p( RXE, ISR ); /* acknowledge interrupt */
 531                 }
 532 
 533                 if (inb_p( ISR ) & TXE ) {      /* transmit aborted! */
 534                         stats.tx_errors++; /* general errors */
 535                         errors = inb_p( TSR ); /* get detailed errors */
 536                         if (errors & ABT ){
 537                                 stats.tx_aborted_errors++;
 538                                 printk("\nwd8013 - network cable open!");
 539                         }
 540                         if (errors & FU )
 541                                 stats.tx_fifo_errors++;
 542                                 printk("\nwd8013 - TX FIFO underrun!");
 543 
 544                         /* Cannot do anymore - empty the bit bucket */
 545                         tx_aborted = 1;
 546                         wd_trs( dev );
 547                         tx_aborted = 0;
 548 
 549                         outb_p( TXE, ISR ); /* acknowledge interrupt */
 550                 }
 551 
 552                 if( inb_p( ISR ) & CNTE ){ /* Tally counters overflowing */
 553                         errors = inb_p( CNTR0 );
 554                         errors = inb_p( CNTR1 );
 555                         errors = inb_p( CNTR2 );
 556                         outb_p( CNTE, ISR ); /* acknowledge interrupt */
 557                 }
 558                 if( inb_p( ISR ) & RST ) /* Reset has been performed */
 559                         outb_p( RST, ISR ); /* acknowledge interrupt */
 560 
 561                 if( wd_debug ){
 562                         if( ( isr = inb_p( ISR ) ) != 0 )
 563                                 printk("\nwd8013 - ISR not cleared = x%x", isr );
 564                 }
 565                 if( ++count > max_pages + 1 ){
 566                         printk("\nwd8013_interrupt - infinite loop detected, isr = x%x, count = %d", isr, count );
 567                 }
 568 
 569         } while( inb_p( ISR ) != 0 );
 570 
 571         status &= ~IN_INT;
 572 }
 573 
 574 
 575 static struct sigaction wd8003_sigaction = 
 576 {
 577    wd8003_interrupt,
 578    0,
 579    0,
 580    NULL
 581 };
 582 
 583 void
 584 wd8003_init(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 585 {
 586   unsigned char csum;
 587   int i;
 588   csum = 0;
 589   for (i = 0; i < 8; i++)
 590     {
 591       csum += inb_p(WD_ROM+i);
 592     }
 593   if (csum != WD_CHECK)
 594     {
 595       printk ("Warning WD8013 board not found at i/o = %X.\n",dev->base_addr);
 596 
 597       /* make sure no one can attempt to open the device. */
 598       status = OPEN;
 599       return;
 600     }
 601   printk("wd8013");
 602   /* initialize the rest of the device structure. */
 603   dev->mtu = 1500; /* eth_mtu */
 604   dev->hard_start_xmit = wd8003_start_xmit;
 605   dev->open = wd8003_open;
 606   dev->hard_header = eth_hard_header;
 607   dev->add_arp = eth_add_arp;
 608   dev->type_trans = eth_type_trans;
 609   dev->hard_header_len = sizeof (struct enet_header);
 610   dev->addr_len = ETHER_ADDR_LEN;
 611   dev->type = ETHER_TYPE;
 612   dev->queue_xmit = dev_queue_xmit;
 613   dev->rebuild_header = eth_rebuild_header;
 614   for (i = 0; i < DEV_NUMBUFFS; i++)
 615     dev->buffs[i] = NULL;
 616 
 617 #ifndef FORCE_8BIT
 618   /* check for 16 bit board - it doesn't have register 0/8 aliasing */
 619   for (i = 0; i < 8; i++) {
 620         if( inb_p( EN_SAPROM+i ) != inb_p( EN_CMD+i) ){
 621                 csum = inb_p( EN_REG1 ); /* fiddle with 16bit bit */
 622                 outb( csum ^ BUS16, EN_REG1 ); /* attempt to clear 16bit bit */
 623                 if( (csum & BUS16) == (inb_p( EN_REG1 ) & BUS16) ) {
 624                         printk(", using 16 bit I/F ");
 625                         dconfig |= 1; /* use word mode of operation */
 626                         outb_p( LAN16ENABLE|MEMMASK, EN_REG5);
 627                         outb( csum , EN_REG1 );
 628                         break; /* We have a 16bit board here! */
 629                 }
 630                 outb( csum , EN_REG1 );
 631         }
 632     }
 633 #endif /* FORCE_8BIT */
 634 
 635   /* mapin the interface memory. */
 636   outb_p(WD_IMEM,WD_CTL);
 637 
 638   /* clear the interface memory */
 639   for (i = dev->mem_start; i < dev->mem_end; i++)
 640     {
 641       *((unsigned char *)i) = 0;
 642       if (*((unsigned char *)i) != 0) 
 643         {
 644           printk ("WD Memory error.\n");
 645           if( (i - dev->mem_start) > 4096 )
 646                 break;
 647           else
 648                 status = OPEN;
 649         }
 650     }
 651   /* Calculate how many pages of memory on board */
 652   max_pages = ( i - dev->mem_start )/256;
 653 
 654   /* need to set up the dev->mem_end and dev->rmem_end */
 655   dev->rmem_end = i;
 656   dev->mem_end = i;
 657 
 658   /* print the initialization message, and the
 659      ethernet address. */
 660   printk (", %d pages memory, ethernet Address: ", max_pages );
 661   for (i = 0; i <ETHER_ADDR_LEN; i++)
 662     {
 663       dev->dev_addr[i]=inb_p(WD_ROM+i);
 664       dev->broadcast[i]=0xff;
 665       printk ("%2.2X ",dev->dev_addr[i]);
 666     }
 667 
 668   /* Clear the statistics */
 669   for( i = 0; i < sizeof( struct enet_statistics ); i++ )
 670         ((char *)&stats)[i] = 0;
 671 
 672   printk ("\n");
 673   status = 0;
 674 
 675   if (irqaction (dev->irq, &wd8003_sigaction))
 676     {
 677        printk ("Unable to get IRQ%d for wd8013 board\n", dev->irq);
 678     }
 679 }

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