root/net/drv/we8003/handler.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. we8003_probe
  14. we8003_8bit
  15. we8003_cmem
  16. we8003_geth
  17. we8003_conf

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

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