Annotation of Gnu-Mach/linux/src/drivers/net/wavelan.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *     WaveLAN ISA driver
        !             3:  *
        !             4:  *             Jean II - HPLB '96
        !             5:  *
        !             6:  * Reorganisation and extension of the driver.
        !             7:  * Original copyright follows (also see the end of this file).
        !             8:  * See wavelan.p.h for details.
        !             9:  */
        !            10: 
        !            11: /*
        !            12:  * AT&T GIS (nee NCR) WaveLAN card:
        !            13:  *     An Ethernet-like radio transceiver
        !            14:  *     controlled by an Intel 82586 coprocessor.
        !            15:  */
        !            16: 
        !            17: #include "wavelan.p.h"         /* Private header */
        !            18: 
        !            19: /************************* MISC SUBROUTINES **************************/
        !            20: /*
        !            21:  * Subroutines which won't fit in one of the following category
        !            22:  * (WaveLAN modem or i82586)
        !            23:  */
        !            24: 
        !            25: /*------------------------------------------------------------------*/
        !            26: /*
        !            27:  * Wrapper for disabling interrupts.
        !            28:  */
        !            29: static inline unsigned long
        !            30: wv_splhi(void)
        !            31: {
        !            32:   unsigned long flags;
        !            33: 
        !            34:   save_flags(flags);
        !            35:   cli();
        !            36: 
        !            37:   return(flags);
        !            38: }
        !            39: 
        !            40: /*------------------------------------------------------------------*/
        !            41: /*
        !            42:  * Wrapper for re-enabling interrupts.
        !            43:  */
        !            44: static inline void
        !            45: wv_splx(unsigned long  flags)
        !            46: {
        !            47:   restore_flags(flags);
        !            48: }
        !            49: 
        !            50: /*------------------------------------------------------------------*/
        !            51: /*
        !            52:  * Translate irq number to PSA irq parameter
        !            53:  */
        !            54: static u_char
        !            55: wv_irq_to_psa(int      irq)
        !            56: {
        !            57:   if(irq < 0 || irq >= NELS(irqvals))
        !            58:     return 0;
        !            59: 
        !            60:   return irqvals[irq];
        !            61: }
        !            62: 
        !            63: /*------------------------------------------------------------------*/
        !            64: /*
        !            65:  * Translate PSA irq parameter to irq number 
        !            66:  */
        !            67: static int
        !            68: wv_psa_to_irq(u_char   irqval)
        !            69: {
        !            70:   int  irq;
        !            71: 
        !            72:   for(irq = 0; irq < NELS(irqvals); irq++)
        !            73:     if(irqvals[irq] == irqval)
        !            74:       return irq;
        !            75: 
        !            76:   return -1;
        !            77: }
        !            78: 
        !            79: #ifdef STRUCT_CHECK
        !            80: /*------------------------------------------------------------------*/
        !            81: /*
        !            82:  * Sanity routine to verify the sizes of the various WaveLAN interface
        !            83:  * structures.
        !            84:  */
        !            85: static char *
        !            86: wv_struct_check(void)
        !            87: {
        !            88: #define        SC(t,s,n)       if (sizeof(t) != s) return(n);
        !            89: 
        !            90:   SC(psa_t, PSA_SIZE, "psa_t");
        !            91:   SC(mmw_t, MMW_SIZE, "mmw_t");
        !            92:   SC(mmr_t, MMR_SIZE, "mmr_t");
        !            93:   SC(ha_t, HA_SIZE, "ha_t");
        !            94: 
        !            95: #undef SC
        !            96: 
        !            97:   return((char *) NULL);
        !            98: } /* wv_struct_check */
        !            99: #endif /* STRUCT_CHECK */
        !           100: 
        !           101: /********************* HOST ADAPTER SUBROUTINES *********************/
        !           102: /*
        !           103:  * Useful subroutines to manage the WaveLAN ISA interface
        !           104:  *
        !           105:  * One major difference with the PCMCIA hardware (except the port mapping)
        !           106:  * is that we have to keep the state of the Host Control Register
        !           107:  * because of the interrupt enable & bus size flags.
        !           108:  */
        !           109: 
        !           110: /*------------------------------------------------------------------*/
        !           111: /*
        !           112:  * Read from card's Host Adaptor Status Register.
        !           113:  */
        !           114: static inline u_short
        !           115: hasr_read(u_long       ioaddr)
        !           116: {
        !           117:   return(inw(HASR(ioaddr)));
        !           118: } /* hasr_read */
        !           119: 
        !           120: /*------------------------------------------------------------------*/
        !           121: /*
        !           122:  * Write to card's Host Adapter Command Register.
        !           123:  */
        !           124: static inline void
        !           125: hacr_write(u_long      ioaddr,
        !           126:           u_short      hacr)
        !           127: {
        !           128:   outw(hacr, HACR(ioaddr));
        !           129: } /* hacr_write */
        !           130: 
        !           131: /*------------------------------------------------------------------*/
        !           132: /*
        !           133:  * Write to card's Host Adapter Command Register. Include a delay for
        !           134:  * those times when it is needed.
        !           135:  */
        !           136: static inline void
        !           137: hacr_write_slow(u_long ioaddr,
        !           138:                u_short hacr)
        !           139: {
        !           140:   hacr_write(ioaddr, hacr);
        !           141:   /* delay might only be needed sometimes */
        !           142:   udelay(1000L);
        !           143: } /* hacr_write_slow */
        !           144: 
        !           145: /*------------------------------------------------------------------*/
        !           146: /*
        !           147:  * Set the channel attention bit.
        !           148:  */
        !           149: static inline void
        !           150: set_chan_attn(u_long   ioaddr,
        !           151:              u_short   hacr)
        !           152: {
        !           153:   hacr_write(ioaddr, hacr | HACR_CA);
        !           154: } /* set_chan_attn */
        !           155: 
        !           156: /*------------------------------------------------------------------*/
        !           157: /*
        !           158:  * Reset, and then set host adaptor into default mode.
        !           159:  */
        !           160: static inline void
        !           161: wv_hacr_reset(u_long   ioaddr)
        !           162: {
        !           163:   hacr_write_slow(ioaddr, HACR_RESET);
        !           164:   hacr_write(ioaddr, HACR_DEFAULT);
        !           165: } /* wv_hacr_reset */
        !           166: 
        !           167: /*------------------------------------------------------------------*/
        !           168: /*
        !           169:  * Set the i/o transfer over the ISA bus to 8 bits mode
        !           170:  */
        !           171: static inline void
        !           172: wv_16_off(u_long       ioaddr,
        !           173:          u_short       hacr)
        !           174: {
        !           175:   hacr &= ~HACR_16BITS;
        !           176:   hacr_write(ioaddr, hacr);
        !           177: } /* wv_16_off */
        !           178: 
        !           179: /*------------------------------------------------------------------*/
        !           180: /*
        !           181:  * Set the i/o transfer over the ISA bus to 8 bits mode
        !           182:  */
        !           183: static inline void
        !           184: wv_16_on(u_long                ioaddr,
        !           185:         u_short        hacr)
        !           186: {
        !           187:   hacr |= HACR_16BITS;
        !           188:   hacr_write(ioaddr, hacr);
        !           189: } /* wv_16_on */
        !           190: 
        !           191: /*------------------------------------------------------------------*/
        !           192: /*
        !           193:  * Disable interrupts on the WaveLAN hardware
        !           194:  */
        !           195: static inline void
        !           196: wv_ints_off(device *   dev)
        !           197: {
        !           198:   net_local *  lp = (net_local *)dev->priv;
        !           199:   u_long       ioaddr = dev->base_addr;
        !           200:   u_long       x;
        !           201: 
        !           202:   x = wv_splhi();
        !           203: 
        !           204:   lp->hacr &= ~HACR_INTRON;
        !           205:   hacr_write(ioaddr, lp->hacr);
        !           206: 
        !           207:   wv_splx(x);
        !           208: } /* wv_ints_off */
        !           209: 
        !           210: /*------------------------------------------------------------------*/
        !           211: /*
        !           212:  * Enable interrupts on the WaveLAN hardware
        !           213:  */
        !           214: static inline void
        !           215: wv_ints_on(device *    dev)
        !           216: {
        !           217:   net_local *  lp = (net_local *)dev->priv;
        !           218:   u_long       ioaddr = dev->base_addr;
        !           219:   u_long       x;
        !           220: 
        !           221:   x = wv_splhi();
        !           222: 
        !           223:   lp->hacr |= HACR_INTRON;
        !           224:   hacr_write(ioaddr, lp->hacr);
        !           225: 
        !           226:   wv_splx(x);
        !           227: } /* wv_ints_on */
        !           228: 
        !           229: /******************* MODEM MANAGEMENT SUBROUTINES *******************/
        !           230: /*
        !           231:  * Useful subroutines to manage the modem of the WaveLAN
        !           232:  */
        !           233: 
        !           234: /*------------------------------------------------------------------*/
        !           235: /*
        !           236:  * Read the Parameter Storage Area from the WaveLAN card's memory
        !           237:  */
        !           238: /*
        !           239:  * Read bytes from the PSA.
        !           240:  */
        !           241: static void
        !           242: psa_read(u_long                ioaddr,
        !           243:         u_short        hacr,
        !           244:         int            o,      /* offset in PSA */
        !           245:         u_char *       b,      /* buffer to fill */
        !           246:         int            n)      /* size to read */
        !           247: {
        !           248:   wv_16_off(ioaddr, hacr);
        !           249: 
        !           250:   while(n-- > 0)
        !           251:     {
        !           252:       outw(o, PIOR2(ioaddr));
        !           253:       o++;
        !           254:       *b++ = inb(PIOP2(ioaddr));
        !           255:     }
        !           256: 
        !           257:   wv_16_on(ioaddr, hacr);
        !           258: } /* psa_read */
        !           259: 
        !           260: /*------------------------------------------------------------------*/
        !           261: /*
        !           262:  * Write the Paramter Storage Area to the WaveLAN card's memory
        !           263:  */
        !           264: static void
        !           265: psa_write(u_long       ioaddr,
        !           266:          u_short       hacr,
        !           267:          int           o,      /* Offset in psa */
        !           268:          u_char *      b,      /* Buffer in memory */
        !           269:          int           n)      /* Length of buffer */
        !           270: {
        !           271:   int  count = 0;
        !           272: 
        !           273:   wv_16_off(ioaddr, hacr);
        !           274: 
        !           275:   while(n-- > 0)
        !           276:     {
        !           277:       outw(o, PIOR2(ioaddr));
        !           278:       o++;
        !           279: 
        !           280:       outb(*b, PIOP2(ioaddr));
        !           281:       b++;
        !           282: 
        !           283:       /* Wait for the memory to finish its write cycle */
        !           284:       count = 0;
        !           285:       while((count++ < 100) &&
        !           286:            (hasr_read(ioaddr) & HASR_PSA_BUSY))
        !           287:        udelay(1000);
        !           288:     }
        !           289: 
        !           290:   wv_16_on(ioaddr, hacr);
        !           291: } /* psa_write */
        !           292: 
        !           293: #ifdef PSA_CRC
        !           294: /*------------------------------------------------------------------*/
        !           295: /*
        !           296:  * Calculate the PSA CRC (not tested yet)
        !           297:  * As the WaveLAN drivers don't use the CRC, I won't use it either.
        !           298:  * Thanks to Valster, Nico <[email protected]> for the code
        !           299:  * NOTE: By specifying a length including the CRC position the
        !           300:  * returned value should be zero. (i.e. a correct checksum in the PSA)
        !           301:  */
        !           302: static u_short
        !           303: psa_crc(u_short *      psa,    /* The PSA */
        !           304:        int             size)   /* Number of short for CRC */
        !           305: {
        !           306:   int          byte_cnt;       /* Loop on the PSA */
        !           307:   u_short      crc_bytes = 0;  /* Data in the PSA */
        !           308:   int          bit_cnt;        /* Loop on the bits of the short */
        !           309: 
        !           310:   for(byte_cnt = 0; byte_cnt <= size; byte_cnt++ )
        !           311:     {
        !           312:       crc_bytes ^= psa[byte_cnt];      /* Its an xor */
        !           313: 
        !           314:       for(bit_cnt = 1; bit_cnt < 9; bit_cnt++ )
        !           315:        {
        !           316:          if(crc_bytes & 0x0001)
        !           317:            crc_bytes = (crc_bytes >> 1) ^ 0xA001;
        !           318:          else
        !           319:            crc_bytes >>= 1 ;
        !           320:         }
        !           321:     }
        !           322: 
        !           323:   return crc_bytes;
        !           324: } /* psa_crc */
        !           325: #endif /* PSA_CRC */
        !           326: 
        !           327: /*------------------------------------------------------------------*/
        !           328: /*
        !           329:  * Write 1 byte to the MMC.
        !           330:  */
        !           331: static inline void
        !           332: mmc_out(u_long         ioaddr,
        !           333:        u_short         o,
        !           334:        u_char          d)
        !           335: {
        !           336:   /* Wait for MMC to go idle */
        !           337:   while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
        !           338:     ;
        !           339: 
        !           340:   outw((u_short) (((u_short) d << 8) | (o << 1) | 1),
        !           341:        MMCR(ioaddr));
        !           342: }
        !           343: 
        !           344: /*------------------------------------------------------------------*/
        !           345: /*
        !           346:  * Routine to write bytes to the Modem Management Controller.
        !           347:  * We start by the end because it is the way it should be !
        !           348:  */
        !           349: static inline void
        !           350: mmc_write(u_long       ioaddr,
        !           351:          u_char        o,
        !           352:          u_char *      b,
        !           353:          int           n)
        !           354: {
        !           355:   o += n;
        !           356:   b += n;
        !           357: 
        !           358:   while(n-- > 0 )
        !           359:     mmc_out(ioaddr, --o, *(--b));
        !           360: } /* mmc_write */
        !           361: 
        !           362: /*------------------------------------------------------------------*/
        !           363: /*
        !           364:  * Read 1 byte from the MMC.
        !           365:  * Optimised version for 1 byte, avoid using memory...
        !           366:  */
        !           367: static inline u_char
        !           368: mmc_in(u_long  ioaddr,
        !           369:        u_short o)
        !           370: {
        !           371:   while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
        !           372:     ;
        !           373:   outw(o << 1, MMCR(ioaddr));
        !           374: 
        !           375:   while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
        !           376:     ;
        !           377:   return (u_char) (inw(MMCR(ioaddr)) >> 8);
        !           378: }
        !           379: 
        !           380: /*------------------------------------------------------------------*/
        !           381: /*
        !           382:  * Routine to read bytes from the Modem Management Controller.
        !           383:  * The implementation is complicated by a lack of address lines,
        !           384:  * which prevents decoding of the low-order bit.
        !           385:  * (code has just been moved in the above function)
        !           386:  * We start by the end because it is the way it should be !
        !           387:  */
        !           388: static inline void
        !           389: mmc_read(u_long                ioaddr,
        !           390:         u_char         o,
        !           391:         u_char *       b,
        !           392:         int            n)
        !           393: {
        !           394:   o += n;
        !           395:   b += n;
        !           396: 
        !           397:   while(n-- > 0)
        !           398:     *(--b) = mmc_in(ioaddr, --o);
        !           399: } /* mmc_read */
        !           400: 
        !           401: /*------------------------------------------------------------------*/
        !           402: /*
        !           403:  * Get the type of encryption available...
        !           404:  */
        !           405: static inline int
        !           406: mmc_encr(u_long                ioaddr) /* i/o port of the card */
        !           407: {
        !           408:   int  temp;
        !           409: 
        !           410:   temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail));
        !           411:   if((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES))
        !           412:     return 0;
        !           413:   else
        !           414:     return temp;
        !           415: }
        !           416: 
        !           417: /*------------------------------------------------------------------*/
        !           418: /*
        !           419:  * Wait for the frequency EEPROM to complete a command...
        !           420:  * I hope this one will be optimally inlined...
        !           421:  */
        !           422: static inline void
        !           423: fee_wait(u_long                ioaddr, /* i/o port of the card */
        !           424:         int            delay,  /* Base delay to wait for */
        !           425:         int            number) /* Number of time to wait */
        !           426: {
        !           427:   int          count = 0;      /* Wait only a limited time */
        !           428: 
        !           429:   while((count++ < number) &&
        !           430:        (mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & MMR_FEE_STATUS_BUSY))
        !           431:     udelay(delay);
        !           432: }
        !           433: 
        !           434: /*------------------------------------------------------------------*/
        !           435: /*
        !           436:  * Read bytes from the frequency EEPROM (frequency select cards).
        !           437:  */
        !           438: static void
        !           439: fee_read(u_long                ioaddr, /* i/o port of the card */
        !           440:         u_short        o,      /* destination offset */
        !           441:         u_short *      b,      /* data buffer */
        !           442:         int            n)      /* number of registers */
        !           443: {
        !           444:   b += n;              /* Position at the end of the area */
        !           445: 
        !           446:   /* Write the address */
        !           447:   mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);
        !           448: 
        !           449:   /* Loop on all buffer */
        !           450:   while(n-- > 0)
        !           451:     {
        !           452:       /* Write the read command */
        !           453:       mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_READ);
        !           454: 
        !           455:       /* Wait until EEPROM is ready (should be quick!) */
        !           456:       fee_wait(ioaddr, 10, 100);
        !           457: 
        !           458:       /* Read the value */
        !           459:       *--b = ((mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)) << 8) |
        !           460:              mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));
        !           461:     }
        !           462: }
        !           463: 
        !           464: #ifdef WIRELESS_EXT    /* If wireless extension exist in the kernel */
        !           465: 
        !           466: /*------------------------------------------------------------------*/
        !           467: /*
        !           468:  * Write bytes from the Frequency EEPROM (frequency select cards).
        !           469:  * This is a bit complicated, because the frequency EEPROM has to
        !           470:  * be unprotected and the write enabled.
        !           471:  * Jean II
        !           472:  */
        !           473: static void
        !           474: fee_write(u_long       ioaddr, /* i/o port of the card */
        !           475:          u_short       o,      /* destination offset */
        !           476:          u_short *     b,      /* data buffer */
        !           477:          int           n)      /* number of registers */
        !           478: {
        !           479:   b += n;              /* Position at the end of the area */
        !           480: 
        !           481: #ifdef EEPROM_IS_PROTECTED     /* disabled */
        !           482: #ifdef DOESNT_SEEM_TO_WORK     /* disabled */
        !           483:   /* Ask to read the protected register */
        !           484:   mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD);
        !           485: 
        !           486:   fee_wait(ioaddr, 10, 100);
        !           487: 
        !           488:   /* Read the protected register */
        !           489:   printk("Protected 2 : %02X-%02X\n",
        !           490:         mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)),
        !           491:         mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));
        !           492: #endif /* DOESNT_SEEM_TO_WORK */
        !           493: 
        !           494:   /* Enable protected register */
        !           495:   mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);
        !           496:   mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN);
        !           497: 
        !           498:   fee_wait(ioaddr, 10, 100);
        !           499: 
        !           500:   /* Unprotect area */
        !           501:   mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n);
        !           502:   mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);
        !           503: #ifdef DOESNT_SEEM_TO_WORK     /* disabled */
        !           504:   /* Or use : */
        !           505:   mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRCLEAR);
        !           506: #endif /* DOESNT_SEEM_TO_WORK */
        !           507: 
        !           508:   fee_wait(ioaddr, 10, 100);
        !           509: #endif /* EEPROM_IS_PROTECTED */
        !           510: 
        !           511:   /* Write enable */
        !           512:   mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);
        !           513:   mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN);
        !           514: 
        !           515:   fee_wait(ioaddr, 10, 100);
        !           516: 
        !           517:   /* Write the EEPROM address */
        !           518:   mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);
        !           519: 
        !           520:   /* Loop on all buffer */
        !           521:   while(n-- > 0)
        !           522:     {
        !           523:       /* Write the value */
        !           524:       mmc_out(ioaddr, mmwoff(0, mmw_fee_data_h), (*--b) >> 8);
        !           525:       mmc_out(ioaddr, mmwoff(0, mmw_fee_data_l), *b & 0xFF);
        !           526: 
        !           527:       /* Write the write command */
        !           528:       mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WRITE);
        !           529: 
        !           530:       /* Wavelan doc says : wait at least 10 ms for EEBUSY = 0 */
        !           531:       udelay(10000);
        !           532:       fee_wait(ioaddr, 10, 100);
        !           533:     }
        !           534: 
        !           535:   /* Write disable */
        !           536:   mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS);
        !           537:   mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS);
        !           538: 
        !           539:   fee_wait(ioaddr, 10, 100);
        !           540: 
        !           541: #ifdef EEPROM_IS_PROTECTED     /* disabled */
        !           542:   /* Reprotect EEPROM */
        !           543:   mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x00);
        !           544:   mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);
        !           545: 
        !           546:   fee_wait(ioaddr, 10, 100);
        !           547: #endif /* EEPROM_IS_PROTECTED */
        !           548: }
        !           549: #endif /* WIRELESS_EXT */
        !           550: 
        !           551: /************************ I82586 SUBROUTINES *************************/
        !           552: /*
        !           553:  * Usefull subroutines to manage the Ethernet controler
        !           554:  */
        !           555: 
        !           556: /*------------------------------------------------------------------*/
        !           557: /*
        !           558:  * Read bytes from the on-board RAM.
        !           559:  * Why inlining this function make it fail ???
        !           560:  */
        !           561: static /*inline*/ void
        !           562: obram_read(u_long      ioaddr,
        !           563:           u_short      o,
        !           564:           u_char *     b,
        !           565:           int          n)
        !           566: {
        !           567:   outw(o, PIOR1(ioaddr));
        !           568:   insw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);
        !           569: }
        !           570: 
        !           571: /*------------------------------------------------------------------*/
        !           572: /*
        !           573:  * Write bytes to the on-board RAM.
        !           574:  */
        !           575: static inline void
        !           576: obram_write(u_long     ioaddr,
        !           577:            u_short     o,
        !           578:            u_char *    b,
        !           579:            int         n)
        !           580: {
        !           581:   outw(o, PIOR1(ioaddr));
        !           582:   outsw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);
        !           583: }
        !           584: 
        !           585: /*------------------------------------------------------------------*/
        !           586: /*
        !           587:  * Acknowledge the reading of the status issued by the i82586
        !           588:  */
        !           589: static void
        !           590: wv_ack(device *                dev)
        !           591: {
        !           592:   net_local *  lp = (net_local *)dev->priv;
        !           593:   u_long       ioaddr = dev->base_addr;
        !           594:   u_short      scb_cs;
        !           595:   int          i;
        !           596: 
        !           597:   obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
        !           598:             (unsigned char *) &scb_cs, sizeof(scb_cs));
        !           599:   scb_cs &= SCB_ST_INT;
        !           600: 
        !           601:   if(scb_cs == 0)
        !           602:     return;
        !           603: 
        !           604:   obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
        !           605:              (unsigned char *) &scb_cs, sizeof(scb_cs));
        !           606: 
        !           607:   set_chan_attn(ioaddr, lp->hacr);
        !           608: 
        !           609:   for(i = 1000; i > 0; i--)
        !           610:     {
        !           611:       obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs));
        !           612:       if(scb_cs == 0)
        !           613:        break;
        !           614: 
        !           615:       udelay(10);
        !           616:     }
        !           617:   udelay(100);
        !           618: 
        !           619: #ifdef DEBUG_CONFIG_ERROR
        !           620:   if(i <= 0)
        !           621:     printk(KERN_INFO "%s: wv_ack(): board not accepting command.\n",
        !           622:           dev->name);
        !           623: #endif
        !           624: }
        !           625: 
        !           626: /*------------------------------------------------------------------*/
        !           627: /*
        !           628:  * Set channel attention bit and busy wait until command has
        !           629:  * completed, then acknowledge the command completion.
        !           630:  */
        !           631: static inline int
        !           632: wv_synchronous_cmd(device *    dev,
        !           633:                   const char * str)
        !           634: {
        !           635:   net_local *  lp = (net_local *)dev->priv;
        !           636:   u_long       ioaddr = dev->base_addr;
        !           637:   u_short      scb_cmd;
        !           638:   ach_t                cb;
        !           639:   int          i;
        !           640: 
        !           641:   scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO;
        !           642:   obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
        !           643:              (unsigned char *) &scb_cmd, sizeof(scb_cmd));
        !           644: 
        !           645:   set_chan_attn(ioaddr, lp->hacr);
        !           646: 
        !           647:   for (i = 1000; i > 0; i--)
        !           648:     {
        !           649:       obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
        !           650:       if (cb.ac_status & AC_SFLD_C)
        !           651:        break;
        !           652: 
        !           653:       udelay(10);
        !           654:     }
        !           655:   udelay(100);
        !           656: 
        !           657:   if(i <= 0 || !(cb.ac_status & AC_SFLD_OK))
        !           658:     {
        !           659: #ifdef DEBUG_CONFIG_ERROR
        !           660:       printk(KERN_INFO "%s: %s failed; status = 0x%x\n",
        !           661:             dev->name, str, cb.ac_status);
        !           662: #endif
        !           663: #ifdef DEBUG_I82586_SHOW
        !           664:       wv_scb_show(ioaddr);
        !           665: #endif
        !           666:       return -1;
        !           667:     }
        !           668: 
        !           669:   /* Ack the status */
        !           670:   wv_ack(dev);
        !           671: 
        !           672:   return 0;
        !           673: }
        !           674: 
        !           675: /*------------------------------------------------------------------*/
        !           676: /*
        !           677:  * Configuration commands completion interrupt.
        !           678:  * Check if done, and if ok...
        !           679:  */
        !           680: static inline int
        !           681: wv_config_complete(device *    dev,
        !           682:                   u_long       ioaddr,
        !           683:                   net_local *  lp)
        !           684: {
        !           685:   unsigned short       mcs_addr;
        !           686:   unsigned short       status;
        !           687:   int                  ret;
        !           688: 
        !           689: #ifdef DEBUG_INTERRUPT_TRACE
        !           690:   printk(KERN_DEBUG "%s: ->wv_config_complete()\n", dev->name);
        !           691: #endif
        !           692: 
        !           693:   mcs_addr = lp->tx_first_in_use + sizeof(ac_tx_t) + sizeof(ac_nop_t)
        !           694:     + sizeof(tbd_t) + sizeof(ac_cfg_t) + sizeof(ac_ias_t);
        !           695: 
        !           696:   /* Read the status of the last command (set mc list) */
        !           697:   obram_read(ioaddr, acoff(mcs_addr, ac_status), (unsigned char *)&status, sizeof(status));
        !           698: 
        !           699:   /* If not completed -> exit */
        !           700:   if((status & AC_SFLD_C) == 0)
        !           701:     ret = 0;           /* Not ready to be scrapped */
        !           702:   else
        !           703:     {
        !           704: #ifdef DEBUG_CONFIG_ERROR
        !           705:       unsigned short   cfg_addr;
        !           706:       unsigned short   ias_addr;
        !           707: 
        !           708:       /* Check mc_config command */
        !           709:       if(status & AC_SFLD_OK != 0)
        !           710:        printk(KERN_INFO "wv_config_complete(): set_multicast_address failed; status = 0x%x\n",
        !           711:               dev->name, str, status);
        !           712: 
        !           713:       /* check ia-config command */
        !           714:       ias_addr = mcs_addr - sizeof(ac_ias_t);
        !           715:       obram_read(ioaddr, acoff(ias_addr, ac_status), (unsigned char *)&status, sizeof(status));
        !           716:       if(status & AC_SFLD_OK != 0)
        !           717:        printk(KERN_INFO "wv_config_complete(): set_MAC_address; status = 0x%x\n",
        !           718:               dev->name, str, status);
        !           719: 
        !           720:       /* Check config command */
        !           721:       cfg_addr = ias_addr - sizeof(ac_cfg_t);
        !           722:       obram_read(ioaddr, acoff(cfg_addr, ac_status), (unsigned char *)&status, sizeof(status));
        !           723:       if(status & AC_SFLD_OK != 0)
        !           724:        printk(KERN_INFO "wv_config_complete(): configure; status = 0x%x\n",
        !           725:               dev->name, str, status);
        !           726: #endif /* DEBUG_CONFIG_ERROR */
        !           727: 
        !           728:       ret = 1;         /* Ready to be scrapped */
        !           729:     }
        !           730: 
        !           731: #ifdef DEBUG_INTERRUPT_TRACE
        !           732:   printk(KERN_DEBUG "%s: <-wv_config_complete() - %d\n", dev->name, ret);
        !           733: #endif
        !           734:   return ret;
        !           735: }
        !           736: 
        !           737: /*------------------------------------------------------------------*/
        !           738: /*
        !           739:  * Command completion interrupt.
        !           740:  * Reclaim as many freed tx buffers as we can.
        !           741:  */
        !           742: static int
        !           743: wv_complete(device *   dev,
        !           744:            u_long      ioaddr,
        !           745:            net_local * lp)
        !           746: {
        !           747:   int  nreaped = 0;
        !           748: 
        !           749: #ifdef DEBUG_INTERRUPT_TRACE
        !           750:   printk(KERN_DEBUG "%s: ->wv_complete()\n", dev->name);
        !           751: #endif
        !           752: 
        !           753:   /* Loop on all the transmit buffers */
        !           754:   while(lp->tx_first_in_use != I82586NULL)
        !           755:     {
        !           756:       unsigned short   tx_status;
        !           757: 
        !           758:       /* Read the first transmit buffer */
        !           759:       obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), (unsigned char *)&tx_status, sizeof(tx_status));
        !           760: 
        !           761:       /* Hack for reconfiguration... */
        !           762:       if(tx_status == 0xFFFF)
        !           763:        if(!wv_config_complete(dev, ioaddr, lp))
        !           764:          break;        /* Not completed */
        !           765: 
        !           766:       /* If not completed -> exit */
        !           767:       if((tx_status & AC_SFLD_C) == 0)
        !           768:        break;
        !           769: 
        !           770:       /* We now remove this buffer */
        !           771:       nreaped++;
        !           772:       --lp->tx_n_in_use;
        !           773: 
        !           774: /*
        !           775: if (lp->tx_n_in_use > 0)
        !           776:        printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]);
        !           777: */
        !           778: 
        !           779:       /* Was it the last one ? */
        !           780:       if(lp->tx_n_in_use <= 0)
        !           781:        lp->tx_first_in_use = I82586NULL;
        !           782:       else
        !           783:        {
        !           784:          /* Next one in the chain */
        !           785:          lp->tx_first_in_use += TXBLOCKZ;
        !           786:          if(lp->tx_first_in_use >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
        !           787:            lp->tx_first_in_use -= NTXBLOCKS * TXBLOCKZ;
        !           788:        }
        !           789: 
        !           790:       /* Hack for reconfiguration... */
        !           791:       if(tx_status == 0xFFFF)
        !           792:        continue;
        !           793: 
        !           794:       /* Now, check status of the finished command */
        !           795:       if(tx_status & AC_SFLD_OK)
        !           796:        {
        !           797:          int   ncollisions;
        !           798: 
        !           799:          lp->stats.tx_packets++;
        !           800:          ncollisions = tx_status & AC_SFLD_MAXCOL;
        !           801:          lp->stats.collisions += ncollisions;
        !           802: #ifdef DEBUG_INTERRUPT_INFO
        !           803:          if(ncollisions > 0)
        !           804:            printk(KERN_DEBUG "%s: wv_complete(): tx completed after %d collisions.\n",
        !           805:                   dev->name, ncollisions);
        !           806: #endif
        !           807:        }
        !           808:       else
        !           809:        {
        !           810:          lp->stats.tx_errors++;
        !           811: #ifndef IGNORE_NORMAL_XMIT_ERRS
        !           812:          if(tx_status & AC_SFLD_S10)
        !           813:            {
        !           814:              lp->stats.tx_carrier_errors++;
        !           815: #ifdef DEBUG_INTERRUPT_ERROR
        !           816:              printk(KERN_INFO "%s: wv_complete(): tx error: no CS.\n",
        !           817:                     dev->name);
        !           818: #endif
        !           819:            }
        !           820: #endif /* IGNORE_NORMAL_XMIT_ERRS */
        !           821:          if(tx_status & AC_SFLD_S9)
        !           822:            {
        !           823:              lp->stats.tx_carrier_errors++;
        !           824: #ifdef DEBUG_INTERRUPT_ERROR
        !           825:              printk(KERN_INFO "%s: wv_complete(): tx error: lost CTS.\n",
        !           826:                     dev->name);
        !           827: #endif
        !           828:            }
        !           829:          if(tx_status & AC_SFLD_S8)
        !           830:            {
        !           831:              lp->stats.tx_fifo_errors++;
        !           832: #ifdef DEBUG_INTERRUPT_ERROR
        !           833:              printk(KERN_INFO "%s: wv_complete(): tx error: slow DMA.\n",
        !           834:                     dev->name);
        !           835: #endif
        !           836:            }
        !           837: #ifndef IGNORE_NORMAL_XMIT_ERRS
        !           838:          if(tx_status & AC_SFLD_S6)
        !           839:            {
        !           840:              lp->stats.tx_heartbeat_errors++;
        !           841: #ifdef DEBUG_INTERRUPT_ERROR
        !           842:              printk(KERN_INFO "%s: wv_complete(): tx error: heart beat.\n",
        !           843:                     dev->name);
        !           844: #endif
        !           845:            }
        !           846:          if(tx_status & AC_SFLD_S5)
        !           847:            {
        !           848:              lp->stats.tx_aborted_errors++;
        !           849: #ifdef DEBUG_INTERRUPT_ERROR
        !           850:              printk(KERN_INFO "%s: wv_complete(): tx error: too many collisions.\n",
        !           851:                     dev->name);
        !           852: #endif
        !           853:            }
        !           854: #endif /* IGNORE_NORMAL_XMIT_ERRS */
        !           855:        }
        !           856: 
        !           857: #ifdef DEBUG_INTERRUPT_INFO
        !           858:       printk(KERN_DEBUG "%s: wv_complete(): tx completed, tx_status 0x%04x\n",
        !           859:             dev->name, tx_status);
        !           860: #endif
        !           861:     }
        !           862: 
        !           863: #ifdef DEBUG_INTERRUPT_INFO
        !           864:   if(nreaped > 1)
        !           865:     printk(KERN_DEBUG "%s: wv_complete(): reaped %d\n", dev->name, nreaped);
        !           866: #endif
        !           867: 
        !           868:   /*
        !           869:    * Inform upper layers.
        !           870:    */
        !           871:   if(lp->tx_n_in_use < NTXBLOCKS - 1)
        !           872:     {
        !           873:       dev->tbusy = 0;
        !           874:       mark_bh(NET_BH);
        !           875:     }
        !           876: 
        !           877: #ifdef DEBUG_INTERRUPT_TRACE
        !           878:   printk(KERN_DEBUG "%s: <-wv_complete()\n", dev->name);
        !           879: #endif
        !           880:   return nreaped;
        !           881: }
        !           882: 
        !           883: /*------------------------------------------------------------------*/
        !           884: /*
        !           885:  * Reconfigure the i82586, or at least ask for it...
        !           886:  * Because wv_82586_config use a transmission buffer, we must do it
        !           887:  * when we are sure that there is one left, so we do it now
        !           888:  * or in wavelan_packet_xmit() (I can't find any better place,
        !           889:  * wavelan_interrupt is not an option...), so you may experience
        !           890:  * some delay sometime...
        !           891:  */
        !           892: static inline void
        !           893: wv_82586_reconfig(device *     dev)
        !           894: {
        !           895:   net_local *  lp = (net_local *)dev->priv;
        !           896: 
        !           897:   /* Check if we can do it now ! */
        !           898:   if(!(dev->start) || (set_bit(0, (void *)&dev->tbusy) != 0))
        !           899:     {
        !           900:       lp->reconfig_82586 = 1;
        !           901: #ifdef DEBUG_CONFIG_INFO
        !           902:       printk(KERN_DEBUG "%s: wv_82586_reconfig(): delayed (busy = %ld, start = %d)\n",
        !           903:             dev->name, dev->tbusy, dev->start);
        !           904: #endif
        !           905:     }
        !           906:   else
        !           907:     wv_82586_config(dev);
        !           908: }
        !           909: 
        !           910: /********************* DEBUG & INFO SUBROUTINES *********************/
        !           911: /*
        !           912:  * This routines are used in the code to show debug informations.
        !           913:  * Most of the time, it dump the content of hardware structures...
        !           914:  */
        !           915: 
        !           916: #ifdef DEBUG_PSA_SHOW
        !           917: /*------------------------------------------------------------------*/
        !           918: /*
        !           919:  * Print the formatted contents of the Parameter Storage Area.
        !           920:  */
        !           921: static void
        !           922: wv_psa_show(psa_t *    p)
        !           923: {
        !           924:   printk(KERN_DEBUG "##### WaveLAN psa contents: #####\n");
        !           925:   printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n",
        !           926:         p->psa_io_base_addr_1,
        !           927:         p->psa_io_base_addr_2,
        !           928:         p->psa_io_base_addr_3,
        !           929:         p->psa_io_base_addr_4);
        !           930:   printk(KERN_DEBUG "psa_rem_boot_addr_1: 0x%02X %02X %02X\n",
        !           931:         p->psa_rem_boot_addr_1,
        !           932:         p->psa_rem_boot_addr_2,
        !           933:         p->psa_rem_boot_addr_3);
        !           934:   printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params);
        !           935:   printk("psa_int_req_no: %d\n", p->psa_int_req_no);
        !           936: #ifdef DEBUG_SHOW_UNUSED
        !           937:   printk(KERN_DEBUG "psa_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
        !           938:         p->psa_unused0[0],
        !           939:         p->psa_unused0[1],
        !           940:         p->psa_unused0[2],
        !           941:         p->psa_unused0[3],
        !           942:         p->psa_unused0[4],
        !           943:         p->psa_unused0[5],
        !           944:         p->psa_unused0[6]);
        !           945: #endif /* DEBUG_SHOW_UNUSED */
        !           946:   printk(KERN_DEBUG "psa_univ_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n",
        !           947:         p->psa_univ_mac_addr[0],
        !           948:         p->psa_univ_mac_addr[1],
        !           949:         p->psa_univ_mac_addr[2],
        !           950:         p->psa_univ_mac_addr[3],
        !           951:         p->psa_univ_mac_addr[4],
        !           952:         p->psa_univ_mac_addr[5]);
        !           953:   printk(KERN_DEBUG "psa_local_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n",
        !           954:         p->psa_local_mac_addr[0],
        !           955:         p->psa_local_mac_addr[1],
        !           956:         p->psa_local_mac_addr[2],
        !           957:         p->psa_local_mac_addr[3],
        !           958:         p->psa_local_mac_addr[4],
        !           959:         p->psa_local_mac_addr[5]);
        !           960:   printk(KERN_DEBUG "psa_univ_local_sel: %d, ", p->psa_univ_local_sel);
        !           961:   printk("psa_comp_number: %d, ", p->psa_comp_number);
        !           962:   printk("psa_thr_pre_set: 0x%02x\n", p->psa_thr_pre_set);
        !           963:   printk(KERN_DEBUG "psa_feature_select/decay_prm: 0x%02x, ",
        !           964:         p->psa_feature_select);
        !           965:   printk("psa_subband/decay_update_prm: %d\n", p->psa_subband);
        !           966:   printk(KERN_DEBUG "psa_quality_thr: 0x%02x, ", p->psa_quality_thr);
        !           967:   printk("psa_mod_delay: 0x%02x\n", p->psa_mod_delay);
        !           968:   printk(KERN_DEBUG "psa_nwid: 0x%02x%02x, ", p->psa_nwid[0], p->psa_nwid[1]);
        !           969:   printk("psa_nwid_select: %d\n", p->psa_nwid_select);
        !           970:   printk(KERN_DEBUG "psa_encryption_select: %d, ", p->psa_encryption_select);
        !           971:   printk("psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
        !           972:         p->psa_encryption_key[0],
        !           973:         p->psa_encryption_key[1],
        !           974:         p->psa_encryption_key[2],
        !           975:         p->psa_encryption_key[3],
        !           976:         p->psa_encryption_key[4],
        !           977:         p->psa_encryption_key[5],
        !           978:         p->psa_encryption_key[6],
        !           979:         p->psa_encryption_key[7]);
        !           980:   printk(KERN_DEBUG "psa_databus_width: %d\n", p->psa_databus_width);
        !           981:   printk(KERN_DEBUG "psa_call_code/auto_squelch: 0x%02x, ",
        !           982:         p->psa_call_code[0]);
        !           983:   printk("psa_call_code[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
        !           984:         p->psa_call_code[0],
        !           985:         p->psa_call_code[1],
        !           986:         p->psa_call_code[2],
        !           987:         p->psa_call_code[3],
        !           988:         p->psa_call_code[4],
        !           989:         p->psa_call_code[5],
        !           990:         p->psa_call_code[6],
        !           991:         p->psa_call_code[7]);
        !           992: #ifdef DEBUG_SHOW_UNUSED
        !           993:   printk(KERN_DEBUG "psa_reserved[]: %02X:%02X:%02X:%02X\n",
        !           994:         p->psa_reserved[0],
        !           995:         p->psa_reserved[1],
        !           996:         p->psa_reserved[2],
        !           997:         p->psa_reserved[3]);
        !           998: #endif /* DEBUG_SHOW_UNUSED */
        !           999:   printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status);
        !          1000:   printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]);
        !          1001:   printk("psa_crc_status: 0x%02x\n", p->psa_crc_status);
        !          1002: } /* wv_psa_show */
        !          1003: #endif /* DEBUG_PSA_SHOW */
        !          1004: 
        !          1005: #ifdef DEBUG_MMC_SHOW
        !          1006: /*------------------------------------------------------------------*/
        !          1007: /*
        !          1008:  * Print the formatted status of the Modem Management Controller.
        !          1009:  * This function need to be completed...
        !          1010:  */
        !          1011: static void
        !          1012: wv_mmc_show(device *   dev)
        !          1013: {
        !          1014:   u_long       ioaddr = dev->base_addr;
        !          1015:   net_local *  lp = (net_local *)dev->priv;
        !          1016:   mmr_t                m;
        !          1017: 
        !          1018:   /* Basic check */
        !          1019:   if(hasr_read(ioaddr) & HASR_NO_CLK)
        !          1020:     {
        !          1021:       printk(KERN_WARNING "%s: wv_mmc_show: modem not connected\n",
        !          1022:             dev->name);
        !          1023:       return;
        !          1024:     }
        !          1025: 
        !          1026:   /* Read the mmc */
        !          1027:   mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
        !          1028:   mmc_read(ioaddr, 0, (u_char *)&m, sizeof(m));
        !          1029:   mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
        !          1030: 
        !          1031: #ifdef WIRELESS_EXT    /* If wireless extension exist in the kernel */
        !          1032:   /* Don't forget to update statistics */
        !          1033:   lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
        !          1034: #endif /* WIRELESS_EXT */
        !          1035: 
        !          1036:   printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n");
        !          1037: #ifdef DEBUG_SHOW_UNUSED
        !          1038:   printk(KERN_DEBUG "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
        !          1039:         m.mmr_unused0[0],
        !          1040:         m.mmr_unused0[1],
        !          1041:         m.mmr_unused0[2],
        !          1042:         m.mmr_unused0[3],
        !          1043:         m.mmr_unused0[4],
        !          1044:         m.mmr_unused0[5],
        !          1045:         m.mmr_unused0[6],
        !          1046:         m.mmr_unused0[7]);
        !          1047: #endif /* DEBUG_SHOW_UNUSED */
        !          1048:   printk(KERN_DEBUG "Encryption algorythm: %02X - Status: %02X\n",
        !          1049:         m.mmr_des_avail, m.mmr_des_status);
        !          1050: #ifdef DEBUG_SHOW_UNUSED
        !          1051:   printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n",
        !          1052:         m.mmr_unused1[0],
        !          1053:         m.mmr_unused1[1],
        !          1054:         m.mmr_unused1[2],
        !          1055:         m.mmr_unused1[3],
        !          1056:         m.mmr_unused1[4]);
        !          1057: #endif /* DEBUG_SHOW_UNUSED */
        !          1058:   printk(KERN_DEBUG "dce_status: 0x%x [%s%s%s%s]\n",
        !          1059:         m.mmr_dce_status,
        !          1060:         (m.mmr_dce_status & MMR_DCE_STATUS_RX_BUSY) ? "energy detected,":"",
        !          1061:         (m.mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ?
        !          1062:         "loop test indicated," : "",
        !          1063:         (m.mmr_dce_status & MMR_DCE_STATUS_TX_BUSY) ? "transmitter on," : "",
        !          1064:         (m.mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ?
        !          1065:         "jabber timer expired," : "");
        !          1066:   printk(KERN_DEBUG "Dsp ID: %02X\n",
        !          1067:         m.mmr_dsp_id);
        !          1068: #ifdef DEBUG_SHOW_UNUSED
        !          1069:   printk(KERN_DEBUG "mmc_unused2[]: %02X:%02X\n",
        !          1070:         m.mmr_unused2[0],
        !          1071:         m.mmr_unused2[1]);
        !          1072: #endif /* DEBUG_SHOW_UNUSED */
        !          1073:   printk(KERN_DEBUG "# correct_nwid: %d, # wrong_nwid: %d\n",
        !          1074:         (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l,
        !          1075:         (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l);
        !          1076:   printk(KERN_DEBUG "thr_pre_set: 0x%x [current signal %s]\n",
        !          1077:         m.mmr_thr_pre_set & MMR_THR_PRE_SET,
        !          1078:         (m.mmr_thr_pre_set & MMR_THR_PRE_SET_CUR) ? "above" : "below");
        !          1079:   printk(KERN_DEBUG "signal_lvl: %d [%s], ",
        !          1080:         m.mmr_signal_lvl & MMR_SIGNAL_LVL,
        !          1081:         (m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) ? "new msg" : "no new msg");
        !          1082:   printk("silence_lvl: %d [%s], ", m.mmr_silence_lvl & MMR_SILENCE_LVL,
        !          1083:         (m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) ? "update done" : "no new update");
        !          1084:   printk("sgnl_qual: 0x%x [%s]\n",
        !          1085:         m.mmr_sgnl_qual & MMR_SGNL_QUAL,
        !          1086:         (m.mmr_sgnl_qual & MMR_SGNL_QUAL_ANT) ? "Antenna 1" : "Antenna 0");
        !          1087: #ifdef DEBUG_SHOW_UNUSED
        !          1088:   printk(KERN_DEBUG "netw_id_l: %x\n", m.mmr_netw_id_l);
        !          1089: #endif /* DEBUG_SHOW_UNUSED */
        !          1090: } /* wv_mmc_show */
        !          1091: #endif /* DEBUG_MMC_SHOW */
        !          1092: 
        !          1093: #ifdef DEBUG_I82586_SHOW
        !          1094: /*------------------------------------------------------------------*/
        !          1095: /*
        !          1096:  * Print the last block of the i82586 memory
        !          1097:  */
        !          1098: static void
        !          1099: wv_scb_show(u_long     ioaddr)
        !          1100: {
        !          1101:   scb_t                scb;
        !          1102: 
        !          1103:   obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb));   
        !          1104: 
        !          1105:   printk(KERN_DEBUG "##### WaveLAN system control block: #####\n");
        !          1106: 
        !          1107:   printk(KERN_DEBUG "status: ");
        !          1108:   printk("stat 0x%x[%s%s%s%s] ",
        !          1109:         (scb.scb_status & (SCB_ST_CX | SCB_ST_FR | SCB_ST_CNA | SCB_ST_RNR)) >> 12,
        !          1110:         (scb.scb_status & SCB_ST_CX) ? "cmd completion interrupt," : "",
        !          1111:         (scb.scb_status & SCB_ST_FR) ? "frame received," : "",
        !          1112:         (scb.scb_status & SCB_ST_CNA) ? "cmd unit not active," : "",
        !          1113:         (scb.scb_status & SCB_ST_RNR) ? "rcv unit not ready," : "");
        !          1114:   printk("cus 0x%x[%s%s%s] ",
        !          1115:         (scb.scb_status & SCB_ST_CUS) >> 8,
        !          1116:         ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_IDLE) ? "idle" : "",
        !          1117:         ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_SUSP) ? "suspended" : "",
        !          1118:         ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_ACTV) ? "active" : "");
        !          1119:   printk("rus 0x%x[%s%s%s%s]\n",
        !          1120:         (scb.scb_status & SCB_ST_RUS) >> 4,
        !          1121:         ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_IDLE) ? "idle" : "",
        !          1122:         ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_SUSP) ? "suspended" : "",
        !          1123:         ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_NRES) ? "no resources" : "",
        !          1124:         ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_RDY) ? "ready" : "");
        !          1125: 
        !          1126:   printk(KERN_DEBUG "command: ");
        !          1127:   printk("ack 0x%x[%s%s%s%s] ",
        !          1128:         (scb.scb_command & (SCB_CMD_ACK_CX | SCB_CMD_ACK_FR | SCB_CMD_ACK_CNA | SCB_CMD_ACK_RNR)) >> 12,
        !          1129:         (scb.scb_command & SCB_CMD_ACK_CX) ? "ack cmd completion," : "",
        !          1130:         (scb.scb_command & SCB_CMD_ACK_FR) ? "ack frame received," : "",
        !          1131:         (scb.scb_command & SCB_CMD_ACK_CNA) ? "ack CU not active," : "",
        !          1132:         (scb.scb_command & SCB_CMD_ACK_RNR) ? "ack RU not ready," : "");
        !          1133:   printk("cuc 0x%x[%s%s%s%s%s] ",
        !          1134:         (scb.scb_command & SCB_CMD_CUC) >> 8,
        !          1135:         ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_NOP) ? "nop" : "",
        !          1136:         ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_GO) ? "start cbl_offset" : "",
        !          1137:         ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_RES) ? "resume execution" : "",
        !          1138:         ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_SUS) ? "suspend execution" : "",
        !          1139:         ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_ABT) ? "abort execution" : "");
        !          1140:   printk("ruc 0x%x[%s%s%s%s%s]\n",
        !          1141:         (scb.scb_command & SCB_CMD_RUC) >> 4,
        !          1142:         ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_NOP) ? "nop" : "",
        !          1143:         ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_GO) ? "start rfa_offset" : "",
        !          1144:         ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_RES) ? "resume reception" : "",
        !          1145:         ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_SUS) ? "suspend reception" : "",
        !          1146:         ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_ABT) ? "abort reception" : "");
        !          1147: 
        !          1148:   printk(KERN_DEBUG "cbl_offset 0x%x ", scb.scb_cbl_offset);
        !          1149:   printk("rfa_offset 0x%x\n", scb.scb_rfa_offset);
        !          1150: 
        !          1151:   printk(KERN_DEBUG "crcerrs %d ", scb.scb_crcerrs);
        !          1152:   printk("alnerrs %d ", scb.scb_alnerrs);
        !          1153:   printk("rscerrs %d ", scb.scb_rscerrs);
        !          1154:   printk("ovrnerrs %d\n", scb.scb_ovrnerrs);
        !          1155: }
        !          1156: 
        !          1157: /*------------------------------------------------------------------*/
        !          1158: /*
        !          1159:  * Print the formatted status of the i82586's receive unit.
        !          1160:  */
        !          1161: static void
        !          1162: wv_ru_show(device *    dev)
        !          1163: {
        !          1164:   /* net_local *lp = (net_local *) dev->priv; */
        !          1165: 
        !          1166:   printk(KERN_DEBUG "##### WaveLAN i82586 receiver unit status: #####\n");
        !          1167:   printk(KERN_DEBUG "ru:");
        !          1168:   /*
        !          1169:    * Not implemented yet...
        !          1170:    */
        !          1171:   printk("\n");
        !          1172: } /* wv_ru_show */
        !          1173: 
        !          1174: /*------------------------------------------------------------------*/
        !          1175: /*
        !          1176:  * Display info about one control block of the i82586 memory
        !          1177:  */
        !          1178: static void
        !          1179: wv_cu_show_one(device *                dev,
        !          1180:               net_local *      lp,
        !          1181:               int              i,
        !          1182:               u_short          p)
        !          1183: {
        !          1184:   u_long               ioaddr;
        !          1185:   ac_tx_t              actx;
        !          1186: 
        !          1187:   ioaddr = dev->base_addr;
        !          1188: 
        !          1189:   printk("%d: 0x%x:", i, p);
        !          1190: 
        !          1191:   obram_read(ioaddr, p, (unsigned char *)&actx, sizeof(actx));
        !          1192:   printk(" status=0x%x,", actx.tx_h.ac_status);
        !          1193:   printk(" command=0x%x,", actx.tx_h.ac_command);
        !          1194: 
        !          1195:   /*
        !          1196:   {
        !          1197:     tbd_t      tbd;
        !          1198: 
        !          1199:     obram_read(ioaddr, actx.tx_tbd_offset, (unsigned char *)&tbd, sizeof(tbd));
        !          1200:     printk(" tbd_status=0x%x,", tbd.tbd_status);
        !          1201:   }
        !          1202:   */
        !          1203: 
        !          1204:   printk("|");
        !          1205: }
        !          1206: 
        !          1207: /*------------------------------------------------------------------*/
        !          1208: /*
        !          1209:  * Print status of the command unit of the i82586
        !          1210:  */
        !          1211: static void
        !          1212: wv_cu_show(device *    dev)
        !          1213: {
        !          1214:   net_local *  lp = (net_local *)dev->priv;
        !          1215:   unsigned int i;
        !          1216:   u_short      p;
        !          1217: 
        !          1218:   printk(KERN_DEBUG "##### WaveLAN i82586 command unit status: #####\n");
        !          1219: 
        !          1220:   printk(KERN_DEBUG);
        !          1221:   for(i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++)
        !          1222:     {
        !          1223:       wv_cu_show_one(dev, lp, i, p);
        !          1224: 
        !          1225:       p += TXBLOCKZ;
        !          1226:       if(p >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
        !          1227:        p -= NTXBLOCKS * TXBLOCKZ;
        !          1228:     }
        !          1229:   printk("\n");
        !          1230: }
        !          1231: #endif /* DEBUG_I82586_SHOW */
        !          1232: 
        !          1233: #ifdef DEBUG_DEVICE_SHOW
        !          1234: /*------------------------------------------------------------------*/
        !          1235: /*
        !          1236:  * Print the formatted status of the WaveLAN PCMCIA device driver.
        !          1237:  */
        !          1238: static void
        !          1239: wv_dev_show(device *   dev)
        !          1240: {
        !          1241:   printk(KERN_DEBUG "dev:");
        !          1242:   printk(" start=%d,", dev->start);
        !          1243:   printk(" tbusy=%ld,", dev->tbusy);
        !          1244:   printk(" interrupt=%d,", dev->interrupt);
        !          1245:   printk(" trans_start=%ld,", dev->trans_start);
        !          1246:   printk(" flags=0x%x,", dev->flags);
        !          1247:   printk("\n");
        !          1248: } /* wv_dev_show */
        !          1249: 
        !          1250: /*------------------------------------------------------------------*/
        !          1251: /*
        !          1252:  * Print the formatted status of the WaveLAN PCMCIA device driver's
        !          1253:  * private information.
        !          1254:  */
        !          1255: static void
        !          1256: wv_local_show(device * dev)
        !          1257: {
        !          1258:   net_local *lp;
        !          1259: 
        !          1260:   lp = (net_local *)dev->priv;
        !          1261: 
        !          1262:   printk(KERN_DEBUG "local:");
        !          1263:   printk(" tx_n_in_use=%d,", lp->tx_n_in_use);
        !          1264:   printk(" hacr=0x%x,", lp->hacr);
        !          1265:   printk(" rx_head=0x%x,", lp->rx_head);
        !          1266:   printk(" rx_last=0x%x,", lp->rx_last);
        !          1267:   printk(" tx_first_free=0x%x,", lp->tx_first_free);
        !          1268:   printk(" tx_first_in_use=0x%x,", lp->tx_first_in_use);
        !          1269:   printk("\n");
        !          1270: } /* wv_local_show */
        !          1271: #endif /* DEBUG_DEVICE_SHOW */
        !          1272: 
        !          1273: #if defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO)
        !          1274: /*------------------------------------------------------------------*/
        !          1275: /*
        !          1276:  * Dump packet header (and content if necessary) on the screen
        !          1277:  */
        !          1278: static inline void
        !          1279: wv_packet_info(u_char *                p,              /* Packet to dump */
        !          1280:               int              length,         /* Length of the packet */
        !          1281:               char *           msg1,           /* Name of the device */
        !          1282:               char *           msg2)           /* Name of the function */
        !          1283: {
        !          1284: #ifndef DEBUG_PACKET_DUMP
        !          1285:   printk(KERN_DEBUG "%s: %s(): dest %02X:%02X:%02X:%02X:%02X:%02X, length %d\n",
        !          1286:         msg1, msg2, p[0], p[1], p[2], p[3], p[4], p[5], length);
        !          1287:   printk(KERN_DEBUG "%s: %s(): src %02X:%02X:%02X:%02X:%02X:%02X, type 0x%02X%02X\n",
        !          1288:         msg1, msg2, p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13]);
        !          1289: 
        !          1290: #else  /* DEBUG_PACKET_DUMP */
        !          1291:   int          i;
        !          1292:   int          maxi;
        !          1293: 
        !          1294:   printk(KERN_DEBUG "%s: %s(): len=%d, data=\"", msg1, msg2, length);
        !          1295: 
        !          1296:   if((maxi = length) > DEBUG_PACKET_DUMP)
        !          1297:     maxi = DEBUG_PACKET_DUMP;
        !          1298:   for(i = 0; i < maxi; i++)
        !          1299:     if(p[i] >= ' ' && p[i] <= '~')
        !          1300:       printk(" %c", p[i]);
        !          1301:     else
        !          1302:       printk("%02X", p[i]);
        !          1303:   if(maxi < length)
        !          1304:     printk("..");
        !          1305:   printk("\"\n");
        !          1306:   printk(KERN_DEBUG "\n");
        !          1307: #endif /* DEBUG_PACKET_DUMP */
        !          1308: }
        !          1309: #endif /* defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) */
        !          1310: 
        !          1311: /*------------------------------------------------------------------*/
        !          1312: /*
        !          1313:  * This is the information which is displayed by the driver at startup
        !          1314:  * There  is a lot of flag to configure it at your will...
        !          1315:  */
        !          1316: static inline void
        !          1317: wv_init_info(device *  dev)
        !          1318: {
        !          1319:   short                ioaddr = dev->base_addr;
        !          1320:   net_local *  lp = (net_local *)dev->priv;
        !          1321:   psa_t                psa;
        !          1322:   int          i;
        !          1323: 
        !          1324:   /* Read the parameter storage area */
        !          1325:   psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
        !          1326: 
        !          1327: #ifdef DEBUG_PSA_SHOW
        !          1328:   wv_psa_show(&psa);
        !          1329: #endif
        !          1330: #ifdef DEBUG_MMC_SHOW
        !          1331:   wv_mmc_show(dev);
        !          1332: #endif
        !          1333: #ifdef DEBUG_I82586_SHOW
        !          1334:   wv_cu_show(dev);
        !          1335: #endif
        !          1336: 
        !          1337: #ifdef DEBUG_BASIC_SHOW
        !          1338:   /* Now, let's go for the basic stuff */
        !          1339:   printk(KERN_NOTICE "%s: WaveLAN at %#x,", dev->name, ioaddr);
        !          1340:   for(i = 0; i < WAVELAN_ADDR_SIZE; i++)
        !          1341:     printk("%s%02X", (i == 0) ? " " : ":", dev->dev_addr[i]);
        !          1342:   printk(", IRQ %d", dev->irq);
        !          1343: 
        !          1344:   /* Print current network id */
        !          1345:   if(psa.psa_nwid_select)
        !          1346:     printk(", nwid 0x%02X-%02X", psa.psa_nwid[0], psa.psa_nwid[1]);
        !          1347:   else
        !          1348:     printk(", nwid off");
        !          1349: 
        !          1350:   /* If 2.00 card */
        !          1351:   if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
        !          1352:        (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
        !          1353:     {
        !          1354:       unsigned short   freq;
        !          1355: 
        !          1356:       /* Ask the EEPROM to read the frequency from the first area */
        !          1357:       fee_read(ioaddr, 0x00 /* 1st area - frequency... */,
        !          1358:               &freq, 1);
        !          1359: 
        !          1360:       /* Print frequency */
        !          1361:       printk(", 2.00, %ld", (freq >> 6) + 2400L);
        !          1362: 
        !          1363:       /* Hack !!! */
        !          1364:       if(freq & 0x20)
        !          1365:        printk(".5");
        !          1366:     }
        !          1367:   else
        !          1368:     {
        !          1369:       printk(", PC");
        !          1370:       switch(psa.psa_comp_number)
        !          1371:        {
        !          1372:        case PSA_COMP_PC_AT_915:
        !          1373:        case PSA_COMP_PC_AT_2400:
        !          1374:          printk("-AT");
        !          1375:          break;
        !          1376:        case PSA_COMP_PC_MC_915:
        !          1377:        case PSA_COMP_PC_MC_2400:
        !          1378:          printk("-MC");
        !          1379:          break;
        !          1380:        case PSA_COMP_PCMCIA_915:
        !          1381:          printk("MCIA");
        !          1382:          break;
        !          1383:        default:
        !          1384:          printk("???");
        !          1385:        }
        !          1386:       printk(", ");
        !          1387:       switch (psa.psa_subband)
        !          1388:        {
        !          1389:        case PSA_SUBBAND_915:
        !          1390:          printk("915");
        !          1391:          break;
        !          1392:        case PSA_SUBBAND_2425:
        !          1393:          printk("2425");
        !          1394:          break;
        !          1395:        case PSA_SUBBAND_2460:
        !          1396:          printk("2460");
        !          1397:          break;
        !          1398:        case PSA_SUBBAND_2484:
        !          1399:          printk("2484");
        !          1400:          break;
        !          1401:        case PSA_SUBBAND_2430_5:
        !          1402:          printk("2430.5");
        !          1403:          break;
        !          1404:        default:
        !          1405:          printk("???");
        !          1406:        }
        !          1407:     }
        !          1408: 
        !          1409:   printk(" MHz\n");
        !          1410: #endif /* DEBUG_BASIC_SHOW */
        !          1411: 
        !          1412: #ifdef DEBUG_VERSION_SHOW
        !          1413:   /* Print version information */
        !          1414:   printk(KERN_NOTICE "%s", version);
        !          1415: #endif
        !          1416: } /* wv_init_info */
        !          1417: 
        !          1418: /********************* IOCTL, STATS & RECONFIG *********************/
        !          1419: /*
        !          1420:  * We found here routines that are called by Linux on differents
        !          1421:  * occasions after the configuration and not for transmitting data
        !          1422:  * These may be called when the user use ifconfig, /proc/net/dev
        !          1423:  * or wireless extensions
        !          1424:  */
        !          1425: 
        !          1426: /*------------------------------------------------------------------*/
        !          1427: /*
        !          1428:  * Get the current ethernet statistics. This may be called with the
        !          1429:  * card open or closed.
        !          1430:  * Used when the user read /proc/net/dev
        !          1431:  */
        !          1432: static en_stats        *
        !          1433: wavelan_get_stats(device *     dev)
        !          1434: {
        !          1435: #ifdef DEBUG_IOCTL_TRACE
        !          1436:   printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name);
        !          1437: #endif
        !          1438: 
        !          1439:   return(&((net_local *) dev->priv)->stats);
        !          1440: }
        !          1441: 
        !          1442: /*------------------------------------------------------------------*/
        !          1443: /*
        !          1444:  * Set or clear the multicast filter for this adaptor.
        !          1445:  * num_addrs == -1     Promiscuous mode, receive all packets
        !          1446:  * num_addrs == 0      Normal mode, clear multicast list
        !          1447:  * num_addrs > 0       Multicast mode, receive normal and MC packets,
        !          1448:  *                     and do best-effort filtering.
        !          1449:  */
        !          1450: static void
        !          1451: wavelan_set_multicast_list(device *    dev)
        !          1452: {
        !          1453:   net_local *  lp = (net_local *) dev->priv;
        !          1454: 
        !          1455: #ifdef DEBUG_IOCTL_TRACE
        !          1456:   printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n", dev->name);
        !          1457: #endif
        !          1458: 
        !          1459: #ifdef DEBUG_IOCTL_INFO
        !          1460:   printk(KERN_DEBUG "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n",
        !          1461:         dev->name, dev->flags, dev->mc_count);
        !          1462: #endif
        !          1463: 
        !          1464:   /* If we ask for promiscuous mode,
        !          1465:    * or all multicast addresses (we don't have that !)
        !          1466:    * or too much multicast addresses for the hardware filter */
        !          1467:   if((dev->flags & IFF_PROMISC) ||
        !          1468:      (dev->flags & IFF_ALLMULTI) ||
        !          1469:      (dev->mc_count > I82586_MAX_MULTICAST_ADDRESSES))
        !          1470:     {
        !          1471:       /*
        !          1472:        * Enable promiscuous mode: receive all packets.
        !          1473:        */
        !          1474:       if(!lp->promiscuous)
        !          1475:        {
        !          1476:          lp->promiscuous = 1;
        !          1477:          lp->mc_count = 0;
        !          1478: 
        !          1479:          wv_82586_reconfig(dev);
        !          1480: 
        !          1481:          /* Tell the kernel that we are doing a really bad job... */
        !          1482:          dev->flags |= IFF_PROMISC;
        !          1483:        }
        !          1484:     }
        !          1485:   else
        !          1486:     /* If there is some multicast addresses to send */
        !          1487:     if(dev->mc_list != (struct dev_mc_list *) NULL)
        !          1488:       {
        !          1489:        /*
        !          1490:         * Disable promiscuous mode, but receive all packets
        !          1491:         * in multicast list
        !          1492:         */
        !          1493: #ifdef MULTICAST_AVOID
        !          1494:        if(lp->promiscuous ||
        !          1495:           (dev->mc_count != lp->mc_count))
        !          1496: #endif
        !          1497:          {
        !          1498:            lp->promiscuous = 0;
        !          1499:            lp->mc_count = dev->mc_count;
        !          1500: 
        !          1501:            wv_82586_reconfig(dev);
        !          1502:          }
        !          1503:       }
        !          1504:     else
        !          1505:       {
        !          1506:        /*
        !          1507:         * Switch to normal mode: disable promiscuous mode and 
        !          1508:         * clear the multicast list.
        !          1509:         */
        !          1510:        if(lp->promiscuous || lp->mc_count == 0)
        !          1511:          {
        !          1512:            lp->promiscuous = 0;
        !          1513:            lp->mc_count = 0;
        !          1514: 
        !          1515:            wv_82586_reconfig(dev);
        !          1516:          }
        !          1517:       }
        !          1518: #ifdef DEBUG_IOCTL_TRACE
        !          1519:   printk(KERN_DEBUG "%s: <-wavelan_set_multicast_list()\n", dev->name);
        !          1520: #endif
        !          1521: }
        !          1522: 
        !          1523: /*------------------------------------------------------------------*/
        !          1524: /*
        !          1525:  * This function doesn't exist...
        !          1526:  */
        !          1527: static int
        !          1528: wavelan_set_mac_address(device *       dev,
        !          1529:                        void *          addr)
        !          1530: {
        !          1531:   struct sockaddr *    mac = addr;
        !          1532: 
        !          1533:   /* Copy the address */
        !          1534:   memcpy(dev->dev_addr, mac->sa_data, WAVELAN_ADDR_SIZE);
        !          1535: 
        !          1536:   /* Reconfig the beast */
        !          1537:   wv_82586_reconfig(dev);
        !          1538: 
        !          1539:   return 0;
        !          1540: }
        !          1541: 
        !          1542: #ifdef WIRELESS_EXT    /* If wireless extension exist in the kernel */
        !          1543: 
        !          1544: /*------------------------------------------------------------------*/
        !          1545: /*
        !          1546:  * Frequency setting (for hardware able of it)
        !          1547:  * It's a bit complicated and you don't really want to look into it...
        !          1548:  * (called in wavelan_ioctl)
        !          1549:  */
        !          1550: static inline int
        !          1551: wv_set_frequency(u_long                ioaddr, /* i/o port of the card */
        !          1552:                 iw_freq *      frequency)
        !          1553: {
        !          1554:   const int    BAND_NUM = 10;  /* Number of bands */
        !          1555:   long         freq = 0L;      /* offset to 2.4 GHz in .5 MHz */
        !          1556: #ifdef DEBUG_IOCTL_INFO
        !          1557:   int          i;
        !          1558: #endif
        !          1559: 
        !          1560:   /* Setting by frequency */
        !          1561:   /* Theoretically, you may set any frequency between
        !          1562:    * the two limits with a 0.5 MHz precision. In practice,
        !          1563:    * I don't want you to have trouble with local
        !          1564:    * regulations... */
        !          1565:   if((frequency->e == 1) &&
        !          1566:      (frequency->m >= (int) 2.412e8) && (frequency->m <= (int) 2.487e8))
        !          1567:     {
        !          1568:       freq = ((frequency->m / 10000) - 24000L) / 5;
        !          1569:     }
        !          1570: 
        !          1571:   /* Setting by channel (same as wfreqsel) */
        !          1572:   /* Warning : each channel is 22MHz wide, so some of the channels
        !          1573:    * will interfere... */
        !          1574:   if((frequency->e == 0) &&
        !          1575:      (frequency->m >= 0) && (frequency->m < BAND_NUM))
        !          1576:     {
        !          1577:       /* frequency in 1/4 of MHz (as read in the offset register) */
        !          1578:       short    bands[] = { 0x30, 0x58, 0x64, 0x7A, 0x80, 0xA8, 0xD0, 0xF0, 0xF8, 0x150 };
        !          1579: 
        !          1580:       /* Get frequency offset */
        !          1581:       freq = bands[frequency->m] >> 1;
        !          1582:     }
        !          1583: 
        !          1584:   /* Verify if the frequency is allowed */
        !          1585:   if(freq != 0L)
        !          1586:     {
        !          1587:       u_short  table[10];      /* Authorized frequency table */
        !          1588: 
        !          1589:       /* Read the frequency table */
        !          1590:       fee_read(ioaddr, 0x71 /* frequency table */,
        !          1591:               table, 10);
        !          1592: 
        !          1593: #ifdef DEBUG_IOCTL_INFO
        !          1594:       printk(KERN_DEBUG "Frequency table :");
        !          1595:       for(i = 0; i < 10; i++)
        !          1596:        {
        !          1597:          printk(" %04X",
        !          1598:                 table[i]);
        !          1599:        }
        !          1600:       printk("\n");
        !          1601: #endif
        !          1602: 
        !          1603:       /* Look in the table if the frequency is allowed */
        !          1604:       if(!(table[9 - ((freq - 24) / 16)] &
        !          1605:           (1 << ((freq - 24) % 16))))
        !          1606:        return -EINVAL;         /* not allowed */
        !          1607:     }
        !          1608:   else
        !          1609:     return -EINVAL;
        !          1610: 
        !          1611:   /* If we get a usable frequency */
        !          1612:   if(freq != 0L)
        !          1613:     {
        !          1614:       unsigned short   area[16];
        !          1615:       unsigned short   dac[2];
        !          1616:       unsigned short   area_verify[16];
        !          1617:       unsigned short   dac_verify[2];
        !          1618:       /* Corresponding gain (in the power adjust value table)
        !          1619:        * see AT&T WaveLAN Data Manual, REF 407-024689/E, page 3-8
        !          1620:        * & WCIN062D.DOC, page 6.2.9 */
        !          1621:       unsigned short   power_limit[] = { 40, 80, 120, 160, 0 };
        !          1622:       int              power_band = 0;         /* Selected band */
        !          1623:       unsigned short   power_adjust;           /* Correct value */
        !          1624: 
        !          1625:       /* Search for the gain */
        !          1626:       power_band = 0;
        !          1627:       while((freq > power_limit[power_band]) &&
        !          1628:            (power_limit[++power_band] != 0))
        !          1629:        ;
        !          1630: 
        !          1631:       /* Read the first area */
        !          1632:       fee_read(ioaddr, 0x00,
        !          1633:               area, 16);
        !          1634: 
        !          1635:       /* Read the DAC */
        !          1636:       fee_read(ioaddr, 0x60,
        !          1637:               dac, 2);
        !          1638: 
        !          1639:       /* Read the new power adjust value */
        !          1640:       fee_read(ioaddr, 0x6B - (power_band >> 1),
        !          1641:               &power_adjust, 1);
        !          1642:       if(power_band & 0x1)
        !          1643:        power_adjust >>= 8;
        !          1644:       else
        !          1645:        power_adjust &= 0xFF;
        !          1646: 
        !          1647: #ifdef DEBUG_IOCTL_INFO
        !          1648:       printk(KERN_DEBUG "WaveLAN EEPROM Area 1:");
        !          1649:       for(i = 0; i < 16; i++)
        !          1650:        {
        !          1651:          printk(" %04X",
        !          1652:                 area[i]);
        !          1653:        }
        !          1654:       printk("\n");
        !          1655: 
        !          1656:       printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n",
        !          1657:             dac[0], dac[1]);
        !          1658: #endif
        !          1659: 
        !          1660:       /* Frequency offset (for info only) */
        !          1661:       area[0] = ((freq << 5) & 0xFFE0) | (area[0] & 0x1F);
        !          1662: 
        !          1663:       /* Receiver Principle main divider coefficient */
        !          1664:       area[3] = (freq >> 1) + 2400L - 352L;
        !          1665:       area[2] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);
        !          1666: 
        !          1667:       /* Transmitter Main divider coefficient */
        !          1668:       area[13] = (freq >> 1) + 2400L;
        !          1669:       area[12] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);
        !          1670: 
        !          1671:       /* Others part of the area are flags, bit streams or unused... */
        !          1672: 
        !          1673:       /* Set the value in the DAC. */
        !          1674:       dac[1] = ((power_adjust >> 1) & 0x7F) | (dac[1] & 0xFF80);
        !          1675:       dac[0] = ((power_adjust & 0x1) << 4) | (dac[0] & 0xFFEF);
        !          1676: 
        !          1677:       /* Write the first area. */
        !          1678:       fee_write(ioaddr, 0x00,
        !          1679:                area, 16);
        !          1680: 
        !          1681:       /* Write the DAC. */
        !          1682:       fee_write(ioaddr, 0x60,
        !          1683:                dac, 2);
        !          1684: 
        !          1685:       /* We now should verify here that the EEPROM writing was OK. */
        !          1686: 
        !          1687:       /* Reread the first area. */
        !          1688:       fee_read(ioaddr, 0x00,
        !          1689:               area_verify, 16);
        !          1690: 
        !          1691:       /* ReRead the DAC */
        !          1692:       fee_read(ioaddr, 0x60,
        !          1693:               dac_verify, 2);
        !          1694: 
        !          1695:       /* Compare */
        !          1696:       if(memcmp(area, area_verify, 16 * 2) ||
        !          1697:         memcmp(dac, dac_verify, 2 * 2))
        !          1698:        {
        !          1699: #ifdef DEBUG_IOCTL_ERROR
        !          1700:          printk(KERN_INFO "WaveLAN: wv_set_frequency: unable to write new frequency to EEPROM(?).\n");
        !          1701: #endif
        !          1702:          return -EOPNOTSUPP;
        !          1703:        }
        !          1704: 
        !          1705:       /* We must download the frequency parameters to the
        !          1706:        * synthesizers (from the EEPROM - area 1)
        !          1707:        * Note: as the EEPROM is automatically decremented, we set the end
        !          1708:        * if the area... */
        !          1709:       mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x0F);
        !          1710:       mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
        !          1711:              MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);
        !          1712: 
        !          1713:       /* Wait until the download is finished */
        !          1714:       fee_wait(ioaddr, 100, 100);
        !          1715: 
        !          1716:       /* We must now download the power adjust value (gain) to
        !          1717:        * the synthesizers (from the EEPROM - area 7 - DAC) */
        !          1718:       mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x61);
        !          1719:       mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
        !          1720:              MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);
        !          1721: 
        !          1722:       /* Wait until the download is finished */
        !          1723:       fee_wait(ioaddr, 100, 100);
        !          1724: 
        !          1725: #ifdef DEBUG_IOCTL_INFO
        !          1726:       /* Verification of what we have done... */
        !          1727: 
        !          1728:       printk(KERN_DEBUG "WaveLAN EEPROM Area 1:");
        !          1729:       for(i = 0; i < 16; i++)
        !          1730:        {
        !          1731:          printk(" %04X",
        !          1732:                 area_verify[i]);
        !          1733:        }
        !          1734:       printk("\n");
        !          1735: 
        !          1736:       printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n",
        !          1737:             dac_verify[0], dac_verify[1]);
        !          1738: #endif
        !          1739: 
        !          1740:       return 0;
        !          1741:     }
        !          1742:   else
        !          1743:     return -EINVAL;            /* Bah, never get there... */
        !          1744: }
        !          1745: 
        !          1746: /*------------------------------------------------------------------*/
        !          1747: /*
        !          1748:  * Give the list of available frequencies
        !          1749:  */
        !          1750: static inline int
        !          1751: wv_frequency_list(u_long       ioaddr, /* i/o port of the card */
        !          1752:                  iw_freq *     list,   /* List of frequency to fill */
        !          1753:                  int           max)    /* Maximum number of frequencies */
        !          1754: {
        !          1755:   u_short      table[10];      /* Authorized frequency table */
        !          1756:   long         freq = 0L;      /* offset to 2.4 GHz in .5 MHz + 12 MHz */
        !          1757:   int          i;              /* index in the table */
        !          1758: 
        !          1759:   /* Read the frequency table */
        !          1760:   fee_read(ioaddr, 0x71 /* frequency table */,
        !          1761:           table, 10);
        !          1762: 
        !          1763:   /* Look all frequencies */
        !          1764:   i = 0;
        !          1765:   for(freq = 0; freq < 150; freq++)
        !          1766:     /* Look in the table if the frequency is allowed */
        !          1767:     if(table[9 - (freq / 16)] & (1 << (freq % 16)))
        !          1768:       {
        !          1769:        /* put in the list */
        !          1770:        list[i].m = (((freq + 24) * 5) + 24000L) * 10000;
        !          1771:        list[i++].e = 1;
        !          1772: 
        !          1773:        /* Check number */
        !          1774:        if(i >= max)
        !          1775:          return(i);
        !          1776:       }
        !          1777: 
        !          1778:   return(i);
        !          1779: }
        !          1780: 
        !          1781: #ifdef WIRELESS_SPY
        !          1782: /*------------------------------------------------------------------*/
        !          1783: /*
        !          1784:  * Gather wireless spy statistics : for each packet, compare the source
        !          1785:  * address with out list, and if match, get the stats...
        !          1786:  * Sorry, but this function really need wireless extensions...
        !          1787:  */
        !          1788: static inline void
        !          1789: wl_spy_gather(device * dev,
        !          1790:              u_char *  mac,            /* MAC address */
        !          1791:              u_char *  stats)          /* Statistics to gather */
        !          1792: {
        !          1793:   net_local *  lp = (net_local *) dev->priv;
        !          1794:   int          i;
        !          1795: 
        !          1796:   /* Look all addresses */
        !          1797:   for(i = 0; i < lp->spy_number; i++)
        !          1798:     /* If match */
        !          1799:     if(!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE))
        !          1800:       {
        !          1801:        /* Update statistics */
        !          1802:        lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL;
        !          1803:        lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL;
        !          1804:        lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL;
        !          1805:        lp->spy_stat[i].updated = 0x7;
        !          1806:       }
        !          1807: }
        !          1808: #endif /* WIRELESS_SPY */
        !          1809: 
        !          1810: #ifdef HISTOGRAM
        !          1811: /*------------------------------------------------------------------*/
        !          1812: /*
        !          1813:  * This function calculates an histogram on the signal level.
        !          1814:  * As the noise is quite constant, it's like doing it on the SNR.
        !          1815:  * We have defined a set of interval (lp->his_range), and each time
        !          1816:  * the level goes in that interval, we increment the count (lp->his_sum).
        !          1817:  * With this histogram you may detect if one WaveLAN is really weak,
        !          1818:  * or you may also calculate the mean and standard deviation of the level.
        !          1819:  */
        !          1820: static inline void
        !          1821: wl_his_gather(device * dev,
        !          1822:              u_char *  stats)          /* Statistics to gather */
        !          1823: {
        !          1824:   net_local *  lp = (net_local *) dev->priv;
        !          1825:   u_char       level = stats[0] & MMR_SIGNAL_LVL;
        !          1826:   int          i;
        !          1827: 
        !          1828:   /* Find the correct interval */
        !          1829:   i = 0;
        !          1830:   while((i < (lp->his_number - 1)) && (level >= lp->his_range[i++]))
        !          1831:     ;
        !          1832: 
        !          1833:   /* Increment interval counter */
        !          1834:   (lp->his_sum[i])++;
        !          1835: }
        !          1836: #endif /* HISTOGRAM */
        !          1837: 
        !          1838: /*------------------------------------------------------------------*/
        !          1839: /*
        !          1840:  * Perform ioctl : config & info stuff
        !          1841:  * This is here that are treated the wireless extensions (iwconfig)
        !          1842:  */
        !          1843: static int
        !          1844: wavelan_ioctl(struct device *  dev,    /* device on which the ioctl is applied */
        !          1845:              struct ifreq *    rq,     /* data passed */
        !          1846:              int               cmd)    /* ioctl number */
        !          1847: {
        !          1848:   u_long               ioaddr = dev->base_addr;
        !          1849:   net_local *          lp = (net_local *)dev->priv;    /* lp is not unused */
        !          1850:   struct iwreq *       wrq = (struct iwreq *) rq;
        !          1851:   psa_t                        psa;
        !          1852:   mm_t                 m;
        !          1853:   unsigned long                x;
        !          1854:   int                  ret = 0;
        !          1855: 
        !          1856: #ifdef DEBUG_IOCTL_TRACE
        !          1857:   printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, cmd);
        !          1858: #endif
        !          1859: 
        !          1860:   /* Disable interrupts & save flags */
        !          1861:   x = wv_splhi();
        !          1862: 
        !          1863:   /* Look what is the request */
        !          1864:   switch(cmd)
        !          1865:     {
        !          1866:       /* --------------- WIRELESS EXTENSIONS --------------- */
        !          1867: 
        !          1868:     case SIOCGIWNAME:
        !          1869:       strcpy(wrq->u.name, "Wavelan");
        !          1870:       break;
        !          1871: 
        !          1872:     case SIOCSIWNWID:
        !          1873:       /* Set NWID in WaveLAN */
        !          1874:       if(wrq->u.nwid.on)
        !          1875:        {
        !          1876:          /* Set NWID in psa */
        !          1877:          psa.psa_nwid[0] = (wrq->u.nwid.nwid & 0xFF00) >> 8;
        !          1878:          psa.psa_nwid[1] = wrq->u.nwid.nwid & 0xFF;
        !          1879:          psa.psa_nwid_select = 0x01;
        !          1880:          psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
        !          1881:                    (unsigned char *)psa.psa_nwid, 3);
        !          1882: 
        !          1883:          /* Set NWID in mmc */
        !          1884:          m.w.mmw_netw_id_l = wrq->u.nwid.nwid & 0xFF;
        !          1885:          m.w.mmw_netw_id_h = (wrq->u.nwid.nwid & 0xFF00) >> 8;
        !          1886:          mmc_write(ioaddr, (char *)&m.w.mmw_netw_id_l - (char *)&m,
        !          1887:                    (unsigned char *)&m.w.mmw_netw_id_l, 2);
        !          1888:          mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
        !          1889:        }
        !          1890:       else
        !          1891:        {
        !          1892:          /* Disable nwid in the psa */
        !          1893:          psa.psa_nwid_select = 0x00;
        !          1894:          psa_write(ioaddr, lp->hacr,
        !          1895:                    (char *)&psa.psa_nwid_select - (char *)&psa,
        !          1896:                    (unsigned char *)&psa.psa_nwid_select, 1);
        !          1897: 
        !          1898:          /* Disable nwid in the mmc (no filtering) */
        !          1899:          mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID);
        !          1900:        }
        !          1901:       break;
        !          1902: 
        !          1903:     case SIOCGIWNWID:
        !          1904:       /* Read the NWID */
        !          1905:       psa_read(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
        !          1906:               (unsigned char *)psa.psa_nwid, 3);
        !          1907:       wrq->u.nwid.nwid = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
        !          1908:       wrq->u.nwid.on = psa.psa_nwid_select;
        !          1909:       break;
        !          1910: 
        !          1911:     case SIOCSIWFREQ:
        !          1912:       /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) */
        !          1913:       if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
        !          1914:           (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
        !          1915:        ret = wv_set_frequency(ioaddr, &(wrq->u.freq));
        !          1916:       else
        !          1917:        ret = -EOPNOTSUPP;
        !          1918:       break;
        !          1919: 
        !          1920:     case SIOCGIWFREQ:
        !          1921:       /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
        !          1922:        * (does it work for everybody ??? - especially old cards...) */
        !          1923:       if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
        !          1924:           (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
        !          1925:        {
        !          1926:          unsigned short        freq;
        !          1927: 
        !          1928:          /* Ask the EEPROM to read the frequency from the first area */
        !          1929:          fee_read(ioaddr, 0x00 /* 1st area - frequency... */,
        !          1930:                   &freq, 1);
        !          1931:          wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
        !          1932:          wrq->u.freq.e = 1;
        !          1933:        }
        !          1934:       else
        !          1935:        {
        !          1936:          int   bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 };
        !          1937: 
        !          1938:          psa_read(ioaddr, lp->hacr, (char *)&psa.psa_subband - (char *)&psa,
        !          1939:                   (unsigned char *)&psa.psa_subband, 1);
        !          1940: 
        !          1941:          if(psa.psa_subband <= 4)
        !          1942:            {
        !          1943:              wrq->u.freq.m = bands[psa.psa_subband];
        !          1944:              wrq->u.freq.e = (psa.psa_subband != 0);
        !          1945:            }
        !          1946:          else
        !          1947:            ret = -EOPNOTSUPP;
        !          1948:        }
        !          1949:       break;
        !          1950: 
        !          1951:     case SIOCSIWSENS:
        !          1952:       /* Set the level threshold */
        !          1953:       if(!suser())
        !          1954:        return -EPERM;
        !          1955:       psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F;
        !          1956:       psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
        !          1957:               (unsigned char *) &psa.psa_thr_pre_set, 1);
        !          1958:       mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set);
        !          1959:       break;
        !          1960: 
        !          1961:     case SIOCGIWSENS:
        !          1962:       /* Read the level threshold */
        !          1963:       psa_read(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
        !          1964:               (unsigned char *) &psa.psa_thr_pre_set, 1);
        !          1965:       wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F;
        !          1966:       break;
        !          1967: 
        !          1968:      case SIOCSIWENCODE:
        !          1969:        /* Set encryption key */
        !          1970:        if(!mmc_encr(ioaddr))
        !          1971:         {
        !          1972:           ret = -EOPNOTSUPP;
        !          1973:           break;
        !          1974:         }
        !          1975: 
        !          1976:        if(wrq->u.encoding.method)
        !          1977:         {      /* enable encryption */
        !          1978:           int          i;
        !          1979:           long long    key = wrq->u.encoding.code;
        !          1980: 
        !          1981:           for(i = 7; i >= 0; i--)
        !          1982:             {
        !          1983:               psa.psa_encryption_key[i] = key & 0xFF;
        !          1984:               key >>= 8;
        !          1985:             }
        !          1986:            psa.psa_encryption_select = 1;
        !          1987:           psa_write(ioaddr, lp->hacr,
        !          1988:                     (char *) &psa.psa_encryption_select - (char *) &psa,
        !          1989:                     (unsigned char *) &psa.psa_encryption_select, 8+1);
        !          1990: 
        !          1991:            mmc_out(ioaddr, mmwoff(0, mmw_encr_enable),
        !          1992:                   MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
        !          1993:            mmc_write(ioaddr, mmwoff(0, mmw_encr_key),
        !          1994:                     (unsigned char *) &psa.psa_encryption_key, 8);
        !          1995:         }
        !          1996:        else
        !          1997:         {      /* disable encryption */
        !          1998:           psa.psa_encryption_select = 0;
        !          1999:           psa_write(ioaddr, lp->hacr,
        !          2000:                     (char *) &psa.psa_encryption_select - (char *) &psa,
        !          2001:                     (unsigned char *) &psa.psa_encryption_select, 1);
        !          2002: 
        !          2003:           mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);
        !          2004:         }
        !          2005:        break;
        !          2006: 
        !          2007:      case SIOCGIWENCODE:
        !          2008:        /* Read the encryption key */
        !          2009:        if(!mmc_encr(ioaddr))
        !          2010:         {
        !          2011:           ret = -EOPNOTSUPP;
        !          2012:           break;
        !          2013:         }
        !          2014: 
        !          2015:        /* only super-user can see encryption key */
        !          2016:        if(!suser())
        !          2017:         {
        !          2018:           ret = -EPERM;
        !          2019:           break;
        !          2020:         }
        !          2021:        else
        !          2022:         {
        !          2023:           int          i;
        !          2024:           long long    key = 0;
        !          2025: 
        !          2026:           psa_read(ioaddr, lp->hacr,
        !          2027:                    (char *) &psa.psa_encryption_select - (char *) &psa,
        !          2028:                    (unsigned char *) &psa.psa_encryption_select, 1+8);
        !          2029:           for(i = 0; i < 8; i++)
        !          2030:             {
        !          2031:               key <<= 8;
        !          2032:               key += psa.psa_encryption_key[i];
        !          2033:             }
        !          2034:           wrq->u.encoding.code = key;
        !          2035: 
        !          2036:           /* encryption is enabled */
        !          2037:           if(psa.psa_encryption_select)
        !          2038:             wrq->u.encoding.method = mmc_encr(ioaddr);
        !          2039:           else
        !          2040:             wrq->u.encoding.method = 0;
        !          2041:         }
        !          2042:        break;
        !          2043: 
        !          2044:     case SIOCGIWRANGE:
        !          2045:       /* basic checking */
        !          2046:       if(wrq->u.data.pointer != (caddr_t) 0)
        !          2047:        {
        !          2048:          struct iw_range       range;
        !          2049: 
        !          2050:          /* Verify the user buffer */
        !          2051:          ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
        !          2052:                            sizeof(struct iw_range));
        !          2053:          if(ret)
        !          2054:            break;
        !          2055: 
        !          2056:          /* Set the length (useless : its constant...) */
        !          2057:          wrq->u.data.length = sizeof(struct iw_range);
        !          2058: 
        !          2059:          /* Set information in the range struct */
        !          2060:          range.throughput = 1.6 * 1024 * 1024; /* don't argue on this ! */
        !          2061:          range.min_nwid = 0x0000;
        !          2062:          range.max_nwid = 0xFFFF;
        !          2063: 
        !          2064:          /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
        !          2065:          if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
        !          2066:               (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
        !          2067:            {
        !          2068:              range.num_channels = 10;
        !          2069:              range.num_frequency = wv_frequency_list(ioaddr, range.freq,
        !          2070:                                                      IW_MAX_FREQUENCIES);
        !          2071:            }
        !          2072:          else
        !          2073:            range.num_channels = range.num_frequency = 0;
        !          2074: 
        !          2075:          range.sensitivity = 0x3F;
        !          2076:          range.max_qual.qual = MMR_SGNL_QUAL;
        !          2077:          range.max_qual.level = MMR_SIGNAL_LVL;
        !          2078:          range.max_qual.noise = MMR_SILENCE_LVL;
        !          2079: 
        !          2080:          /* Copy structure to the user buffer */
        !          2081:          copy_to_user(wrq->u.data.pointer, &range,
        !          2082:                       sizeof(struct iw_range));
        !          2083:        }
        !          2084:       break;
        !          2085: 
        !          2086:     case SIOCGIWPRIV:
        !          2087:       /* Basic checking... */
        !          2088:       if(wrq->u.data.pointer != (caddr_t) 0)
        !          2089:        {
        !          2090:          struct iw_priv_args   priv[] =
        !          2091:          {     /* cmd,         set_args,       get_args,       name */
        !          2092:            { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" },
        !          2093:            { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" },
        !          2094: 
        !          2095:            { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16,     0, "sethisto" },
        !          2096:            { SIOCGIPHISTO, 0,      IW_PRIV_TYPE_INT | 16, "gethisto" },
        !          2097:          };
        !          2098: 
        !          2099:          /* Verify the user buffer */
        !          2100:          ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
        !          2101:                            sizeof(priv));
        !          2102:          if(ret)
        !          2103:            break;
        !          2104: 
        !          2105:          /* Set the number of ioctl available */
        !          2106:          wrq->u.data.length = 4;
        !          2107: 
        !          2108:          /* Copy structure to the user buffer */
        !          2109:          copy_to_user(wrq->u.data.pointer, (u_char *) priv,
        !          2110:                       sizeof(priv));
        !          2111:        }
        !          2112:       break;
        !          2113: 
        !          2114: #ifdef WIRELESS_SPY
        !          2115:     case SIOCSIWSPY:
        !          2116:       /* Set the spy list */
        !          2117: 
        !          2118:       /* Check the number of addresses */
        !          2119:       if(wrq->u.data.length > IW_MAX_SPY)
        !          2120:        {
        !          2121:          ret = -E2BIG;
        !          2122:          break;
        !          2123:        }
        !          2124:       lp->spy_number = wrq->u.data.length;
        !          2125: 
        !          2126:       /* If there is some addresses to copy */
        !          2127:       if(lp->spy_number > 0)
        !          2128:        {
        !          2129:          struct sockaddr       address[IW_MAX_SPY];
        !          2130:          int                   i;
        !          2131: 
        !          2132:          /* Verify where the user has set his addresses */
        !          2133:          ret = verify_area(VERIFY_READ, wrq->u.data.pointer,
        !          2134:                            sizeof(struct sockaddr) * lp->spy_number);
        !          2135:          if(ret)
        !          2136:            break;
        !          2137:          /* Copy addresses to the driver */
        !          2138:          copy_from_user(address, wrq->u.data.pointer,
        !          2139:                         sizeof(struct sockaddr) * lp->spy_number);
        !          2140: 
        !          2141:          /* Copy addresses to the lp structure */
        !          2142:          for(i = 0; i < lp->spy_number; i++)
        !          2143:            {
        !          2144:              memcpy(lp->spy_address[i], address[i].sa_data,
        !          2145:                     WAVELAN_ADDR_SIZE);
        !          2146:            }
        !          2147: 
        !          2148:          /* Reset structure... */
        !          2149:          memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
        !          2150: 
        !          2151: #ifdef DEBUG_IOCTL_INFO
        !          2152:          printk(KERN_DEBUG "SetSpy - Set of new addresses is :\n");
        !          2153:          for(i = 0; i < wrq->u.data.length; i++)
        !          2154:            printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X \n",
        !          2155:                   lp->spy_address[i][0],
        !          2156:                   lp->spy_address[i][1],
        !          2157:                   lp->spy_address[i][2],
        !          2158:                   lp->spy_address[i][3],
        !          2159:                   lp->spy_address[i][4],
        !          2160:                   lp->spy_address[i][5]);
        !          2161: #endif /* DEBUG_IOCTL_INFO */
        !          2162:        }
        !          2163: 
        !          2164:       break;
        !          2165: 
        !          2166:     case SIOCGIWSPY:
        !          2167:       /* Get the spy list and spy stats */
        !          2168: 
        !          2169:       /* Set the number of addresses */
        !          2170:       wrq->u.data.length = lp->spy_number;
        !          2171: 
        !          2172:       /* If the user want to have the addresses back... */
        !          2173:       if((lp->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
        !          2174:        {
        !          2175:          struct sockaddr       address[IW_MAX_SPY];
        !          2176:          int                   i;
        !          2177: 
        !          2178:          /* Verify the user buffer */
        !          2179:          ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
        !          2180:                            (sizeof(iw_qual) + sizeof(struct sockaddr))
        !          2181:                            * IW_MAX_SPY);
        !          2182:          if(ret)
        !          2183:            break;
        !          2184: 
        !          2185:          /* Copy addresses from the lp structure */
        !          2186:          for(i = 0; i < lp->spy_number; i++)
        !          2187:            {
        !          2188:              memcpy(address[i].sa_data, lp->spy_address[i],
        !          2189:                     WAVELAN_ADDR_SIZE);
        !          2190:              address[i].sa_family = AF_UNIX;
        !          2191:            }
        !          2192: 
        !          2193:          /* Copy addresses to the user buffer */
        !          2194:          copy_to_user(wrq->u.data.pointer, address,
        !          2195:                       sizeof(struct sockaddr) * lp->spy_number);
        !          2196: 
        !          2197:          /* Copy stats to the user buffer (just after) */
        !          2198:          copy_to_user(wrq->u.data.pointer +
        !          2199:                       (sizeof(struct sockaddr) * lp->spy_number),
        !          2200:                       lp->spy_stat, sizeof(iw_qual) * lp->spy_number);
        !          2201: 
        !          2202:          /* Reset updated flags */
        !          2203:          for(i = 0; i < lp->spy_number; i++)
        !          2204:            lp->spy_stat[i].updated = 0x0;
        !          2205:        }       /* if(pointer != NULL) */
        !          2206: 
        !          2207:       break;
        !          2208: #endif /* WIRELESS_SPY */
        !          2209: 
        !          2210:       /* ------------------ PRIVATE IOCTL ------------------ */
        !          2211: 
        !          2212:     case SIOCSIPQTHR:
        !          2213:       if(!suser())
        !          2214:        return -EPERM;
        !          2215:       psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
        !          2216:       psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
        !          2217:               (unsigned char *)&psa.psa_quality_thr, 1);
        !          2218:       mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr);
        !          2219:       break;
        !          2220: 
        !          2221:     case SIOCGIPQTHR:
        !          2222:       psa_read(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
        !          2223:               (unsigned char *)&psa.psa_quality_thr, 1);
        !          2224:       *(wrq->u.name) = psa.psa_quality_thr & 0x0F;
        !          2225:       break;
        !          2226: 
        !          2227: #ifdef HISTOGRAM
        !          2228:     case SIOCSIPHISTO:
        !          2229:       /* Verif if the user is root */
        !          2230:       if(!suser())
        !          2231:        return -EPERM;
        !          2232: 
        !          2233:       /* Check the number of intervals */
        !          2234:       if(wrq->u.data.length > 16)
        !          2235:        {
        !          2236:          ret = -E2BIG;
        !          2237:          break;
        !          2238:        }
        !          2239:       lp->his_number = wrq->u.data.length;
        !          2240: 
        !          2241:       /* If there is some addresses to copy */
        !          2242:       if(lp->his_number > 0)
        !          2243:        {
        !          2244:          /* Verify where the user has set his addresses */
        !          2245:          ret = verify_area(VERIFY_READ, wrq->u.data.pointer,
        !          2246:                            sizeof(char) * lp->his_number);
        !          2247:          if(ret)
        !          2248:            break;
        !          2249:          /* Copy interval ranges to the driver */
        !          2250:          copy_from_user(lp->his_range, wrq->u.data.pointer,
        !          2251:                         sizeof(char) * lp->his_number);
        !          2252: 
        !          2253:          /* Reset structure... */
        !          2254:          memset(lp->his_sum, 0x00, sizeof(long) * 16);
        !          2255:        }
        !          2256:       break;
        !          2257: 
        !          2258:     case SIOCGIPHISTO:
        !          2259:       /* Set the number of intervals */
        !          2260:       wrq->u.data.length = lp->his_number;
        !          2261: 
        !          2262:       /* Give back the distribution statistics */
        !          2263:       if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
        !          2264:        {
        !          2265:          /* Verify the user buffer */
        !          2266:          ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
        !          2267:                            sizeof(long) * 16);
        !          2268:          if(ret)
        !          2269:            break;
        !          2270: 
        !          2271:          /* Copy data to the user buffer */
        !          2272:          copy_to_user(wrq->u.data.pointer, lp->his_sum,
        !          2273:                       sizeof(long) * lp->his_number);
        !          2274:        }       /* if(pointer != NULL) */
        !          2275:       break;
        !          2276: #endif /* HISTOGRAM */
        !          2277: 
        !          2278:       /* ------------------- OTHER IOCTL ------------------- */
        !          2279: 
        !          2280:     default:
        !          2281:       ret = -EOPNOTSUPP;
        !          2282:     }
        !          2283: 
        !          2284:   /* Enable interrupts, restore flags */
        !          2285:   wv_splx(x);
        !          2286: 
        !          2287: #ifdef DEBUG_IOCTL_TRACE
        !          2288:   printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
        !          2289: #endif
        !          2290:   return ret;
        !          2291: }
        !          2292: 
        !          2293: /*------------------------------------------------------------------*/
        !          2294: /*
        !          2295:  * Get wireless statistics
        !          2296:  * Called by /proc/net/wireless
        !          2297:  */
        !          2298: static iw_stats *
        !          2299: wavelan_get_wireless_stats(device *    dev)
        !          2300: {
        !          2301:   u_long               ioaddr = dev->base_addr;
        !          2302:   net_local *          lp = (net_local *) dev->priv;
        !          2303:   mmr_t                        m;
        !          2304:   iw_stats *           wstats;
        !          2305:   unsigned long                x;
        !          2306: 
        !          2307: #ifdef DEBUG_IOCTL_TRACE
        !          2308:   printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name);
        !          2309: #endif
        !          2310: 
        !          2311:   /* Disable interrupts & save flags */
        !          2312:   x = wv_splhi();
        !          2313: 
        !          2314:   if(lp == (net_local *) NULL)
        !          2315:     return (iw_stats *) NULL;
        !          2316:   wstats = &lp->wstats;
        !          2317: 
        !          2318:   /* Get data from the mmc */
        !          2319:   mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
        !          2320: 
        !          2321:   mmc_read(ioaddr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1);
        !          2322:   mmc_read(ioaddr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, 2);
        !          2323:   mmc_read(ioaddr, mmroff(0, mmr_thr_pre_set), &m.mmr_thr_pre_set, 4);
        !          2324: 
        !          2325:   mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
        !          2326: 
        !          2327:   /* Copy data to wireless stuff */
        !          2328:   wstats->status = m.mmr_dce_status;
        !          2329:   wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL;
        !          2330:   wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL;
        !          2331:   wstats->qual.noise = m.mmr_silence_lvl & MMR_SILENCE_LVL;
        !          2332:   wstats->qual.updated = (((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 7) |
        !          2333:                          ((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 6) |
        !          2334:                          ((m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) >> 5));
        !          2335:   wstats->discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
        !          2336:   wstats->discard.code = 0L;
        !          2337:   wstats->discard.misc = 0L;
        !          2338: 
        !          2339:   /* Enable interrupts & restore flags */
        !          2340:   wv_splx(x);
        !          2341: 
        !          2342: #ifdef DEBUG_IOCTL_TRACE
        !          2343:   printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name);
        !          2344: #endif
        !          2345:   return &lp->wstats;
        !          2346: }
        !          2347: #endif /* WIRELESS_EXT */
        !          2348: 
        !          2349: /************************* PACKET RECEPTION *************************/
        !          2350: /*
        !          2351:  * This part deals with receiving the packets.
        !          2352:  * The interrupt handler gets an interrupt when a packet has been
        !          2353:  * successfully received and calls this part.
        !          2354:  */
        !          2355: 
        !          2356: /*------------------------------------------------------------------*/
        !          2357: /*
        !          2358:  * This routine does the actual copying of data (including the Ethernet
        !          2359:  * header structure) from the WaveLAN card to an sk_buff chain that
        !          2360:  * will be passed up to the network interface layer. NOTE: we
        !          2361:  * currently don't handle trailer protocols (neither does the rest of
        !          2362:  * the network interface), so if that is needed, it will (at least in
        !          2363:  * part) be added here.  The contents of the receive ring buffer are
        !          2364:  * copied to a message chain that is then passed to the kernel.
        !          2365:  *
        !          2366:  * Note: if any errors occur, the packet is "dropped on the floor"
        !          2367:  * (called by wv_packet_rcv())
        !          2368:  */
        !          2369: static inline void
        !          2370: wv_packet_read(device *                dev,
        !          2371:               u_short          buf_off,
        !          2372:               int              sksize)
        !          2373: {
        !          2374:   net_local *          lp = (net_local *) dev->priv;
        !          2375:   u_long               ioaddr = dev->base_addr;
        !          2376:   struct sk_buff *     skb;
        !          2377: 
        !          2378: #ifdef DEBUG_RX_TRACE
        !          2379:   printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n",
        !          2380:         dev->name, fd_p, sksize);
        !          2381: #endif
        !          2382: 
        !          2383:   /* Allocate buffer for the data */
        !          2384:   if((skb = dev_alloc_skb(sksize)) == (struct sk_buff *) NULL)
        !          2385:     {
        !          2386: #ifdef DEBUG_RX_ERROR
        !          2387:       printk(KERN_INFO "%s: wv_packet_read(): could not alloc_skb(%d, GFP_ATOMIC).\n",
        !          2388:             dev->name, sksize);
        !          2389: #endif
        !          2390:       lp->stats.rx_dropped++;
        !          2391:       return;
        !          2392:     }
        !          2393: 
        !          2394:   skb->dev = dev;
        !          2395: 
        !          2396:   /* Copy the packet to the buffer */
        !          2397:   obram_read(ioaddr, buf_off, skb_put(skb, sksize), sksize);
        !          2398:   skb->protocol=eth_type_trans(skb, dev);
        !          2399: 
        !          2400: #ifdef DEBUG_RX_INFO
        !          2401:   wv_packet_info(skb->mac.raw, sksize, dev->name, "wv_packet_read");
        !          2402: #endif /* DEBUG_RX_INFO */
        !          2403: 
        !          2404:   /* Statistics gathering & stuff associated.
        !          2405:    * It seem a bit messy with all the define, but it's really simple... */
        !          2406: #if defined(WIRELESS_SPY) || defined(HISTOGRAM)
        !          2407:   if(
        !          2408: #ifdef WIRELESS_SPY
        !          2409:      (lp->spy_number > 0) ||
        !          2410: #endif /* WIRELESS_SPY */
        !          2411: #ifdef HISTOGRAM
        !          2412:      (lp->his_number > 0) ||
        !          2413: #endif /* HISTOGRAM */
        !          2414:      0)
        !          2415:     {
        !          2416:       u_char   stats[3];       /* signal level, noise level, signal quality */
        !          2417: 
        !          2418:       /* read signal level, silence level and signal quality bytes */
        !          2419:       /* Note: in the PCMCIA hardware, these are part of the frame. It seems
        !          2420:        * that for the ISA hardware, it's nowhere to be found in the frame,
        !          2421:        * so I'm obliged to do this (it has a side effect on /proc/net/wireless).
        !          2422:        * Any ideas? */
        !          2423:       mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
        !          2424:       mmc_read(ioaddr, mmroff(0, mmr_signal_lvl), stats, 3);
        !          2425:       mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
        !          2426: 
        !          2427: #ifdef DEBUG_RX_INFO
        !          2428:       printk(KERN_DEBUG "%s: wv_packet_read(): Signal level %d/63, Silence level %d/63, signal quality %d/16\n",
        !          2429:             dev->name, stats[0] & 0x3F, stats[1] & 0x3F, stats[2] & 0x0F);
        !          2430: #endif
        !          2431: 
        !          2432:       /* Spying stuff */
        !          2433: #ifdef WIRELESS_SPY
        !          2434:       wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE, stats);
        !          2435: #endif /* WIRELESS_SPY */
        !          2436: #ifdef HISTOGRAM
        !          2437:       wl_his_gather(dev, stats);
        !          2438: #endif /* HISTOGRAM */
        !          2439:     }
        !          2440: #endif /* defined(WIRELESS_SPY) || defined(HISTOGRAM) */
        !          2441: 
        !          2442:   /*
        !          2443:    * Hand the packet to the Network Module
        !          2444:    */
        !          2445:   netif_rx(skb);
        !          2446: 
        !          2447:   lp->stats.rx_packets++;
        !          2448: 
        !          2449: #ifdef DEBUG_RX_TRACE
        !          2450:   printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name);
        !          2451: #endif
        !          2452: }
        !          2453: 
        !          2454: /*------------------------------------------------------------------*/
        !          2455: /*
        !          2456:  * Transfer as many packets as we can
        !          2457:  * from the device RAM.
        !          2458:  * Called by the interrupt handler.
        !          2459:  */
        !          2460: static inline void
        !          2461: wv_receive(device *    dev)
        !          2462: {
        !          2463:   u_long       ioaddr = dev->base_addr;
        !          2464:   net_local *  lp = (net_local *)dev->priv;
        !          2465:   int          nreaped = 0;
        !          2466: 
        !          2467: #ifdef DEBUG_RX_TRACE
        !          2468:   printk(KERN_DEBUG "%s: ->wv_receive()\n", dev->name);
        !          2469: #endif
        !          2470: 
        !          2471:   /* Loop on each received packet */
        !          2472:   for(;;)
        !          2473:     {
        !          2474:       fd_t             fd;
        !          2475:       rbd_t            rbd;
        !          2476:       ushort           pkt_len;
        !          2477: 
        !          2478:       obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd, sizeof(fd));
        !          2479: 
        !          2480:       /* If the current frame is not complete, we have reach the end... */
        !          2481:       if((fd.fd_status & FD_STATUS_C) != FD_STATUS_C)
        !          2482:        break;          /* This is how we exit the loop */
        !          2483: 
        !          2484:       nreaped++;
        !          2485: 
        !          2486:       /* Check if frame correctly received */
        !          2487:       if((fd.fd_status & (FD_STATUS_B | FD_STATUS_OK)) !=
        !          2488:         (FD_STATUS_B | FD_STATUS_OK))
        !          2489:        {
        !          2490:          /*
        !          2491:           * Not sure about this one -- it does not seem
        !          2492:           * to be an error so we will keep quiet about it.
        !          2493:           */
        !          2494: #ifndef IGNORE_NORMAL_XMIT_ERRS
        !          2495: #ifdef DEBUG_RX_ERROR
        !          2496:          if((fd.fd_status & FD_STATUS_B) != FD_STATUS_B)
        !          2497:            printk(KERN_INFO "%s: wv_receive(): frame not consumed by RU.\n",
        !          2498:                   dev->name);
        !          2499: #endif
        !          2500: #endif /* IGNORE_NORMAL_XMIT_ERRS */
        !          2501: 
        !          2502: #ifdef DEBUG_RX_ERROR
        !          2503:          if((fd.fd_status & FD_STATUS_OK) != FD_STATUS_OK)
        !          2504:            printk(KERN_INFO "%s: wv_receive(): frame not received successfully.\n",
        !          2505:                   dev->name);
        !          2506: #endif
        !          2507:        }
        !          2508: 
        !          2509:       /* Were there problems in processing the frame?  Let's check. */
        !          2510:       if((fd.fd_status & (FD_STATUS_S6 | FD_STATUS_S7 | FD_STATUS_S8 |
        !          2511:                          FD_STATUS_S9 | FD_STATUS_S10 | FD_STATUS_S11))
        !          2512:         != 0)
        !          2513:        {
        !          2514:          lp->stats.rx_errors++;
        !          2515: 
        !          2516: #ifdef DEBUG_RX_ERROR
        !          2517:          if((fd.fd_status & FD_STATUS_S6) != 0)
        !          2518:            printk(KERN_INFO "%s: wv_receive(): no EOF flag.\n", dev->name);
        !          2519: #endif
        !          2520: 
        !          2521:          if((fd.fd_status & FD_STATUS_S7) != 0)
        !          2522:            {
        !          2523:              lp->stats.rx_length_errors++;
        !          2524: #ifdef DEBUG_RX_ERROR
        !          2525:              printk(KERN_INFO "%s: wv_receive(): frame too short.\n",
        !          2526:                     dev->name);
        !          2527: #endif
        !          2528:            }
        !          2529: 
        !          2530:          if((fd.fd_status & FD_STATUS_S8) != 0)
        !          2531:            {
        !          2532:              lp->stats.rx_over_errors++;
        !          2533: #ifdef DEBUG_RX_ERROR
        !          2534:              printk(KERN_INFO "%s: wv_receive(): rx DMA overrun.\n",
        !          2535:                     dev->name);
        !          2536: #endif
        !          2537:            }
        !          2538: 
        !          2539:          if((fd.fd_status & FD_STATUS_S9) != 0)
        !          2540:            {
        !          2541:              lp->stats.rx_fifo_errors++;
        !          2542: #ifdef DEBUG_RX_ERROR
        !          2543:              printk(KERN_INFO "%s: wv_receive(): ran out of resources.\n",
        !          2544:                     dev->name);
        !          2545: #endif
        !          2546:            }
        !          2547: 
        !          2548:          if((fd.fd_status & FD_STATUS_S10) != 0)
        !          2549:            {
        !          2550:              lp->stats.rx_frame_errors++;
        !          2551: #ifdef DEBUG_RX_ERROR
        !          2552:              printk(KERN_INFO "%s: wv_receive(): alignment error.\n",
        !          2553:                     dev->name);
        !          2554: #endif
        !          2555:            }
        !          2556: 
        !          2557:          if((fd.fd_status & FD_STATUS_S11) != 0)
        !          2558:            {
        !          2559:              lp->stats.rx_crc_errors++;
        !          2560: #ifdef DEBUG_RX_ERROR
        !          2561:              printk(KERN_INFO "%s: wv_receive(): CRC error.\n", dev->name);
        !          2562: #endif
        !          2563:            }
        !          2564:        }
        !          2565: 
        !          2566:       /* Does the frame contain a pointer to the data?  Let's check. */
        !          2567:       if(fd.fd_rbd_offset == I82586NULL)
        !          2568: #ifdef DEBUG_RX_ERROR
        !          2569:        printk(KERN_INFO "%s: wv_receive(): frame has no data.\n", dev->name);
        !          2570: #endif
        !          2571:       else
        !          2572:        {
        !          2573:          obram_read(ioaddr, fd.fd_rbd_offset,
        !          2574:                     (unsigned char *) &rbd, sizeof(rbd));
        !          2575: 
        !          2576: #ifdef DEBUG_RX_ERROR
        !          2577:          if((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF)
        !          2578:            printk(KERN_INFO "%s: wv_receive(): missing EOF flag.\n",
        !          2579:                   dev->name);
        !          2580: 
        !          2581:          if((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F)
        !          2582:            printk(KERN_INFO "%s: wv_receive(): missing F flag.\n",
        !          2583:                   dev->name);
        !          2584: #endif
        !          2585: 
        !          2586:          pkt_len = rbd.rbd_status & RBD_STATUS_ACNT;
        !          2587: 
        !          2588:          /* Read the packet and transmit to Linux */
        !          2589:          wv_packet_read(dev, rbd.rbd_bufl, pkt_len);
        !          2590:        }       /* if frame has data */
        !          2591: 
        !          2592:       fd.fd_status = 0;
        !          2593:       obram_write(ioaddr, fdoff(lp->rx_head, fd_status),
        !          2594:                  (unsigned char *) &fd.fd_status, sizeof(fd.fd_status));
        !          2595: 
        !          2596:       fd.fd_command = FD_COMMAND_EL;
        !          2597:       obram_write(ioaddr, fdoff(lp->rx_head, fd_command),
        !          2598:                  (unsigned char *) &fd.fd_command, sizeof(fd.fd_command));
        !          2599: 
        !          2600:       fd.fd_command = 0;
        !          2601:       obram_write(ioaddr, fdoff(lp->rx_last, fd_command),
        !          2602:                  (unsigned char *) &fd.fd_command, sizeof(fd.fd_command));
        !          2603: 
        !          2604:       lp->rx_last = lp->rx_head;
        !          2605:       lp->rx_head = fd.fd_link_offset;
        !          2606:     }  /* for(;;) -> loop on all frames */
        !          2607: 
        !          2608: #ifdef DEBUG_RX_INFO
        !          2609:   if(nreaped > 1)
        !          2610:     printk(KERN_DEBUG "%s: wv_receive(): reaped %d\n", dev->name, nreaped);
        !          2611: #endif
        !          2612: #ifdef DEBUG_RX_TRACE
        !          2613:   printk(KERN_DEBUG "%s: <-wv_receive()\n", dev->name);
        !          2614: #endif
        !          2615: }
        !          2616: 
        !          2617: /*********************** PACKET TRANSMISSION ***********************/
        !          2618: /*
        !          2619:  * This part deals with sending packet through the WaveLAN
        !          2620:  *
        !          2621:  */
        !          2622: 
        !          2623: /*------------------------------------------------------------------*/
        !          2624: /*
        !          2625:  * This routine fills in the appropriate registers and memory
        !          2626:  * locations on the WaveLAN card and starts the card off on
        !          2627:  * the transmit.
        !          2628:  *
        !          2629:  * The principle :
        !          2630:  * Each block contain a transmit command, a nop command,
        !          2631:  * a transmit block descriptor and a buffer.
        !          2632:  * The CU read the transmit block which point to the tbd,
        !          2633:  * read the tbd and the content of the buffer.
        !          2634:  * When it has finished with it, it goes to the next command
        !          2635:  * which in our case is the nop. The nop point on itself,
        !          2636:  * so the CU stop here.
        !          2637:  * When we add the next block, we modify the previous nop
        !          2638:  * to make it point on the new tx command.
        !          2639:  * Simple, isn't it ?
        !          2640:  *
        !          2641:  * (called in wavelan_packet_xmit())
        !          2642:  */
        !          2643: static inline void
        !          2644: wv_packet_write(device *       dev,
        !          2645:                void *  buf,
        !          2646:                short   length)
        !          2647: {
        !          2648:   net_local *          lp = (net_local *) dev->priv;
        !          2649:   u_long               ioaddr = dev->base_addr;
        !          2650:   unsigned short       txblock;
        !          2651:   unsigned short       txpred;
        !          2652:   unsigned short       tx_addr;
        !          2653:   unsigned short       nop_addr;
        !          2654:   unsigned short       tbd_addr;
        !          2655:   unsigned short       buf_addr;
        !          2656:   ac_tx_t              tx;
        !          2657:   ac_nop_t             nop;
        !          2658:   tbd_t                        tbd;
        !          2659:   int                  clen = length;
        !          2660:   unsigned long                x;
        !          2661: 
        !          2662: #ifdef DEBUG_TX_TRACE
        !          2663:   printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length);
        !          2664: #endif
        !          2665: 
        !          2666:   /* Check if we need some padding */
        !          2667:   if(clen < ETH_ZLEN)
        !          2668:     clen = ETH_ZLEN;
        !          2669: 
        !          2670:   x = wv_splhi();
        !          2671: 
        !          2672:   /* Calculate addresses of next block and previous block */
        !          2673:   txblock = lp->tx_first_free;
        !          2674:   txpred = txblock - TXBLOCKZ;
        !          2675:   if(txpred < OFFSET_CU)
        !          2676:     txpred += NTXBLOCKS * TXBLOCKZ;
        !          2677:   lp->tx_first_free += TXBLOCKZ;
        !          2678:   if(lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
        !          2679:     lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ;
        !          2680: 
        !          2681: /*
        !          2682: if (lp->tx_n_in_use > 0)
        !          2683:        printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]);
        !          2684: */
        !          2685: 
        !          2686:   lp->tx_n_in_use++;
        !          2687: 
        !          2688:   /* Calculate addresses of the differents part of the block */
        !          2689:   tx_addr = txblock;
        !          2690:   nop_addr = tx_addr + sizeof(tx);
        !          2691:   tbd_addr = nop_addr + sizeof(nop);
        !          2692:   buf_addr = tbd_addr + sizeof(tbd);
        !          2693: 
        !          2694:   /*
        !          2695:    * Transmit command.
        !          2696:    */
        !          2697:   tx.tx_h.ac_status = 0;
        !          2698:   obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status),
        !          2699:              (unsigned char *) &tx.tx_h.ac_status,
        !          2700:              sizeof(tx.tx_h.ac_status));
        !          2701: 
        !          2702:   /*
        !          2703:    * NOP command.
        !          2704:    */
        !          2705:   nop.nop_h.ac_status = 0;
        !          2706:   obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
        !          2707:              (unsigned char *) &nop.nop_h.ac_status,
        !          2708:              sizeof(nop.nop_h.ac_status));
        !          2709:   nop.nop_h.ac_link = nop_addr;
        !          2710:   obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
        !          2711:              (unsigned char *) &nop.nop_h.ac_link,
        !          2712:              sizeof(nop.nop_h.ac_link));
        !          2713: 
        !          2714:   /*
        !          2715:    * Transmit buffer descriptor
        !          2716:    */
        !          2717:   tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & clen);
        !          2718:   tbd.tbd_next_bd_offset = I82586NULL;
        !          2719:   tbd.tbd_bufl = buf_addr;
        !          2720:   tbd.tbd_bufh = 0;
        !          2721:   obram_write(ioaddr, tbd_addr, (unsigned char *)&tbd, sizeof(tbd));
        !          2722: 
        !          2723:   /*
        !          2724:    * Data
        !          2725:    */
        !          2726:   obram_write(ioaddr, buf_addr, buf, clen);
        !          2727: 
        !          2728:   /*
        !          2729:    * Overwrite the predecessor NOP link
        !          2730:    * so that it points to this txblock.
        !          2731:    */
        !          2732:   nop_addr = txpred + sizeof(tx);
        !          2733:   nop.nop_h.ac_status = 0;
        !          2734:   obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
        !          2735:              (unsigned char *)&nop.nop_h.ac_status,
        !          2736:              sizeof(nop.nop_h.ac_status));
        !          2737:   nop.nop_h.ac_link = txblock;
        !          2738:   obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
        !          2739:              (unsigned char *) &nop.nop_h.ac_link,
        !          2740:              sizeof(nop.nop_h.ac_link));
        !          2741: 
        !          2742:   /* If watchdog not already active, activate it... */
        !          2743:   if(lp->watchdog.prev == (timer_list *) NULL)
        !          2744:     {
        !          2745:       /* set timer to expire in WATCHDOG_JIFFIES */
        !          2746:       lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
        !          2747:       add_timer(&lp->watchdog);
        !          2748:     }
        !          2749: 
        !          2750:   if(lp->tx_first_in_use == I82586NULL)
        !          2751:     lp->tx_first_in_use = txblock;
        !          2752: 
        !          2753:   if(lp->tx_n_in_use < NTXBLOCKS - 1)
        !          2754:     dev->tbusy = 0;
        !          2755: 
        !          2756:   wv_splx(x);
        !          2757: 
        !          2758: #ifdef DEBUG_TX_INFO
        !          2759:   wv_packet_info((u_char *) buf, length, dev->name, "wv_packet_write");
        !          2760: #endif /* DEBUG_TX_INFO */
        !          2761: 
        !          2762: #ifdef DEBUG_TX_TRACE
        !          2763:   printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name);
        !          2764: #endif
        !          2765: }
        !          2766: 
        !          2767: /*------------------------------------------------------------------*/
        !          2768: /*
        !          2769:  * This routine is called when we want to send a packet (NET3 callback)
        !          2770:  * In this routine, we check if the hardware is ready to accept
        !          2771:  * the packet. We also prevent reentrance. Then, we call the function
        !          2772:  * to send the packet...
        !          2773:  */
        !          2774: static int
        !          2775: wavelan_packet_xmit(struct sk_buff *   skb,
        !          2776:                    device *            dev)
        !          2777: {
        !          2778:   net_local *  lp = (net_local *)dev->priv;
        !          2779: 
        !          2780: #ifdef DEBUG_TX_TRACE
        !          2781:   printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
        !          2782:         (unsigned) skb);
        !          2783: #endif
        !          2784: 
        !          2785:   /* This flag indicate that the hardware can't perform a transmission.
        !          2786:    * Theoretically, NET3 checks it before sending a packet to the driver,
        !          2787:    * but in fact it never does that and pool continuously.
        !          2788:    * As the watchdog will abort overly long transmissions, we are quite safe.
        !          2789:    */
        !          2790:   if(dev->tbusy)
        !          2791:     return 1;
        !          2792: 
        !          2793:   /*
        !          2794:    * If some higher layer thinks we've missed
        !          2795:    * a tx-done interrupt we are passed NULL.
        !          2796:    * Caution: dev_tint() handles the cli()/sti() itself.
        !          2797:    */
        !          2798:   if(skb == (struct sk_buff *)0)
        !          2799:     {
        !          2800: #ifdef DEBUG_TX_ERROR
        !          2801:       printk(KERN_INFO "%s: wavelan_packet_xmit(): skb == NULL\n", dev->name);
        !          2802: #endif
        !          2803:       dev_tint(dev);
        !          2804:       return 0;
        !          2805:     }
        !          2806: 
        !          2807:   /*
        !          2808:    * Block a timer-based transmit from overlapping.
        !          2809:    * In other words, prevent reentering this routine.
        !          2810:    */
        !          2811:   if(set_bit(0, (void *)&dev->tbusy) != 0)
        !          2812: #ifdef DEBUG_TX_ERROR
        !          2813:     printk(KERN_INFO "%s: Transmitter access conflict.\n", dev->name);
        !          2814: #endif
        !          2815:   else
        !          2816:     {
        !          2817:       /* If somebody has asked to reconfigure the controller, 
        !          2818:        * we can do it now.
        !          2819:        */
        !          2820:       if(lp->reconfig_82586)
        !          2821:        {
        !          2822:          wv_82586_config(dev);
        !          2823:          if(dev->tbusy)
        !          2824:            return 1;
        !          2825:        }
        !          2826: 
        !          2827: #ifdef DEBUG_TX_ERROR
        !          2828:       if(skb->next)
        !          2829:        printk(KERN_INFO "skb has next\n");
        !          2830: #endif
        !          2831: 
        !          2832:       wv_packet_write(dev, skb->data, skb->len);
        !          2833:     }
        !          2834: 
        !          2835:   dev_kfree_skb(skb, FREE_WRITE);
        !          2836: 
        !          2837: #ifdef DEBUG_TX_TRACE
        !          2838:   printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
        !          2839: #endif
        !          2840:   return 0;
        !          2841: }
        !          2842: 
        !          2843: /*********************** HARDWARE CONFIGURATION ***********************/
        !          2844: /*
        !          2845:  * This part does the real job of starting and configuring the hardware.
        !          2846:  */
        !          2847: 
        !          2848: /*--------------------------------------------------------------------*/
        !          2849: /*
        !          2850:  * Routine to initialize the Modem Management Controller.
        !          2851:  * (called by wv_hw_reset())
        !          2852:  */
        !          2853: static inline int
        !          2854: wv_mmc_init(device *   dev)
        !          2855: {
        !          2856:   u_long       ioaddr = dev->base_addr;
        !          2857:   net_local *  lp = (net_local *)dev->priv;
        !          2858:   psa_t                psa;
        !          2859:   mmw_t                m;
        !          2860:   int          configured;
        !          2861: 
        !          2862: #ifdef DEBUG_CONFIG_TRACE
        !          2863:   printk(KERN_DEBUG "%s: ->wv_mmc_init()\n", dev->name);
        !          2864: #endif
        !          2865: 
        !          2866:   /* Read the parameter storage area */
        !          2867:   psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
        !          2868: 
        !          2869: #ifdef USE_PSA_CONFIG
        !          2870:   configured = psa.psa_conf_status & 1;
        !          2871: #else
        !          2872:   configured = 0;
        !          2873: #endif
        !          2874: 
        !          2875:   /* Is the PSA is not configured */
        !          2876:   if(!configured)
        !          2877:     {
        !          2878:       /* User will be able to configure NWID after (with iwconfig) */
        !          2879:       psa.psa_nwid[0] = 0;
        !          2880:       psa.psa_nwid[1] = 0;
        !          2881: 
        !          2882:       /* no NWID checking since NWID is not set */
        !          2883:       psa.psa_nwid_select = 0;
        !          2884: 
        !          2885:       /* Disable encryption */
        !          2886:       psa.psa_encryption_select = 0;
        !          2887: 
        !          2888:       /* Set to standard values
        !          2889:        * 0x04 for AT,
        !          2890:        * 0x01 for MCA,
        !          2891:        * 0x04 for PCMCIA and 2.00 card (AT&T 407-024689/E document)
        !          2892:        */
        !          2893:       if (psa.psa_comp_number & 1)
        !          2894:        psa.psa_thr_pre_set = 0x01;
        !          2895:       else
        !          2896:        psa.psa_thr_pre_set = 0x04;
        !          2897:       psa.psa_quality_thr = 0x03;
        !          2898: 
        !          2899:       /* It is configured */
        !          2900:       psa.psa_conf_status |= 1;
        !          2901: 
        !          2902: #ifdef USE_PSA_CONFIG
        !          2903:       /* Write the psa */
        !          2904:       psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
        !          2905:                (unsigned char *)psa.psa_nwid, 4);
        !          2906:       psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
        !          2907:                (unsigned char *)&psa.psa_thr_pre_set, 1);
        !          2908:       psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
        !          2909:                (unsigned char *)&psa.psa_quality_thr, 1);
        !          2910:       psa_write(ioaddr, lp->hacr, (char *)&psa.psa_conf_status - (char *)&psa,
        !          2911:                (unsigned char *)&psa.psa_conf_status, 1);
        !          2912: #endif
        !          2913:     }
        !          2914: 
        !          2915:   /* Zero the mmc structure */
        !          2916:   memset(&m, 0x00, sizeof(m));
        !          2917: 
        !          2918:   /* Copy PSA info to the mmc */
        !          2919:   m.mmw_netw_id_l = psa.psa_nwid[1];
        !          2920:   m.mmw_netw_id_h = psa.psa_nwid[0];
        !          2921:   
        !          2922:   if(psa.psa_nwid_select & 1)
        !          2923:     m.mmw_loopt_sel = 0x00;
        !          2924:   else
        !          2925:     m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID;
        !          2926: 
        !          2927:   memcpy(&m.mmw_encr_key, &psa.psa_encryption_key, 
        !          2928:         sizeof(m.mmw_encr_key));
        !          2929: 
        !          2930:   if(psa.psa_encryption_select)
        !          2931:     m.mmw_encr_enable = MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE;
        !          2932:   else
        !          2933:     m.mmw_encr_enable = 0;
        !          2934: 
        !          2935:   m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F;
        !          2936:   m.mmw_quality_thr = psa.psa_quality_thr & 0x0F;
        !          2937: 
        !          2938:   /* Missing: encryption stuff... */
        !          2939: 
        !          2940:   /*
        !          2941:    * Set default modem control parameters.
        !          2942:    * See NCR document 407-0024326 Rev. A.
        !          2943:    */
        !          2944:   m.mmw_jabber_enable = 0x01;
        !          2945:   m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN;
        !          2946:   m.mmw_ifs = 0x20;
        !          2947:   m.mmw_mod_delay = 0x04;
        !          2948:   m.mmw_jam_time = 0x38;
        !          2949: 
        !          2950:   m.mmw_encr_enable = 0;
        !          2951:   m.mmw_des_io_invert = 0;
        !          2952:   m.mmw_freeze = 0;
        !          2953:   m.mmw_decay_prm = 0;
        !          2954:   m.mmw_decay_updat_prm = 0;
        !          2955: 
        !          2956:   /* Write all info to MMC */
        !          2957:   mmc_write(ioaddr, 0, (u_char *)&m, sizeof(m));
        !          2958: 
        !          2959:   /* The following code starts the modem of the 2.00 frequency
        !          2960:    * selectable cards at power on. It's not strictly needed for the
        !          2961:    * following boots.
        !          2962:    * The original patch was by Joe Finney for the PCMCIA driver, but
        !          2963:    * I've cleaned it up a bit and added documentation.
        !          2964:    * Thanks to Loeke Brederveld from Lucent for the info.
        !          2965:    */
        !          2966: 
        !          2967:   /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
        !          2968:    * (does it work for everybody? -- especially old cards?) */
        !          2969:   /* Note: WFREQSEL verifies that it is able to read a sensible
        !          2970:    * frequency from EEPROM (address 0x00) and that MMR_FEE_STATUS_ID
        !          2971:    * is 0xA (Xilinx version) or 0xB (Ariadne version).
        !          2972:    * My test is more crude but does work. */
        !          2973:   if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
        !          2974:        (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
        !          2975:     {
        !          2976:       /* We must download the frequency parameters to the
        !          2977:        * synthesizers (from the EEPROM - area 1)
        !          2978:        * Note : as the EEPROM is auto decremented, we set the end
        !          2979:        * if the area... */
        !          2980:       m.mmw_fee_addr = 0x0F;
        !          2981:       m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD;
        !          2982:       mmc_write(ioaddr, (char *)&m.mmw_fee_ctrl - (char *)&m,
        !          2983:                (unsigned char *)&m.mmw_fee_ctrl, 2);
        !          2984: 
        !          2985:       /* Wait until the download is finished */
        !          2986:       fee_wait(ioaddr, 100, 100);
        !          2987: 
        !          2988: #ifdef DEBUG_CONFIG_INFO
        !          2989:       /* The frequency was in the last word downloaded. */
        !          2990:       mmc_read(ioaddr, (char *)&m.mmw_fee_data_l - (char *)&m,
        !          2991:               (unsigned char *)&m.mmw_fee_data_l, 2);
        !          2992: 
        !          2993:       /* Print some info for the user. */
        !          2994:       printk(KERN_DEBUG "%s: WaveLAN 2.00 recognised (frequency select) : Current frequency = %ld\n",
        !          2995:             dev->name,
        !          2996:             ((m.mmw_fee_data_h << 4) |
        !          2997:              (m.mmw_fee_data_l >> 4)) * 5 / 2 + 24000L);
        !          2998: #endif
        !          2999: 
        !          3000:       /* We must now download the power adjust value (gain) to
        !          3001:        * the synthesizers (from the EEPROM - area 7 - DAC) */
        !          3002:       m.mmw_fee_addr = 0x61;
        !          3003:       m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD;
        !          3004:       mmc_write(ioaddr, (char *)&m.mmw_fee_ctrl - (char *)&m,
        !          3005:                (unsigned char *)&m.mmw_fee_ctrl, 2);
        !          3006: 
        !          3007:       /* Wait until the download is finished */
        !          3008:     }  /* if 2.00 card */
        !          3009: 
        !          3010: #ifdef DEBUG_CONFIG_TRACE
        !          3011:   printk(KERN_DEBUG "%s: <-wv_mmc_init()\n", dev->name);
        !          3012: #endif
        !          3013:   return 0;
        !          3014: }
        !          3015: 
        !          3016: /*------------------------------------------------------------------*/
        !          3017: /*
        !          3018:  * Construct the fd and rbd structures.
        !          3019:  * Start the receive unit.
        !          3020:  * (called by wv_hw_reset())
        !          3021:  */
        !          3022: static inline int
        !          3023: wv_ru_start(device *   dev)
        !          3024: {
        !          3025:   net_local *  lp = (net_local *) dev->priv;
        !          3026:   u_long       ioaddr = dev->base_addr;
        !          3027:   u_short      scb_cs;
        !          3028:   fd_t         fd;
        !          3029:   rbd_t                rbd;
        !          3030:   u_short      rx;
        !          3031:   u_short      rx_next;
        !          3032:   int          i;
        !          3033: 
        !          3034: #ifdef DEBUG_CONFIG_TRACE
        !          3035:   printk(KERN_DEBUG "%s: ->wv_ru_start()\n", dev->name);
        !          3036: #endif
        !          3037: 
        !          3038:   obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&scb_cs, sizeof(scb_cs));
        !          3039:   if((scb_cs & SCB_ST_RUS) == SCB_ST_RUS_RDY)
        !          3040:     return 0;
        !          3041: 
        !          3042:   lp->rx_head = OFFSET_RU;
        !          3043: 
        !          3044:   for(i = 0, rx = lp->rx_head; i < NRXBLOCKS; i++, rx = rx_next)
        !          3045:     {
        !          3046:       rx_next = (i == NRXBLOCKS - 1) ? lp->rx_head : rx + RXBLOCKZ;
        !          3047: 
        !          3048:       fd.fd_status = 0;
        !          3049:       fd.fd_command = (i == NRXBLOCKS - 1) ? FD_COMMAND_EL : 0;
        !          3050:       fd.fd_link_offset = rx_next;
        !          3051:       fd.fd_rbd_offset = rx + sizeof(fd);
        !          3052:       obram_write(ioaddr, rx, (unsigned char *)&fd, sizeof(fd));
        !          3053: 
        !          3054:       rbd.rbd_status = 0;
        !          3055:       rbd.rbd_next_rbd_offset = I82586NULL;
        !          3056:       rbd.rbd_bufl = rx + sizeof(fd) + sizeof(rbd);
        !          3057:       rbd.rbd_bufh = 0;
        !          3058:       rbd.rbd_el_size = RBD_EL | (RBD_SIZE & MAXDATAZ);
        !          3059:       obram_write(ioaddr, rx + sizeof(fd),
        !          3060:                  (unsigned char *) &rbd, sizeof(rbd));
        !          3061: 
        !          3062:       lp->rx_last = rx;
        !          3063:     }
        !          3064: 
        !          3065:   obram_write(ioaddr, scboff(OFFSET_SCB, scb_rfa_offset),
        !          3066:              (unsigned char *) &lp->rx_head, sizeof(lp->rx_head));
        !          3067: 
        !          3068:   scb_cs = SCB_CMD_RUC_GO;
        !          3069:   obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
        !          3070:              (unsigned char *) &scb_cs, sizeof(scb_cs));
        !          3071: 
        !          3072:   set_chan_attn(ioaddr, lp->hacr);
        !          3073: 
        !          3074:   for(i = 1000; i > 0; i--)
        !          3075:     {
        !          3076:       obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
        !          3077:                 (unsigned char *) &scb_cs, sizeof(scb_cs));
        !          3078:       if (scb_cs == 0)
        !          3079:        break;
        !          3080: 
        !          3081:       udelay(10);
        !          3082:     }
        !          3083: 
        !          3084:   if(i <= 0)
        !          3085:     {
        !          3086: #ifdef DEBUG_CONFIG_ERRORS
        !          3087:       printk(KERN_INFO "%s: wavelan_ru_start(): board not accepting command.\n",
        !          3088:             dev->name);
        !          3089: #endif
        !          3090:       return -1;
        !          3091:     }
        !          3092: 
        !          3093: #ifdef DEBUG_CONFIG_TRACE
        !          3094:   printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name);
        !          3095: #endif
        !          3096:   return 0;
        !          3097: }
        !          3098: 
        !          3099: /*------------------------------------------------------------------*/
        !          3100: /*
        !          3101:  * Initialise the transmit blocks.
        !          3102:  * Start the command unit executing the NOP
        !          3103:  * self-loop of the first transmit block.
        !          3104:  *
        !          3105:  * Here, we create the list of send buffers used to transmit packets
        !          3106:  * between the PC and the command unit. For each buffer, we create a
        !          3107:  * buffer descriptor (pointing on the buffer), a transmit command
        !          3108:  * (pointing to the buffer descriptor) and a NOP command.
        !          3109:  * The transmit command is linked to the NOP, and the NOP to itself.
        !          3110:  * When we will have finished executing the transmit command, we will
        !          3111:  * then loop on the NOP. By releasing the NOP link to a new command,
        !          3112:  * we may send another buffer.
        !          3113:  *
        !          3114:  * (called by wv_hw_reset())
        !          3115:  */
        !          3116: static inline int
        !          3117: wv_cu_start(device *   dev)
        !          3118: {
        !          3119:   net_local *  lp = (net_local *) dev->priv;
        !          3120:   u_long       ioaddr = dev->base_addr;
        !          3121:   int          i;
        !          3122:   u_short      txblock;
        !          3123:   u_short      first_nop;
        !          3124:   u_short      scb_cs;
        !          3125: 
        !          3126: #ifdef DEBUG_CONFIG_TRACE
        !          3127:   printk(KERN_DEBUG "%s: ->wv_cu_start()\n", dev->name);
        !          3128: #endif
        !          3129: 
        !          3130:   lp->tx_first_free = OFFSET_CU;
        !          3131:   lp->tx_first_in_use = I82586NULL;
        !          3132: 
        !          3133:   for(i = 0, txblock = OFFSET_CU;
        !          3134:       i < NTXBLOCKS;
        !          3135:       i++, txblock += TXBLOCKZ)
        !          3136:     {
        !          3137:       ac_tx_t          tx;
        !          3138:       ac_nop_t         nop;
        !          3139:       tbd_t            tbd;
        !          3140:       unsigned short   tx_addr;
        !          3141:       unsigned short   nop_addr;
        !          3142:       unsigned short   tbd_addr;
        !          3143:       unsigned short   buf_addr;
        !          3144: 
        !          3145:       tx_addr = txblock;
        !          3146:       nop_addr = tx_addr + sizeof(tx);
        !          3147:       tbd_addr = nop_addr + sizeof(nop);
        !          3148:       buf_addr = tbd_addr + sizeof(tbd);
        !          3149: 
        !          3150:       tx.tx_h.ac_status = 0;
        !          3151:       tx.tx_h.ac_command = acmd_transmit | AC_CFLD_I;
        !          3152:       tx.tx_h.ac_link = nop_addr;
        !          3153:       tx.tx_tbd_offset = tbd_addr;
        !          3154:       obram_write(ioaddr, tx_addr, (unsigned char *) &tx, sizeof(tx));
        !          3155: 
        !          3156:       nop.nop_h.ac_status = 0;
        !          3157:       nop.nop_h.ac_command = acmd_nop;
        !          3158:       nop.nop_h.ac_link = nop_addr;
        !          3159:       obram_write(ioaddr, nop_addr, (unsigned char *) &nop, sizeof(nop));
        !          3160: 
        !          3161:       tbd.tbd_status = TBD_STATUS_EOF;
        !          3162:       tbd.tbd_next_bd_offset = I82586NULL;
        !          3163:       tbd.tbd_bufl = buf_addr;
        !          3164:       tbd.tbd_bufh = 0;
        !          3165:       obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd, sizeof(tbd));
        !          3166:     }
        !          3167: 
        !          3168:   first_nop = OFFSET_CU + (NTXBLOCKS - 1) * TXBLOCKZ + sizeof(ac_tx_t);
        !          3169:   obram_write(ioaddr, scboff(OFFSET_SCB, scb_cbl_offset),
        !          3170:              (unsigned char *) &first_nop, sizeof(first_nop));
        !          3171: 
        !          3172:   scb_cs = SCB_CMD_CUC_GO;
        !          3173:   obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
        !          3174:              (unsigned char *) &scb_cs, sizeof(scb_cs));
        !          3175: 
        !          3176:   set_chan_attn(ioaddr, lp->hacr);
        !          3177: 
        !          3178:   for(i = 1000; i > 0; i--)
        !          3179:     {
        !          3180:       obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
        !          3181:                 (unsigned char *) &scb_cs, sizeof(scb_cs));
        !          3182:       if (scb_cs == 0)
        !          3183:        break;
        !          3184: 
        !          3185:       udelay(10);
        !          3186:     }
        !          3187: 
        !          3188:   if(i <= 0)
        !          3189:     {
        !          3190: #ifdef DEBUG_CONFIG_ERRORS
        !          3191:       printk(KERN_INFO "%s: wavelan_cu_start(): board not accepting command.\n",
        !          3192:             dev->name);
        !          3193: #endif
        !          3194:       return -1;
        !          3195:     }
        !          3196: 
        !          3197:   lp->tx_n_in_use = 0;
        !          3198:   dev->tbusy = 0;
        !          3199: 
        !          3200: #ifdef DEBUG_CONFIG_TRACE
        !          3201:   printk(KERN_DEBUG "%s: <-wv_cu_start()\n", dev->name);
        !          3202: #endif
        !          3203:   return 0;
        !          3204: }
        !          3205: 
        !          3206: /*------------------------------------------------------------------*/
        !          3207: /*
        !          3208:  * This routine does a standard config of the WaveLAN controler (i82586).
        !          3209:  *
        !          3210:  * It initialises the scp, iscp and scb structure
        !          3211:  * The first two are just pointers to the next.
        !          3212:  * The last one is used for basic configuration and for basic
        !          3213:  * communication (interrupt status).
        !          3214:  *
        !          3215:  * (called by wv_hw_reset())
        !          3216:  */
        !          3217: static inline int
        !          3218: wv_82586_start(device *        dev)
        !          3219: {
        !          3220:   net_local *  lp = (net_local *) dev->priv;
        !          3221:   u_long       ioaddr = dev->base_addr;
        !          3222:   scp_t                scp;            /* system configuration pointer */
        !          3223:   iscp_t       iscp;           /* intermediate scp */
        !          3224:   scb_t                scb;            /* system control block */
        !          3225:   ach_t                cb;             /* Action command header */
        !          3226:   u_char       zeroes[512];
        !          3227:   int          i;
        !          3228: 
        !          3229: #ifdef DEBUG_CONFIG_TRACE
        !          3230:   printk(KERN_DEBUG "%s: ->wv_82586_start()\n", dev->name);
        !          3231: #endif
        !          3232: 
        !          3233:   /*
        !          3234:    * Clear the onboard RAM.
        !          3235:    */
        !          3236:   memset(&zeroes[0], 0x00, sizeof(zeroes));
        !          3237:   for(i = 0; i < I82586_MEMZ; i += sizeof(zeroes))
        !          3238:     obram_write(ioaddr, i, &zeroes[0], sizeof(zeroes));
        !          3239: 
        !          3240:   /*
        !          3241:    * Construct the command unit structures:
        !          3242:    * scp, iscp, scb, cb.
        !          3243:    */
        !          3244:   memset(&scp, 0x00, sizeof(scp));
        !          3245:   scp.scp_sysbus = SCP_SY_16BBUS;
        !          3246:   scp.scp_iscpl = OFFSET_ISCP;
        !          3247:   obram_write(ioaddr, OFFSET_SCP, (unsigned char *)&scp, sizeof(scp));
        !          3248: 
        !          3249:   memset(&iscp, 0x00, sizeof(iscp));
        !          3250:   iscp.iscp_busy = 1;
        !          3251:   iscp.iscp_offset = OFFSET_SCB;
        !          3252:   obram_write(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp));
        !          3253: 
        !          3254:   /* Our first command is to reset the i82586. */
        !          3255:   memset(&scb, 0x00, sizeof(scb));
        !          3256:   scb.scb_command = SCB_CMD_RESET;
        !          3257:   scb.scb_cbl_offset = OFFSET_CU;
        !          3258:   scb.scb_rfa_offset = OFFSET_RU;
        !          3259:   obram_write(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb));
        !          3260: 
        !          3261:   set_chan_attn(ioaddr, lp->hacr);
        !          3262: 
        !          3263:   /* Wait for command to finish. */
        !          3264:   for(i = 1000; i > 0; i--)
        !          3265:     {
        !          3266:       obram_read(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp, sizeof(iscp));
        !          3267: 
        !          3268:       if(iscp.iscp_busy == (unsigned short) 0)
        !          3269:        break;
        !          3270: 
        !          3271:       udelay(10);
        !          3272:     }
        !          3273: 
        !          3274:   if(i <= 0)
        !          3275:     {
        !          3276: #ifdef DEBUG_CONFIG_ERRORS
        !          3277:       printk(KERN_INFO "%s: wv_82586_start(): iscp_busy timeout.\n",
        !          3278:             dev->name);
        !          3279: #endif
        !          3280:       return -1;
        !          3281:     }
        !          3282: 
        !          3283:   /* Check command completion */
        !          3284:   for(i = 15; i > 0; i--)
        !          3285:     {
        !          3286:       obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb, sizeof(scb));
        !          3287: 
        !          3288:       if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA))
        !          3289:        break;
        !          3290: 
        !          3291:       udelay(10);
        !          3292:     }
        !          3293: 
        !          3294:   if (i <= 0)
        !          3295:     {
        !          3296: #ifdef DEBUG_CONFIG_ERRORS
        !          3297:       printk(KERN_INFO "%s: wv_82586_start(): status: expected 0x%02x, got 0x%02x.\n",
        !          3298:             dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status);
        !          3299: #endif
        !          3300:       return -1;
        !          3301:     }
        !          3302: 
        !          3303:   wv_ack(dev);
        !          3304: 
        !          3305:   /* Set the action command header. */
        !          3306:   memset(&cb, 0x00, sizeof(cb));
        !          3307:   cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose);
        !          3308:   cb.ac_link = OFFSET_CU;
        !          3309:   obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
        !          3310: 
        !          3311:   if(wv_synchronous_cmd(dev, "diag()") == -1)
        !          3312:     return -1;
        !          3313: 
        !          3314:   obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
        !          3315:   if(cb.ac_status & AC_SFLD_FAIL)
        !          3316:     {
        !          3317: #ifdef DEBUG_CONFIG_ERRORS
        !          3318:       printk(KERN_INFO "%s: wv_82586_start(): i82586 Self Test failed.\n",
        !          3319:             dev->name);
        !          3320: #endif
        !          3321:       return -1;
        !          3322:     }
        !          3323: 
        !          3324: #ifdef DEBUG_I82586_SHOW
        !          3325:   wv_scb_show(ioaddr);
        !          3326: #endif
        !          3327: 
        !          3328: #ifdef DEBUG_CONFIG_TRACE
        !          3329:   printk(KERN_DEBUG "%s: <-wv_82586_start()\n", dev->name);
        !          3330: #endif
        !          3331:   return 0;
        !          3332: }
        !          3333: 
        !          3334: /*------------------------------------------------------------------*/
        !          3335: /*
        !          3336:  * This routine does a standard configuration of the WaveLAN controller
        !          3337:  * (i82586).
        !          3338:  *
        !          3339:  * This routine is a violent hack. We use the first free transmit block
        !          3340:  * to make our configuration. In the buffer area, we create the three
        !          3341:  * configuration commands (linked). We make the previous NOP point to
        !          3342:  * the beginning of the buffer instead of the tx command. After, we go
        !          3343:  * as usual to the NOP command.
        !          3344:  * Note that only the last command (mc_set) will generate an interrupt.
        !          3345:  *
        !          3346:  * (called by wv_hw_reset(), wv_82586_reconfig())
        !          3347:  */
        !          3348: static void
        !          3349: wv_82586_config(device *       dev)
        !          3350: {
        !          3351:   net_local *          lp = (net_local *) dev->priv;
        !          3352:   u_long               ioaddr = dev->base_addr;
        !          3353:   unsigned short       txblock;
        !          3354:   unsigned short       txpred;
        !          3355:   unsigned short       tx_addr;
        !          3356:   unsigned short       nop_addr;
        !          3357:   unsigned short       tbd_addr;
        !          3358:   unsigned short       cfg_addr;
        !          3359:   unsigned short       ias_addr;
        !          3360:   unsigned short       mcs_addr;
        !          3361:   ac_tx_t              tx;
        !          3362:   ac_nop_t             nop;
        !          3363:   ac_cfg_t             cfg;            /* Configure action */
        !          3364:   ac_ias_t             ias;            /* IA-setup action */
        !          3365:   ac_mcs_t             mcs;            /* Multicast setup */
        !          3366:   struct dev_mc_list * dmi;
        !          3367:   unsigned long                x;
        !          3368: 
        !          3369: #ifdef DEBUG_CONFIG_TRACE
        !          3370:   printk(KERN_DEBUG "%s: ->wv_82586_config()\n", dev->name);
        !          3371: #endif
        !          3372: 
        !          3373:   x = wv_splhi();
        !          3374: 
        !          3375:   /* Calculate addresses of next block and previous block */
        !          3376:   txblock = lp->tx_first_free;
        !          3377:   txpred = txblock - TXBLOCKZ;
        !          3378:   if(txpred < OFFSET_CU)
        !          3379:     txpred += NTXBLOCKS * TXBLOCKZ;
        !          3380:   lp->tx_first_free += TXBLOCKZ;
        !          3381:   if(lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
        !          3382:     lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ;
        !          3383: 
        !          3384:   lp->tx_n_in_use++;
        !          3385: 
        !          3386:   /* Calculate addresses of the different parts of the block. */
        !          3387:   tx_addr = txblock;
        !          3388:   nop_addr = tx_addr + sizeof(tx);
        !          3389:   tbd_addr = nop_addr + sizeof(nop);
        !          3390:   cfg_addr = tbd_addr + sizeof(tbd_t); /* beginning of the buffer */
        !          3391:   ias_addr = cfg_addr + sizeof(cfg);
        !          3392:   mcs_addr = ias_addr + sizeof(ias);
        !          3393: 
        !          3394:   /*
        !          3395:    * Transmit command
        !          3396:    */
        !          3397:   tx.tx_h.ac_status = 0xFFFF;  /* Fake completion value */
        !          3398:   obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status),
        !          3399:              (unsigned char *) &tx.tx_h.ac_status,
        !          3400:              sizeof(tx.tx_h.ac_status));
        !          3401: 
        !          3402:   /*
        !          3403:    * NOP command
        !          3404:    */
        !          3405:   nop.nop_h.ac_status = 0;
        !          3406:   obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
        !          3407:              (unsigned char *) &nop.nop_h.ac_status,
        !          3408:              sizeof(nop.nop_h.ac_status));
        !          3409:   nop.nop_h.ac_link = nop_addr;
        !          3410:   obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
        !          3411:              (unsigned char *) &nop.nop_h.ac_link,
        !          3412:              sizeof(nop.nop_h.ac_link));
        !          3413: 
        !          3414:   /* Create a configure action */
        !          3415:   memset(&cfg, 0x00, sizeof(cfg));
        !          3416: 
        !          3417: #if    0
        !          3418:   /*
        !          3419:    * The default board configuration
        !          3420:    */
        !          3421:   cfg.fifolim_bytecnt  = 0x080c;
        !          3422:   cfg.addrlen_mode     = 0x2600;
        !          3423:   cfg.linprio_interframe       = 0x7820;       /* IFS=120, ACS=2 */
        !          3424:   cfg.slot_time        = 0xf00c;       /* slottime=12    */
        !          3425:   cfg.hardware         = 0x0008;       /* tx even without CD */
        !          3426:   cfg.min_frame_len    = 0x0040;
        !          3427: #endif /* 0 */
        !          3428: 
        !          3429:   /*
        !          3430:    * For Linux we invert AC_CFG_ALOC(..) so as to conform
        !          3431:    * to the way that net packets reach us from above.
        !          3432:    * (See also ac_tx_t.)
        !          3433:    */
        !          3434:   cfg.cfg_byte_cnt = AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t));
        !          3435:   cfg.cfg_fifolim = AC_CFG_FIFOLIM(8);
        !          3436:   cfg.cfg_byte8 = AC_CFG_SAV_BF(0) |
        !          3437:                  AC_CFG_SRDY(0);
        !          3438:   cfg.cfg_byte9 = AC_CFG_ELPBCK(0) |
        !          3439:                  AC_CFG_ILPBCK(0) |
        !          3440:                  AC_CFG_PRELEN(AC_CFG_PLEN_2) |
        !          3441:                  AC_CFG_ALOC(1) |
        !          3442:                  AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE);
        !          3443:   cfg.cfg_byte10 = AC_CFG_BOFMET(0) |
        !          3444:                   AC_CFG_ACR(0) |
        !          3445:                   AC_CFG_LINPRIO(0);
        !          3446:   cfg.cfg_ifs = 32;
        !          3447:   cfg.cfg_slotl = 0;
        !          3448:   cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) |
        !          3449:                   AC_CFG_SLTTMHI(2);
        !          3450:   cfg.cfg_byte14 = AC_CFG_FLGPAD(0) |
        !          3451:                   AC_CFG_BTSTF(0) |
        !          3452:                   AC_CFG_CRC16(0) |
        !          3453:                   AC_CFG_NCRC(0) |
        !          3454:                   AC_CFG_TNCRS(1) |
        !          3455:                   AC_CFG_MANCH(0) |
        !          3456:                   AC_CFG_BCDIS(0) |
        !          3457:                   AC_CFG_PRM(lp->promiscuous);
        !          3458:   cfg.cfg_byte15 = AC_CFG_ICDS(0) |
        !          3459:                   AC_CFG_CDTF(0) |
        !          3460:                   AC_CFG_ICSS(0) |
        !          3461:                   AC_CFG_CSTF(0);
        !          3462: /*
        !          3463:   cfg.cfg_min_frm_len = AC_CFG_MNFRM(64);
        !          3464: */
        !          3465:   cfg.cfg_min_frm_len = AC_CFG_MNFRM(8);
        !          3466: 
        !          3467:   cfg.cfg_h.ac_command = (AC_CFLD_CMD & acmd_configure);
        !          3468:   cfg.cfg_h.ac_link = ias_addr;
        !          3469:   obram_write(ioaddr, cfg_addr, (unsigned char *)&cfg, sizeof(cfg));
        !          3470: 
        !          3471:   /* Setup the MAC address */
        !          3472:   memset(&ias, 0x00, sizeof(ias));
        !          3473:   ias.ias_h.ac_command = (AC_CFLD_CMD & acmd_ia_setup);
        !          3474:   ias.ias_h.ac_link = mcs_addr;
        !          3475:   memcpy(&ias.ias_addr[0], (unsigned char *)&dev->dev_addr[0], sizeof(ias.ias_addr));
        !          3476:   obram_write(ioaddr, ias_addr, (unsigned char *)&ias, sizeof(ias));
        !          3477: 
        !          3478:   /* Initialize adapter's ethernet multicast addresses */
        !          3479:   memset(&mcs, 0x00, sizeof(mcs));
        !          3480:   mcs.mcs_h.ac_command = AC_CFLD_I | (AC_CFLD_CMD & acmd_mc_setup);
        !          3481:   mcs.mcs_h.ac_link = nop_addr;
        !          3482:   mcs.mcs_cnt = WAVELAN_ADDR_SIZE * lp->mc_count;
        !          3483:   obram_write(ioaddr, mcs_addr, (unsigned char *)&mcs, sizeof(mcs));
        !          3484: 
        !          3485:   /* If any address to set */
        !          3486:   if(lp->mc_count)
        !          3487:     {
        !          3488:       for(dmi=dev->mc_list; dmi; dmi=dmi->next)
        !          3489:        outsw(PIOP1(ioaddr), (u_short *) dmi->dmi_addr,
        !          3490:              WAVELAN_ADDR_SIZE >> 1);
        !          3491: 
        !          3492: #ifdef DEBUG_CONFIG_INFO
        !          3493:       printk(KERN_DEBUG "%s: wv_82586_config(): set %d multicast addresses:\n",
        !          3494:             dev->name, lp->mc_count);
        !          3495:       for(dmi=dev->mc_list; dmi; dmi=dmi->next)
        !          3496:        printk(KERN_DEBUG " %02x:%02x:%02x:%02x:%02x:%02x\n",
        !          3497:               dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
        !          3498:               dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5] );
        !          3499: #endif
        !          3500:     }
        !          3501: 
        !          3502:   /*
        !          3503:    * Overwrite the predecessor NOP link
        !          3504:    * so that it points to the configure action.
        !          3505:    */
        !          3506:   nop_addr = txpred + sizeof(tx);
        !          3507:   nop.nop_h.ac_status = 0;
        !          3508:   obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
        !          3509:              (unsigned char *)&nop.nop_h.ac_status,
        !          3510:              sizeof(nop.nop_h.ac_status));
        !          3511:   nop.nop_h.ac_link = cfg_addr;
        !          3512:   obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
        !          3513:              (unsigned char *) &nop.nop_h.ac_link,
        !          3514:              sizeof(nop.nop_h.ac_link));
        !          3515: 
        !          3516:   /* If watchdog not already active, activate it... */
        !          3517:   if(lp->watchdog.prev == (timer_list *) NULL)
        !          3518:     {
        !          3519:       /* set timer to expire in WATCHDOG_JIFFIES */
        !          3520:       lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
        !          3521:       add_timer(&lp->watchdog);
        !          3522:     }
        !          3523: 
        !          3524:   lp->reconfig_82586 = 0;
        !          3525: 
        !          3526:   if(lp->tx_first_in_use == I82586NULL)
        !          3527:     lp->tx_first_in_use = txblock;
        !          3528: 
        !          3529:   if(lp->tx_n_in_use < NTXBLOCKS - 1)
        !          3530:     dev->tbusy = 0;
        !          3531: 
        !          3532:   wv_splx(x);
        !          3533: 
        !          3534: #ifdef DEBUG_CONFIG_TRACE
        !          3535:   printk(KERN_DEBUG "%s: <-wv_82586_config()\n", dev->name);
        !          3536: #endif
        !          3537: }
        !          3538: 
        !          3539: /*------------------------------------------------------------------*/
        !          3540: /*
        !          3541:  * This routine, called by wavelan_close(), gracefully stops the 
        !          3542:  * WaveLAN controller (i82586).
        !          3543:  */
        !          3544: static inline void
        !          3545: wv_82586_stop(device * dev)
        !          3546: {
        !          3547:   net_local *  lp = (net_local *) dev->priv;
        !          3548:   u_long       ioaddr = dev->base_addr;
        !          3549:   u_short      scb_cmd;
        !          3550: 
        !          3551: #ifdef DEBUG_CONFIG_TRACE
        !          3552:   printk(KERN_DEBUG "%s: ->wv_82586_stop()\n", dev->name);
        !          3553: #endif
        !          3554: 
        !          3555:   /* Suspend both command unit and receive unit. */
        !          3556:   scb_cmd = (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC & SCB_CMD_RUC_SUS);
        !          3557:   obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
        !          3558:              (unsigned char *)&scb_cmd, sizeof(scb_cmd));
        !          3559:   set_chan_attn(ioaddr, lp->hacr);
        !          3560: 
        !          3561:   /* No more interrupts */
        !          3562:   wv_ints_off(dev);
        !          3563: 
        !          3564: #ifdef DEBUG_CONFIG_TRACE
        !          3565:   printk(KERN_DEBUG "%s: <-wv_82586_stop()\n", dev->name);
        !          3566: #endif
        !          3567: }
        !          3568: 
        !          3569: /*------------------------------------------------------------------*/
        !          3570: /*
        !          3571:  * Totally reset the WaveLAN and restart it.
        !          3572:  * Performs the following actions:
        !          3573:  *     1. A power reset (reset DMA)
        !          3574:  *     2. Initialize the radio modem (using wv_mmc_init)
        !          3575:  *     3. Reset & Configure LAN controller (using wv_82586_start)
        !          3576:  *     4. Start the LAN controller's command unit
        !          3577:  *     5. Start the LAN controller's receive unit
        !          3578:  */
        !          3579: static int
        !          3580: wv_hw_reset(device *   dev)
        !          3581: {
        !          3582:   net_local *  lp = (net_local *)dev->priv;
        !          3583:   u_long       ioaddr = dev->base_addr;
        !          3584: 
        !          3585: #ifdef DEBUG_CONFIG_TRACE
        !          3586:   printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name,
        !          3587:         (unsigned int)dev);
        !          3588: #endif
        !          3589: 
        !          3590:   /* If watchdog was activated, kill it! */
        !          3591:   if(lp->watchdog.prev != (timer_list *) NULL)
        !          3592:     del_timer(&lp->watchdog);
        !          3593: 
        !          3594:   /* Increase the number of resets done */
        !          3595:   lp->nresets++;
        !          3596: 
        !          3597:   wv_hacr_reset(ioaddr);
        !          3598:   lp->hacr = HACR_DEFAULT;
        !          3599: 
        !          3600:   if((wv_mmc_init(dev) < 0) ||
        !          3601:      (wv_82586_start(dev) < 0))
        !          3602:     return -1;
        !          3603: 
        !          3604:   /* Enable the card to send interrupts */
        !          3605:   wv_ints_on(dev);
        !          3606: 
        !          3607:   /* Start card functions */
        !          3608:   if((wv_ru_start(dev) < 0) ||
        !          3609:      (wv_cu_start(dev) < 0))
        !          3610:     return -1;
        !          3611: 
        !          3612:   /* Finish configuration */
        !          3613:   wv_82586_config(dev);
        !          3614: 
        !          3615: #ifdef DEBUG_CONFIG_TRACE
        !          3616:   printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name);
        !          3617: #endif
        !          3618:   return 0;
        !          3619: }
        !          3620: 
        !          3621: /*------------------------------------------------------------------*/
        !          3622: /*
        !          3623:  * Check if there is a WaveLAN at the specific base address.
        !          3624:  * As a side effect, this reads the MAC address.
        !          3625:  * (called in wavelan_probe() and init_module())
        !          3626:  */
        !          3627: static int
        !          3628: wv_check_ioaddr(u_long         ioaddr,
        !          3629:                u_char *        mac)
        !          3630: {
        !          3631:   int          i;              /* Loop counter */
        !          3632: 
        !          3633:   /* Check if the base address if available */
        !          3634:   if(check_region(ioaddr, sizeof(ha_t)))
        !          3635:     return  EADDRINUSE;                /* ioaddr already used... */
        !          3636: 
        !          3637:   /* Reset host interface */
        !          3638:   wv_hacr_reset(ioaddr);
        !          3639: 
        !          3640:   /* Read the MAC address from the parameter storage area */
        !          3641:   psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_univ_mac_addr),
        !          3642:           mac, 6);
        !          3643: 
        !          3644:   /*
        !          3645:    * Check the first three octets of the address for the manufacturer's code.
        !          3646:    * Note: If this can't find your WaveLAN card, you've got a
        !          3647:    * non-NCR/AT&T/Lucent ISA card.  See wavelan.p.h for details on
        !          3648:    * how to configure your card.
        !          3649:    */
        !          3650:   for(i = 0; i < (sizeof(MAC_ADDRESSES) / sizeof(char) / 3); i++)
        !          3651:     if((mac[0] == MAC_ADDRESSES[i][0]) &&
        !          3652:        (mac[1] == MAC_ADDRESSES[i][1]) &&
        !          3653:        (mac[2] == MAC_ADDRESSES[i][2]))
        !          3654:       return 0;
        !          3655: 
        !          3656: #ifdef DEBUG_CONFIG_INFO
        !          3657:   printk(KERN_WARNING "WaveLAN (0x%3X): your MAC address might be: %02X:%02X:%02X.\n",
        !          3658:         ioaddr, mac[0], mac[1], mac[2]);
        !          3659: #endif
        !          3660:     return ENODEV;
        !          3661: }
        !          3662: 
        !          3663: /************************ INTERRUPT HANDLING ************************/
        !          3664: 
        !          3665: /*
        !          3666:  * This function is the interrupt handler for the WaveLAN card. This
        !          3667:  * routine will be called whenever: 
        !          3668:  */
        !          3669: static void
        !          3670: wavelan_interrupt(int                  irq,
        !          3671:                  void *                dev_id,
        !          3672:                  struct pt_regs *      regs)
        !          3673: {
        !          3674:   device *     dev;
        !          3675:   u_long       ioaddr;
        !          3676:   net_local *  lp;
        !          3677:   u_short      hasr;
        !          3678:   u_short      status;
        !          3679:   u_short      ack_cmd;
        !          3680: 
        !          3681:   if((dev = (device *) (irq2dev_map[irq])) == (device *) NULL)
        !          3682:     {
        !          3683: #ifdef DEBUG_INTERRUPT_ERROR
        !          3684:       printk(KERN_WARNING "wavelan_interrupt(): irq %d for unknown device.\n",
        !          3685:             irq);
        !          3686: #endif
        !          3687:       return;
        !          3688:     }
        !          3689: 
        !          3690: #ifdef DEBUG_INTERRUPT_TRACE
        !          3691:   printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name);
        !          3692: #endif
        !          3693: 
        !          3694:   lp = (net_local *) dev->priv;
        !          3695:   ioaddr = dev->base_addr;
        !          3696: 
        !          3697:   /* Prevent reentrance. What should we do here? */
        !          3698: #ifdef DEBUG_INTERRUPT_ERROR
        !          3699:   if(dev->interrupt)
        !          3700:     printk(KERN_INFO "%s: wavelan_interrupt(): Re-entering the interrupt handler.\n",
        !          3701:           dev->name);
        !          3702: #endif
        !          3703:   dev->interrupt = 1;
        !          3704: 
        !          3705:   if((hasr = hasr_read(ioaddr)) & HASR_MMC_INTR)
        !          3706:     {
        !          3707:       u_char   dce_status;
        !          3708: 
        !          3709:       /*
        !          3710:        * Interrupt from the modem management controller.
        !          3711:        * This will clear it -- ignored for now.
        !          3712:        */
        !          3713:       mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, sizeof(dce_status));
        !          3714: #ifdef DEBUG_INTERRUPT_ERROR
        !          3715:       printk(KERN_INFO "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n",
        !          3716:             dev->name, dce_status);
        !          3717: #endif
        !          3718:     }
        !          3719: 
        !          3720:   if((hasr & HASR_82586_INTR) == 0)
        !          3721:     {
        !          3722:       dev->interrupt = 0;
        !          3723: #ifdef DEBUG_INTERRUPT_ERROR
        !          3724:       printk(KERN_INFO "%s: wavelan_interrupt(): interrupt not coming from i82586\n",
        !          3725:             dev->name);
        !          3726: #endif
        !          3727:       return;
        !          3728:     }
        !          3729: 
        !          3730:   /* Read interrupt data. */
        !          3731:   obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
        !          3732:             (unsigned char *) &status, sizeof(status));
        !          3733: 
        !          3734:   /*
        !          3735:    * Acknowledge the interrupt(s).
        !          3736:    */
        !          3737:   ack_cmd = status & SCB_ST_INT;
        !          3738:   obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
        !          3739:              (unsigned char *) &ack_cmd, sizeof(ack_cmd));
        !          3740:   set_chan_attn(ioaddr, lp->hacr);
        !          3741: 
        !          3742: #ifdef DEBUG_INTERRUPT_INFO
        !          3743:   printk(KERN_DEBUG "%s: wavelan_interrupt(): status 0x%04x.\n",
        !          3744:         dev->name, status);
        !          3745: #endif
        !          3746: 
        !          3747:   /* Command completed. */
        !          3748:   if((status & SCB_ST_CX) == SCB_ST_CX)
        !          3749:     {
        !          3750: #ifdef DEBUG_INTERRUPT_INFO
        !          3751:       printk(KERN_DEBUG "%s: wavelan_interrupt(): command completed.\n",
        !          3752:             dev->name);
        !          3753: #endif
        !          3754:       wv_complete(dev, ioaddr, lp);
        !          3755: 
        !          3756:       /* If watchdog was activated, kill it ! */
        !          3757:       if(lp->watchdog.prev != (timer_list *) NULL)
        !          3758:        del_timer(&lp->watchdog);
        !          3759:       if(lp->tx_n_in_use > 0)
        !          3760:        {
        !          3761:          /* set timer to expire in WATCHDOG_JIFFIES */
        !          3762:          lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
        !          3763:          add_timer(&lp->watchdog);
        !          3764:        }
        !          3765:     }
        !          3766: 
        !          3767:   /* Frame received. */
        !          3768:   if((status & SCB_ST_FR) == SCB_ST_FR)
        !          3769:     {
        !          3770: #ifdef DEBUG_INTERRUPT_INFO
        !          3771:       printk(KERN_DEBUG "%s: wavelan_interrupt(): received packet.\n",
        !          3772:             dev->name);
        !          3773: #endif
        !          3774:       wv_receive(dev);
        !          3775:     }
        !          3776: 
        !          3777:   /* Check the state of the command unit. */
        !          3778:   if(((status & SCB_ST_CNA) == SCB_ST_CNA) ||
        !          3779:      (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && dev->start))
        !          3780:     {
        !          3781: #ifdef DEBUG_INTERRUPT_ERROR
        !          3782:       printk(KERN_INFO "%s: wavelan_interrupt(): CU inactive -- restarting\n",
        !          3783:             dev->name);
        !          3784: #endif
        !          3785:       wv_hw_reset(dev);
        !          3786:     }
        !          3787: 
        !          3788:   /* Check the state of the command unit. */
        !          3789:   if(((status & SCB_ST_RNR) == SCB_ST_RNR) ||
        !          3790:      (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && dev->start))
        !          3791:     {
        !          3792: #ifdef DEBUG_INTERRUPT_ERROR
        !          3793:       printk(KERN_INFO "%s: wavelan_interrupt(): RU not ready -- restarting\n",
        !          3794:             dev->name);
        !          3795: #endif
        !          3796:       wv_hw_reset(dev);
        !          3797:     }
        !          3798: 
        !          3799:   dev->interrupt = 0;
        !          3800: 
        !          3801: #ifdef DEBUG_INTERRUPT_TRACE
        !          3802:   printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name);
        !          3803: #endif
        !          3804: }
        !          3805: 
        !          3806: /*------------------------------------------------------------------*/
        !          3807: /*
        !          3808:  * Watchdog: when we start a transmission, we set a timer in the
        !          3809:  * kernel.  If the transmission completes, this timer is disabled. If
        !          3810:  * the timer expires, we try to unlock the hardware.
        !          3811:  *
        !          3812:  * Note: this watchdog doesn't work on the same principle as the
        !          3813:  * watchdog in the previous version of the ISA driver. I made it this
        !          3814:  * way because the overhead of add_timer() and del_timer() is nothing
        !          3815:  * and because it avoids calling the watchdog, saving some CPU time.
        !          3816:  */
        !          3817: static void
        !          3818: wavelan_watchdog(u_long                a)
        !          3819: {
        !          3820:   device *             dev;
        !          3821:   net_local *          lp;
        !          3822:   u_long               ioaddr;
        !          3823:   unsigned long                x;
        !          3824:   unsigned int         nreaped;
        !          3825: 
        !          3826:   dev = (device *) a;
        !          3827:   ioaddr = dev->base_addr;
        !          3828:   lp = (net_local *) dev->priv;
        !          3829: 
        !          3830: #ifdef DEBUG_INTERRUPT_TRACE
        !          3831:   printk(KERN_DEBUG "%s: ->wavelan_watchdog()\n", dev->name);
        !          3832: #endif
        !          3833: 
        !          3834: #ifdef DEBUG_INTERRUPT_ERROR
        !          3835:   printk(KERN_INFO "%s: wavelan_watchdog: watchdog timer expired\n",
        !          3836:         dev->name);
        !          3837: #endif
        !          3838: 
        !          3839:   x = wv_splhi();
        !          3840: 
        !          3841:   dev = (device *) a;
        !          3842:   ioaddr = dev->base_addr;
        !          3843:   lp = (net_local *) dev->priv;
        !          3844: 
        !          3845:   if(lp->tx_n_in_use <= 0)
        !          3846:     {
        !          3847:       wv_splx(x);
        !          3848:       return;
        !          3849:     }
        !          3850: 
        !          3851:   nreaped = wv_complete(dev, ioaddr, lp);
        !          3852: 
        !          3853: #ifdef DEBUG_INTERRUPT_INFO
        !          3854:   printk(KERN_DEBUG "%s: wavelan_watchdog(): %d reaped, %d remain.\n",
        !          3855:         dev->name, nreaped, lp->tx_n_in_use);
        !          3856: #endif
        !          3857: 
        !          3858: #ifdef DEBUG_PSA_SHOW
        !          3859:   {
        !          3860:     psa_t              psa;
        !          3861:     psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa));
        !          3862:     wv_psa_show(&psa);
        !          3863:   }
        !          3864: #endif
        !          3865: #ifdef DEBUG_MMC_SHOW
        !          3866:   wv_mmc_show(dev);
        !          3867: #endif
        !          3868: #ifdef DEBUG_I82586_SHOW
        !          3869:   wv_cu_show(dev);
        !          3870: #endif
        !          3871: 
        !          3872:   /* If no buffer has been freed */
        !          3873:   if(nreaped == 0)
        !          3874:     {
        !          3875: #ifdef DEBUG_INTERRUPT_ERROR
        !          3876:       printk(KERN_INFO "%s: wavelan_watchdog(): cleanup failed, trying reset\n",
        !          3877:             dev->name);
        !          3878: #endif
        !          3879:       wv_hw_reset(dev);
        !          3880:     }
        !          3881:   else
        !          3882:     /* Reset watchdog for next transmission. */
        !          3883:     if(lp->tx_n_in_use > 0)
        !          3884:       {
        !          3885:        /* set timer to expire in WATCHDOG_JIFFIES */
        !          3886:        lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
        !          3887:        add_timer(&lp->watchdog);
        !          3888:       }
        !          3889: 
        !          3890:   wv_splx(x);
        !          3891: 
        !          3892: #ifdef DEBUG_INTERRUPT_TRACE
        !          3893:   printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name);
        !          3894: #endif
        !          3895: }
        !          3896: 
        !          3897: /********************* CONFIGURATION CALLBACKS *********************/
        !          3898: /*
        !          3899:  * Here are the functions called by the Linux networking code (NET3)
        !          3900:  * for initialization, configuration and deinstallations of the 
        !          3901:  * WaveLAN ISA hardware.
        !          3902:  */
        !          3903: 
        !          3904: /*------------------------------------------------------------------*/
        !          3905: /*
        !          3906:  * Configure and start up the WaveLAN PCMCIA adaptor.
        !          3907:  * Called by NET3 when it "open" the device.
        !          3908:  */
        !          3909: static int
        !          3910: wavelan_open(device *  dev)
        !          3911: {
        !          3912:   u_long       x;
        !          3913: 
        !          3914: #ifdef DEBUG_CALLBACK_TRACE
        !          3915:   printk(KERN_DEBUG "%s: ->wavelan_open(dev=0x%x)\n", dev->name,
        !          3916:         (unsigned int) dev);
        !          3917: #endif
        !          3918: 
        !          3919:   /* Check irq */
        !          3920:   if(dev->irq == 0)
        !          3921:     {
        !          3922: #ifdef DEBUG_CONFIG_ERRORS
        !          3923:       printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n", dev->name);
        !          3924: #endif
        !          3925:       return -ENXIO;
        !          3926:     }
        !          3927: 
        !          3928:   if((irq2dev_map[dev->irq] != (device *) NULL) ||
        !          3929:      /* This is always true, but avoid the false IRQ. */
        !          3930:      ((irq2dev_map[dev->irq] = dev) == (device *) NULL) ||
        !          3931:      (request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", NULL) != 0))
        !          3932:     {
        !          3933:       irq2dev_map[dev->irq] = (device *) NULL;
        !          3934: #ifdef DEBUG_CONFIG_ERRORS
        !          3935:       printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n", dev->name);
        !          3936: #endif
        !          3937:       return -EAGAIN;
        !          3938:     }
        !          3939: 
        !          3940:   x = wv_splhi();
        !          3941:   if(wv_hw_reset(dev) != -1)
        !          3942:     {
        !          3943:       dev->interrupt = 0;
        !          3944:       dev->start = 1;
        !          3945:     }
        !          3946:   else
        !          3947:     {
        !          3948:       free_irq(dev->irq, NULL);
        !          3949:       irq2dev_map[dev->irq] = (device *) NULL;
        !          3950: #ifdef DEBUG_CONFIG_ERRORS
        !          3951:       printk(KERN_INFO "%s: wavelan_open(): impossible to start the card\n",
        !          3952:             dev->name);
        !          3953: #endif
        !          3954:       return -EAGAIN;
        !          3955:     }
        !          3956:   wv_splx(x);
        !          3957: 
        !          3958:   MOD_INC_USE_COUNT;
        !          3959: 
        !          3960: #ifdef DEBUG_CALLBACK_TRACE
        !          3961:   printk(KERN_DEBUG "%s: <-wavelan_open()\n", dev->name);
        !          3962: #endif
        !          3963:   return 0;
        !          3964: }
        !          3965: 
        !          3966: /*------------------------------------------------------------------*/
        !          3967: /*
        !          3968:  * Shut down the WaveLAN ISA card.
        !          3969:  * Called by NET3 when it "closes" the device.
        !          3970:  */
        !          3971: static int
        !          3972: wavelan_close(device * dev)
        !          3973: {
        !          3974:   net_local *  lp = (net_local *)dev->priv;
        !          3975: 
        !          3976: #ifdef DEBUG_CALLBACK_TRACE
        !          3977:   printk(KERN_DEBUG "%s: ->wavelan_close(dev=0x%x)\n", dev->name,
        !          3978:         (unsigned int) dev);
        !          3979: #endif
        !          3980: 
        !          3981:   /* Not do the job twice. */
        !          3982:   if(dev->start == 0)
        !          3983:     return 0;
        !          3984: 
        !          3985:   dev->tbusy = 1;
        !          3986:   dev->start = 0;
        !          3987: 
        !          3988:   /* If watchdog was activated, kill it! */
        !          3989:   if(lp->watchdog.prev != (timer_list *) NULL)
        !          3990:     del_timer(&lp->watchdog);
        !          3991: 
        !          3992:   /*
        !          3993:    * Flush the Tx and disable Rx.
        !          3994:    */
        !          3995:   wv_82586_stop(dev);
        !          3996: 
        !          3997:   free_irq(dev->irq, NULL);
        !          3998:   irq2dev_map[dev->irq] = (device *) NULL;
        !          3999: 
        !          4000:   MOD_DEC_USE_COUNT;
        !          4001: 
        !          4002: #ifdef DEBUG_CALLBACK_TRACE
        !          4003:   printk(KERN_DEBUG "%s: <-wavelan_close()\n", dev->name);
        !          4004: #endif
        !          4005:   return 0;
        !          4006: }
        !          4007: 
        !          4008: /*------------------------------------------------------------------*/
        !          4009: /*
        !          4010:  * Probe an I/O address, and if the WaveLAN is there configure the
        !          4011:  * device structure
        !          4012:  * (called by wavelan_probe() & via init_module())
        !          4013:  */
        !          4014: static int
        !          4015: wavelan_config(device *        dev)
        !          4016: {
        !          4017:   u_long       ioaddr = dev->base_addr;
        !          4018:   u_char       irq_mask;
        !          4019:   int          irq;
        !          4020:   net_local *  lp;
        !          4021: 
        !          4022: #ifdef DEBUG_CALLBACK_TRACE
        !          4023:   printk(KERN_DEBUG "%s: ->wavelan_config(dev=0x%x, ioaddr=0x%x)\n", dev->name,
        !          4024:         (unsigned int)dev, ioaddr);
        !          4025: #endif
        !          4026: 
        !          4027:   /* Check irq arg on command line */
        !          4028:   if(dev->irq != 0)
        !          4029:     {
        !          4030:       irq_mask = wv_irq_to_psa(dev->irq);
        !          4031: 
        !          4032:       if(irq_mask == 0)
        !          4033:        {
        !          4034: #ifdef DEBUG_CONFIG_ERROR
        !          4035:          printk(KERN_WARNING "%s: wavelan_config(): invalid irq %d -- ignored.\n",
        !          4036:                 dev->name, dev->irq);
        !          4037: #endif
        !          4038:          dev->irq = 0;
        !          4039:        }
        !          4040:       else
        !          4041:        {
        !          4042: #ifdef DEBUG_CONFIG_INFO
        !          4043:          printk(KERN_DEBUG "%s: wavelan_config(): changing irq to %d\n",
        !          4044:                 dev->name, dev->irq);
        !          4045: #endif
        !          4046:          psa_write(ioaddr, HACR_DEFAULT,
        !          4047:                    psaoff(0, psa_int_req_no), &irq_mask, 1);
        !          4048:          wv_hacr_reset(ioaddr);
        !          4049:        }
        !          4050:     }
        !          4051: 
        !          4052:   psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_int_req_no), &irq_mask, 1);
        !          4053:   if((irq = wv_psa_to_irq(irq_mask)) == -1)
        !          4054:     {
        !          4055: #ifdef DEBUG_CONFIG_ERROR
        !          4056:       printk(KERN_INFO "%s: wavelan_config(): could not wavelan_map_irq(%d).\n",
        !          4057:             dev->name, irq_mask);
        !          4058: #endif
        !          4059:       return EAGAIN;
        !          4060:     }
        !          4061: 
        !          4062:   dev->irq = irq;
        !          4063: 
        !          4064:   request_region(ioaddr, sizeof(ha_t), "wavelan");
        !          4065: 
        !          4066:   dev->mem_start = 0x0000;
        !          4067:   dev->mem_end = 0x0000;
        !          4068:   dev->if_port = 0;
        !          4069: 
        !          4070:   /* Initialize device structures */
        !          4071:   dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL);
        !          4072:   if(dev->priv == NULL)
        !          4073:     return -ENOMEM;
        !          4074:   memset(dev->priv, 0x00, sizeof(net_local));
        !          4075:   lp = (net_local *)dev->priv;
        !          4076: 
        !          4077:   /* Back link to the device structure. */
        !          4078:   lp->dev = dev;
        !          4079:   /* Add the device at the beginning of the linked list. */
        !          4080:   lp->next = wavelan_list;
        !          4081:   wavelan_list = lp;
        !          4082: 
        !          4083:   lp->hacr = HACR_DEFAULT;
        !          4084: 
        !          4085:   lp->watchdog.function = wavelan_watchdog;
        !          4086:   lp->watchdog.data = (unsigned long) dev;
        !          4087:   lp->promiscuous = 0;
        !          4088:   lp->mc_count = 0;
        !          4089: 
        !          4090:   /*
        !          4091:    * Fill in the fields of the device structure
        !          4092:    * with Ethernet-generic values.
        !          4093:    */
        !          4094:   ether_setup(dev);
        !          4095: 
        !          4096:   dev->open = wavelan_open;
        !          4097:   dev->stop = wavelan_close;
        !          4098:   dev->hard_start_xmit = wavelan_packet_xmit;
        !          4099:   dev->get_stats = wavelan_get_stats;
        !          4100:   dev->set_multicast_list = &wavelan_set_multicast_list;
        !          4101:   dev->set_mac_address = &wavelan_set_mac_address;
        !          4102: 
        !          4103: #ifdef WIRELESS_EXT    /* If wireless extension exist in the kernel */
        !          4104:   dev->do_ioctl = wavelan_ioctl;
        !          4105:   dev->get_wireless_stats = wavelan_get_wireless_stats;
        !          4106: #endif
        !          4107: 
        !          4108:   dev->mtu = WAVELAN_MTU;
        !          4109: 
        !          4110:   /* Display nice info */
        !          4111:   wv_init_info(dev);
        !          4112: 
        !          4113: #ifdef DEBUG_CALLBACK_TRACE
        !          4114:   printk(KERN_DEBUG "%s: <-wavelan_config()\n", dev->name);
        !          4115: #endif
        !          4116:   return 0;
        !          4117: }
        !          4118: 
        !          4119: /*------------------------------------------------------------------*/
        !          4120: /*
        !          4121:  * Check for a network adaptor of this type.  Return '0' iff one 
        !          4122:  * exists.  (There seem to be different interpretations of
        !          4123:  * the initial value of dev->base_addr.
        !          4124:  * We follow the example in drivers/net/ne.c.)
        !          4125:  * (called in "Space.c")
        !          4126:  * As this function is called outside the wavelan module, it should be
        !          4127:  * declared extern, but it seem to cause troubles...
        !          4128:  */
        !          4129: /* extern */ int
        !          4130: wavelan_probe(device * dev)
        !          4131: {
        !          4132:   short                base_addr;
        !          4133:   mac_addr     mac;            /* MAC address (check WaveLAN existence) */
        !          4134:   int          i;
        !          4135:   int          r;
        !          4136: 
        !          4137: #ifdef DEBUG_CALLBACK_TRACE
        !          4138:   printk(KERN_DEBUG "%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n",
        !          4139:         dev->name, (unsigned int)dev, (unsigned int)dev->base_addr);
        !          4140: #endif
        !          4141: 
        !          4142: #ifdef STRUCT_CHECK
        !          4143:   if (wv_struct_check() != (char *) NULL)
        !          4144:     {
        !          4145:       printk(KERN_WARNING "%s: wavelan_probe(): structure/compiler botch: \"%s\"\n",
        !          4146:             dev->name, wv_struct_check());
        !          4147:       return ENODEV;
        !          4148:     }
        !          4149: #endif /* STRUCT_CHECK */
        !          4150: 
        !          4151:   /* Check the value of the command line parameter for base address */
        !          4152:   base_addr = dev->base_addr;
        !          4153: 
        !          4154:   /* Don't probe at all. */
        !          4155:   if(base_addr < 0)
        !          4156:     {
        !          4157: #ifdef DEBUG_CONFIG_ERRORS
        !          4158:       printk(KERN_WARNING "%s: wavelan_probe(): invalid base address\n",
        !          4159:             dev->name);
        !          4160: #endif
        !          4161:       return ENXIO;
        !          4162:     }
        !          4163: 
        !          4164:   /* Check a single specified location. */
        !          4165:   if(base_addr > 0x100)
        !          4166:     {
        !          4167:       /* Check if the is something at this base address */
        !          4168:       if((r = wv_check_ioaddr(base_addr, mac)) == 0)
        !          4169:        {
        !          4170:          memcpy(dev->dev_addr, mac, 6);        /* Copy MAC address */
        !          4171:          r = wavelan_config(dev);
        !          4172:        }
        !          4173: 
        !          4174: #ifdef DEBUG_CONFIG_INFO
        !          4175:       if(r != 0)
        !          4176:        printk(KERN_DEBUG "%s: wavelan_probe(): no device at specified base address (0x%X) or address already in use\n",
        !          4177:               dev->name, base_addr);
        !          4178: #endif
        !          4179: 
        !          4180: #ifdef DEBUG_CALLBACK_TRACE
        !          4181:       printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name);
        !          4182: #endif
        !          4183:       return r;
        !          4184:     }
        !          4185: 
        !          4186:   /* Scan all possible addresses of the WaveLAN hardware */
        !          4187:   for(i = 0; i < NELS(iobase); i++)
        !          4188:     {
        !          4189:       /* Check whether there is something at this base address */
        !          4190:       if(wv_check_ioaddr(iobase[i], mac) == 0)
        !          4191:        {
        !          4192:          dev->base_addr = iobase[i];           /* Copy base address. */
        !          4193:          memcpy(dev->dev_addr, mac, 6);        /* Copy MAC address. */
        !          4194:          if(wavelan_config(dev) == 0)
        !          4195:            {
        !          4196: #ifdef DEBUG_CALLBACK_TRACE
        !          4197:              printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name);
        !          4198: #endif
        !          4199:              return 0;
        !          4200:            }
        !          4201:        }
        !          4202:     }
        !          4203: 
        !          4204:   /* We may have touch base_addr: another driver may not like it. */
        !          4205:   dev->base_addr = base_addr;
        !          4206: 
        !          4207: #ifdef DEBUG_CONFIG_INFO
        !          4208:   printk(KERN_DEBUG "%s: wavelan_probe(): no device found\n",
        !          4209:         dev->name);
        !          4210: #endif
        !          4211: 
        !          4212:   return ENODEV;
        !          4213: }
        !          4214: 
        !          4215: /****************************** MODULE ******************************/
        !          4216: /*
        !          4217:  * Module entry point: insertion & removal
        !          4218:  */
        !          4219: 
        !          4220: #ifdef MODULE
        !          4221: /*------------------------------------------------------------------*/
        !          4222: /*
        !          4223:  * Insertion of the module.
        !          4224:  * I'm now quite proud of the multi-device support.
        !          4225:  */
        !          4226: int
        !          4227: init_module(void)
        !          4228: {
        !          4229:   mac_addr     mac;            /* MAC address (check WaveLAN existence) */
        !          4230:   int          ret = 0;
        !          4231:   int          i;
        !          4232: 
        !          4233: #ifdef DEBUG_MODULE_TRACE
        !          4234:   printk(KERN_DEBUG "-> init_module()\n");
        !          4235: #endif
        !          4236: 
        !          4237:   /* If probing is asked */
        !          4238:   if(io[0] == 0)
        !          4239:     {
        !          4240: #ifdef DEBUG_CONFIG_ERRORS
        !          4241:       printk(KERN_WARNING "WaveLAN init_module(): doing device probing (bad !)\n");
        !          4242:       printk(KERN_WARNING "Specify base addresses while loading module to correct the problem\n");
        !          4243: #endif
        !          4244: 
        !          4245:       /* Copy the basic set of address to be probed. */
        !          4246:       for(i = 0; i < NELS(iobase); i++)
        !          4247:        io[i] = iobase[i];
        !          4248:     }
        !          4249: 
        !          4250: 
        !          4251:   /* Loop on all possible base addresses */
        !          4252:   i = -1;
        !          4253:   while((io[++i] != 0) && (i < NELS(io)))
        !          4254:     {
        !          4255:       /* Check if there is something at this base address. */
        !          4256:       if(wv_check_ioaddr(io[i], mac) == 0)
        !          4257:        {
        !          4258:          device *      dev;
        !          4259: 
        !          4260:          /* Create device and set basics args */
        !          4261:          dev = kmalloc(sizeof(struct device), GFP_KERNEL);
        !          4262:          memset(dev, 0x00, sizeof(struct device));
        !          4263:          dev->name = name[i];
        !          4264:          dev->base_addr = io[i];
        !          4265:          dev->irq = irq[i];
        !          4266:          dev->init = &wavelan_config;
        !          4267:          memcpy(dev->dev_addr, mac, 6);        /* Copy MAC address */
        !          4268: 
        !          4269:          /* Try to create the device */
        !          4270:          if(register_netdev(dev) != 0)
        !          4271:            {
        !          4272:              /* DeAllocate everything */
        !          4273:              /* Note : if dev->priv is mallocated, there is no way to fail */
        !          4274:              kfree_s(dev, sizeof(struct device));
        !          4275:              ret = -EIO;
        !          4276:            }
        !          4277:        }       /* if there is something at the address */
        !          4278:     }          /* Loop on all addresses. */
        !          4279: 
        !          4280: #ifdef DEBUG_CONFIG_ERRORS
        !          4281:   if(wavelan_list == (net_local *) NULL)
        !          4282:     printk(KERN_WARNING "WaveLAN init_module(): no device found\n");
        !          4283: #endif
        !          4284: 
        !          4285: #ifdef DEBUG_MODULE_TRACE
        !          4286:   printk(KERN_DEBUG "<- init_module()\n");
        !          4287: #endif
        !          4288:   return ret;
        !          4289: }
        !          4290: 
        !          4291: /*------------------------------------------------------------------*/
        !          4292: /*
        !          4293:  * Removal of the module
        !          4294:  */
        !          4295: void
        !          4296: cleanup_module(void)
        !          4297: {
        !          4298: #ifdef DEBUG_MODULE_TRACE
        !          4299:   printk(KERN_DEBUG "-> cleanup_module()\n");
        !          4300: #endif
        !          4301: 
        !          4302:   /* Loop on all devices and release them. */
        !          4303:   while(wavelan_list != (net_local *) NULL)
        !          4304:     {
        !          4305:       device * dev = wavelan_list->dev;
        !          4306: 
        !          4307: #ifdef DEBUG_CONFIG_INFO
        !          4308:       printk(KERN_DEBUG "%s: cleanup_module(): removing device at 0x%x\n",
        !          4309:             dev->name, (unsigned int) dev);
        !          4310: #endif
        !          4311: 
        !          4312:       /* Release the ioport-region. */
        !          4313:       release_region(dev->base_addr, sizeof(ha_t));
        !          4314: 
        !          4315:       /* Definitely remove the device. */
        !          4316:       unregister_netdev(dev);
        !          4317: 
        !          4318:       /* Unlink the device. */
        !          4319:       wavelan_list = wavelan_list->next;
        !          4320: 
        !          4321:       /* Free pieces. */
        !          4322:       kfree_s(dev->priv, sizeof(struct net_local));
        !          4323:       kfree_s(dev, sizeof(struct device));
        !          4324:     }
        !          4325: 
        !          4326: #ifdef DEBUG_MODULE_TRACE
        !          4327:   printk(KERN_DEBUG "<- cleanup_module()\n");
        !          4328: #endif
        !          4329: }
        !          4330: #endif /* MODULE */
        !          4331: 
        !          4332: /*
        !          4333:  * This software may only be used and distributed
        !          4334:  * according to the terms of the GNU Public License.
        !          4335:  *
        !          4336:  * This software was developed as a component of the
        !          4337:  * Linux operating system.
        !          4338:  * It is based on other device drivers and information
        !          4339:  * either written or supplied by:
        !          4340:  *     Ajay Bakre ([email protected]),
        !          4341:  *     Donald Becker ([email protected]),
        !          4342:  *     Loeke Brederveld ([email protected]),
        !          4343:  *     Anders Klemets ([email protected]),
        !          4344:  *     Vladimir V. Kolpakov ([email protected]),
        !          4345:  *     Marc Meertens ([email protected]),
        !          4346:  *     Pauline Middelink ([email protected]),
        !          4347:  *     Robert Morris ([email protected]),
        !          4348:  *     Jean Tourrilhes ([email protected]),
        !          4349:  *     Girish Welling ([email protected]),
        !          4350:  *
        !          4351:  * Thanks go also to:
        !          4352:  *     James Ashton ([email protected]),
        !          4353:  *     Alan Cox ([email protected]),
        !          4354:  *     Allan Creighton ([email protected]),
        !          4355:  *     Matthew Geier ([email protected]),
        !          4356:  *     Remo di Giovanni ([email protected]),
        !          4357:  *     Eckhard Grah ([email protected]),
        !          4358:  *     Vipul Gupta ([email protected]),
        !          4359:  *     Mark Hagan ([email protected]),
        !          4360:  *     Tim Nicholson ([email protected]),
        !          4361:  *     Ian Parkin ([email protected]),
        !          4362:  *     John Rosenberg ([email protected]),
        !          4363:  *     George Rossi ([email protected]),
        !          4364:  *     Arthur Scott ([email protected]),
        !          4365:  *     Peter Storey,
        !          4366:  * for their assistance and advice.
        !          4367:  *
        !          4368:  * Please send bug reports, updates, comments to:
        !          4369:  *
        !          4370:  * Bruce Janson                                    Email:  [email protected]
        !          4371:  * Basser Department of Computer Science           Phone:  +61-2-9351-3423
        !          4372:  * University of Sydney, N.S.W., 2006, AUSTRALIA   Fax:    +61-2-9351-3838
        !          4373:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.