Annotation of Gnu-Mach/i386/i386at/gpl/linux/net/hp100.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * hp100.c: Hewlett Packard HP10/100VG ANY LAN ethernet driver for Linux.
        !             3:  *
        !             4:  * Author:  Jaroslav Kysela, <[email protected]>
        !             5:  *
        !             6:  * Supports only the following Hewlett Packard cards:
        !             7:  *
        !             8:  *     HP J2577        10/100 EISA card with REVA Cascade chip
        !             9:  *     HP J2573        10/100 ISA card with REVA Cascade chip
        !            10:  *     HP 27248B       10 only EISA card with Cascade chip
        !            11:  *     HP J2577        10/100 EISA card with Cascade chip
        !            12:  *     HP J2573        10/100 ISA card with Cascade chip
        !            13:  *     HP J2585        10/100 PCI card
        !            14:  *
        !            15:  * Other ATT2MD01 Chip based boards might be supported in the future
        !            16:  * (there are some minor changes needed).
        !            17:  *
        !            18:  * This driver is based on the 'hpfepkt' crynwr packet driver.
        !            19:  *
        !            20:  * This source/code is public free; you can distribute it and/or modify 
        !            21:  * it under terms of the GNU General Public License (published by the
        !            22:  * Free Software Foundation) either version two of this License, or any 
        !            23:  * later version.
        !            24:  * ----------------------------------------------------------------------------
        !            25:  *
        !            26:  * Note: Some routines (interrupt handling, transmit) assumes that  
        !            27:  *       there is the PERFORMANCE page selected...
        !            28:  *
        !            29:  * ----------------------------------------------------------------------------
        !            30:  *
        !            31:  * If you are going to use the module version of this driver, you may
        !            32:  * change this values at the "insert time" :
        !            33:  *
        !            34:  *   Variable                   Description
        !            35:  *
        !            36:  *   hp100_rx_ratio            Range 1-99 - onboard memory used for RX
        !            37:  *                              packets in %.
        !            38:  *   hp100_priority_tx         If this variable is nonzero - all outgoing
        !            39:  *                              packets will be transmitted as priority.
        !            40:  *   hp100_port                        Adapter port (for example 0x380).
        !            41:  *
        !            42:  * ----------------------------------------------------------------------------
        !            43:  * MY BEST REGARDS GOING TO:
        !            44:  *
        !            45:  * IPEX s.r.o which lend me two HP J2573 cards and
        !            46:  * the HP AdvanceStack 100VG Hub-15 for debugging.
        !            47:  *
        !            48:  * Russel Nellson <[email protected]> for help with obtaining sources
        !            49:  * of the 'hpfepkt' packet driver.
        !            50:  *
        !            51:  * Also thanks to Abacus Electric s.r.o which let me to use their 
        !            52:  * motherboard for my second computer.
        !            53:  *
        !            54:  * ----------------------------------------------------------------------------
        !            55:  *
        !            56:  * TO DO:
        !            57:  * ======
        !            58:  *       - ioctl handling - some runtime setup things
        !            59:  *       - 100Mb/s Voice Grade AnyLAN network adapter/hub services support
        !            60:  *             - 802.5 frames
        !            61:  *             - promiscuous mode
        !            62:  *             - bridge mode
        !            63:  *             - cascaded repeater mode
        !            64:  *             - 100Mbit MAC
        !            65:  *
        !            66:  * Revision history:
        !            67:  * =================
        !            68:  * 
        !            69:  *    Version   Date       Description
        !            70:  *
        !            71:  *     0.1     14-May-95   Initial writing. ALPHA code was released.
        !            72:  *                          Only HP J2573 on 10Mb/s (two machines) tested.
        !            73:  *      0.11    14-Jun-95   Reset interface bug fixed?
        !            74:  *                         Little bug in hp100_close function fixed.
        !            75:  *                          100Mb/s connection debugged.
        !            76:  *      0.12    14-Jul-95   Link down is now handled better.
        !            77:  *      0.20    01-Aug-95   Added PCI support for HP J2585A card.
        !            78:  *                          Statistics bug fixed.
        !            79:  *      0.21    04-Aug-95   Memory mapped access support for PCI card.
        !            80:  *                          Added priority transmit support for 100Mb/s
        !            81:  *                          Voice Grade AnyLAN network.
        !            82:  *
        !            83:  */
        !            84: 
        !            85: #include <linux/module.h>
        !            86: 
        !            87: #include <linux/kernel.h>
        !            88: #include <linux/sched.h>
        !            89: #include <linux/string.h>
        !            90: #include <linux/errno.h>
        !            91: #include <linux/ioport.h>
        !            92: #include <linux/malloc.h>
        !            93: #include <linux/interrupt.h>
        !            94: #include <linux/pci.h>
        !            95: #include <linux/bios32.h>
        !            96: #include <asm/bitops.h>
        !            97: #include <asm/io.h>
        !            98: 
        !            99: #include <linux/netdevice.h>
        !           100: #include <linux/etherdevice.h>
        !           101: #include <linux/skbuff.h>
        !           102: 
        !           103: #include <linux/types.h>
        !           104: #include <linux/config.h>      /* for CONFIG_PCI */
        !           105: 
        !           106: #include "hp100.h"
        !           107: 
        !           108: /*
        !           109:  *  defines
        !           110:  */
        !           111: 
        !           112: #define HP100_BUS_ISA          0
        !           113: #define HP100_BUS_EISA         1
        !           114: #define HP100_BUS_PCI          2
        !           115: 
        !           116: #define HP100_REGION_SIZE      0x20
        !           117: 
        !           118: #define HP100_MAX_PACKET_SIZE  (1536+4)
        !           119: #define HP100_MIN_PACKET_SIZE  60
        !           120: 
        !           121: #ifndef HP100_DEFAULT_RX_RATIO
        !           122: /* default - 65% onboard memory on the card are used for RX packets */
        !           123: #define HP100_DEFAULT_RX_RATIO 65
        !           124: #endif
        !           125: 
        !           126: #ifndef HP100_DEFAULT_PRIORITY_TX
        !           127: /* default - don't enable transmit outgoing packets as priority */
        !           128: #define HP100_DEFAULT_PRIORITY_TX 0
        !           129: #endif
        !           130: 
        !           131: #ifdef MACH
        !           132: #define HP100_IO_MAPPED
        !           133: #endif
        !           134: 
        !           135: /*
        !           136:  *  structures
        !           137:  */
        !           138: 
        !           139: struct hp100_eisa_id {
        !           140:   u_int id;
        !           141:   const char *name;
        !           142:   u_char bus;
        !           143: };
        !           144: 
        !           145: struct hp100_private {
        !           146:   struct hp100_eisa_id *id;
        !           147:   u_short soft_model;
        !           148:   u_int memory_size;
        !           149:   u_short rx_ratio;                /* 1 - 99 */
        !           150:   u_short priority_tx;             /* != 0 - priority tx */
        !           151:   short mem_mapped;                /* memory mapped access */
        !           152:   u_char *mem_ptr_virt;                    /* virtual memory mapped area, maybe NULL */
        !           153:   u_char *mem_ptr_phys;                    /* physical memory mapped area */
        !           154:   short lan_type;                  /* 10Mb/s, 100Mb/s or -1 (error) */
        !           155:   int hub_status;                  /* login to hub was successfull? */
        !           156:   u_char mac1_mode;
        !           157:   u_char mac2_mode;
        !           158:   struct enet_statistics stats;
        !           159: };
        !           160: 
        !           161: /*
        !           162:  *  variables
        !           163:  */
        !           164:  
        !           165: static struct hp100_eisa_id hp100_eisa_ids[] = {
        !           166: 
        !           167:   /* 10/100 EISA card with REVA Cascade chip */
        !           168:   { 0x080F1F022, "HP J2577 rev A", HP100_BUS_EISA }, 
        !           169: 
        !           170:   /* 10/100 ISA card with REVA Cascade chip */
        !           171:   { 0x050F1F022, "HP J2573 rev A", HP100_BUS_ISA },
        !           172: 
        !           173:   /* 10 only EISA card with Cascade chip */
        !           174:   { 0x02019F022, "HP 27248B",      HP100_BUS_EISA }, 
        !           175: 
        !           176:   /* 10/100 EISA card with Cascade chip */
        !           177:   { 0x04019F022, "HP J2577",       HP100_BUS_EISA },
        !           178: 
        !           179:   /* 10/100 ISA card with Cascade chip */
        !           180:   { 0x05019F022, "HP J2573",       HP100_BUS_ISA },
        !           181: 
        !           182:   /* 10/100 PCI card */
        !           183:   /* Note: ID for this card is same as PCI vendor/device numbers. */
        !           184:   { 0x01030103c, "HP J2585",      HP100_BUS_PCI },
        !           185: };
        !           186: 
        !           187: int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO;
        !           188: int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX;
        !           189: 
        !           190: /*
        !           191:  *  prototypes
        !           192:  */
        !           193: 
        !           194: static int hp100_probe1( struct device *dev, int ioaddr, int bus );
        !           195: static int hp100_open( struct device *dev );
        !           196: static int hp100_close( struct device *dev );
        !           197: static int hp100_start_xmit( struct sk_buff *skb, struct device *dev );
        !           198: static void hp100_rx( struct device *dev );
        !           199: static struct enet_statistics *hp100_get_stats( struct device *dev );
        !           200: static void hp100_update_stats( struct device *dev );
        !           201: static void hp100_clear_stats( int ioaddr );
        !           202: static void hp100_set_multicast_list( struct device *dev);
        !           203: static void hp100_interrupt( int irq, struct pt_regs *regs );
        !           204: 
        !           205: static void hp100_start_interface( struct device *dev );
        !           206: static void hp100_stop_interface( struct device *dev );
        !           207: static void hp100_load_eeprom( struct device *dev );
        !           208: static int hp100_sense_lan( struct device *dev );
        !           209: static int hp100_login_to_vg_hub( struct device *dev );
        !           210: static int hp100_down_vg_link( struct device *dev );
        !           211: 
        !           212: /*
        !           213:  *  probe functions
        !           214:  */
        !           215:  
        !           216: int hp100_probe( struct device *dev )
        !           217: {
        !           218:   int base_addr = dev ? dev -> base_addr : 0;
        !           219:   int ioaddr;
        !           220: #ifdef CONFIG_PCI
        !           221:   int pci_start_index = 0;
        !           222: #endif
        !           223: 
        !           224:   if ( base_addr > 0xff )      /* Check a single specified location. */
        !           225:     {
        !           226:       if ( check_region( base_addr, HP100_REGION_SIZE ) ) return -EINVAL;
        !           227:       if ( base_addr < 0x400 )
        !           228:         return hp100_probe1( dev, base_addr, HP100_BUS_ISA );
        !           229:        else
        !           230:         return hp100_probe1( dev, base_addr, HP100_BUS_EISA );
        !           231:     }
        !           232:    else 
        !           233: #ifdef CONFIG_PCI
        !           234:   if ( base_addr > 0 && base_addr < 8 + 1 )
        !           235:     pci_start_index = 0x100 | ( base_addr - 1 );
        !           236:    else
        !           237: #endif
        !           238:     if ( base_addr != 0 ) return -ENXIO;
        !           239: 
        !           240:   /* at first - scan PCI bus(es) */
        !           241:   
        !           242: #ifdef CONFIG_PCI
        !           243:   if ( pcibios_present() )
        !           244:     {
        !           245:       int pci_index;
        !           246:       
        !           247: #ifdef HP100_DEBUG_PCI
        !           248:       printk( "hp100: PCI BIOS is present, checking for devices..\n" );
        !           249: #endif
        !           250:       for ( pci_index = pci_start_index & 7; pci_index < 8; pci_index++ )
        !           251:         {
        !           252:           u_char pci_bus, pci_device_fn;
        !           253:           u_short pci_command;
        !           254:           
        !           255:           if ( pcibios_find_device( PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A,
        !           256:                                    pci_index, &pci_bus,
        !           257:                                    &pci_device_fn ) != 0 ) break;
        !           258:           pcibios_read_config_dword( pci_bus, pci_device_fn,
        !           259:                                     PCI_BASE_ADDRESS_0, &ioaddr );
        !           260:                                         
        !           261:           ioaddr &= ~3;                /* remove I/O space marker in bit 0. */
        !           262:               
        !           263:           if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue;
        !           264:               
        !           265:           pcibios_read_config_word( pci_bus, pci_device_fn,
        !           266:                                    PCI_COMMAND, &pci_command );
        !           267:           if ( !( pci_command & PCI_COMMAND_MASTER ) )
        !           268:             {
        !           269: #ifdef HP100_DEBUG_PCI
        !           270:               printk( "hp100: PCI Master Bit has not been set. Setting...\n" );
        !           271: #endif
        !           272:               pci_command |= PCI_COMMAND_MASTER;
        !           273:               pcibios_write_config_word( pci_bus, pci_device_fn,
        !           274:                                         PCI_COMMAND, pci_command );
        !           275:             }
        !           276: #ifdef HP100_DEBUG_PCI
        !           277:           printk( "hp100: PCI adapter found at 0x%x\n", ioaddr );
        !           278: #endif
        !           279:                  if ( hp100_probe1( dev, ioaddr, HP100_BUS_PCI ) == 0 ) return 0;
        !           280:         }
        !           281:     }
        !           282:   if ( pci_start_index > 0 ) return -ENODEV;
        !           283: #endif /* CONFIG_PCI */
        !           284:          
        !           285:   /* at second - probe all EISA possible port regions (if EISA bus present) */
        !           286:   
        !           287:   for ( ioaddr = 0x1c38; EISA_bus && ioaddr < 0x10000; ioaddr += 0x400 )
        !           288:     {
        !           289:       if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue;
        !           290:       if ( hp100_probe1( dev, ioaddr, HP100_BUS_EISA ) == 0 ) return 0;
        !           291:     }
        !           292:          
        !           293:   /* at third - probe all ISA possible port regions */
        !           294:          
        !           295:   for ( ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20 )
        !           296:     {
        !           297:       if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue;
        !           298:       if ( hp100_probe1( dev, ioaddr, HP100_BUS_ISA ) == 0 ) return 0;
        !           299:     }
        !           300:                                                                             
        !           301:   return -ENODEV;
        !           302: }
        !           303: 
        !           304: static int hp100_probe1( struct device *dev, int ioaddr, int bus )
        !           305: {
        !           306:   int i;
        !           307:   u_char uc, uc_1;
        !           308:   u_int eisa_id;
        !           309:   short mem_mapped;
        !           310:   u_char *mem_ptr_phys, *mem_ptr_virt;
        !           311:   struct hp100_private *lp;
        !           312:   struct hp100_eisa_id *eid;
        !           313: 
        !           314:   if ( dev == NULL )
        !           315:     {
        !           316: #ifdef HP100_DEBUG
        !           317:       printk( "hp100_probe1: dev == NULL ?\n" );
        !           318: #endif
        !           319:       return EIO;
        !           320:     }
        !           321: 
        !           322:   if ( bus != HP100_BUS_PCI )          /* don't check PCI cards again */
        !           323:     if ( inb( ioaddr + 0 ) != HP100_HW_ID_0 ||
        !           324:          inb( ioaddr + 1 ) != HP100_HW_ID_1 ||
        !           325:          ( inb( ioaddr + 2 ) & 0xf0 ) != HP100_HW_ID_2_REVA ||
        !           326:          inb( ioaddr + 3 ) != HP100_HW_ID_3 ) 
        !           327:        return -ENODEV;
        !           328: 
        !           329:   dev -> base_addr = ioaddr;
        !           330: 
        !           331: #ifdef HP100_DEBUG_PROBE1
        !           332:   printk( "hp100_probe1: card found at port 0x%x\n", ioaddr );
        !           333: #endif
        !           334: 
        !           335:   hp100_page( ID_MAC_ADDR );
        !           336:   for ( i = uc = eisa_id = 0; i < 4; i++ )
        !           337:     {
        !           338:       eisa_id >>= 8;
        !           339:       uc_1 = hp100_inb( BOARD_ID + i );
        !           340:       eisa_id |= uc_1 << 24;
        !           341:       uc += uc_1;
        !           342:     }
        !           343:   uc += hp100_inb( BOARD_ID + 4 );
        !           344: 
        !           345: #ifdef HP100_DEBUG_PROBE1
        !           346:   printk( "hp100_probe1: EISA ID = 0x%08x  checksum = 0x%02x\n", eisa_id, uc );
        !           347: #endif
        !           348: 
        !           349:   if ( uc != 0xff )            /* bad checksum? */
        !           350:     {
        !           351:       printk( "hp100_probe: bad EISA ID checksum at base port 0x%x\n", ioaddr );
        !           352:       return -ENODEV;
        !           353:     }  
        !           354: 
        !           355:   for ( i = 0; i < sizeof( hp100_eisa_ids ) / sizeof( struct hp100_eisa_id ); i++ )
        !           356:     if ( ( hp100_eisa_ids[ i ].id & 0xf0ffffff ) == ( eisa_id & 0xf0ffffff ) )
        !           357:       break;
        !           358:   if ( i >= sizeof( hp100_eisa_ids ) / sizeof( struct hp100_eisa_id ) )
        !           359:     {
        !           360:       printk( "hp100_probe1: card at port 0x%x isn't known (id = 0x%x)\n", ioaddr, eisa_id );
        !           361:       return -ENODEV;
        !           362:     }
        !           363:   eid = &hp100_eisa_ids[ i ];
        !           364:   if ( ( eid -> id & 0x0f000000 ) < ( eisa_id & 0x0f000000 ) )
        !           365:     {
        !           366:       printk( "hp100_probe1: newer version of card %s at port 0x%x - unsupported\n", 
        !           367:        eid -> name, ioaddr );
        !           368:       return -ENODEV;
        !           369:     }
        !           370: 
        !           371:   for ( i = uc = 0; i < 7; i++ )
        !           372:     uc += hp100_inb( LAN_ADDR + i );
        !           373:   if ( uc != 0xff )
        !           374:     {
        !           375:       printk( "hp100_probe1: bad lan address checksum (card %s at port 0x%x)\n", 
        !           376:        eid -> name, ioaddr );
        !           377:       return -EIO;
        !           378:     }
        !           379: 
        !           380: #ifndef HP100_IO_MAPPED
        !           381:   hp100_page( HW_MAP );
        !           382:   mem_mapped = ( hp100_inw( OPTION_LSW ) & 
        !           383:                  ( HP100_MEM_EN | HP100_BM_WRITE | HP100_BM_READ ) ) != 0;
        !           384:   mem_ptr_phys = mem_ptr_virt = NULL;
        !           385:   if ( mem_mapped )
        !           386:     {
        !           387:       mem_ptr_phys = (u_char *)( hp100_inw( MEM_MAP_LSW ) | 
        !           388:                                ( hp100_inw( MEM_MAP_MSW ) << 16 ) );
        !           389:       (u_int)mem_ptr_phys &= ~0x1fff;  /* 8k aligment */
        !           390:       if ( bus == HP100_BUS_ISA && ( (u_long)mem_ptr_phys & ~0xfffff ) != 0 )
        !           391:         {
        !           392:           mem_ptr_phys = NULL;
        !           393:           mem_mapped = 0;
        !           394:         }
        !           395:       if ( mem_mapped && bus == HP100_BUS_PCI )
        !           396:         {
        !           397:           if ( ( mem_ptr_virt = vremap( (u_long)mem_ptr_phys, 0x2000 ) ) == NULL )
        !           398:             {
        !           399:               printk( "hp100: vremap for high PCI memory at 0x%lx failed\n", (u_long)mem_ptr_phys );
        !           400:               mem_ptr_phys = NULL;
        !           401:               mem_mapped = 0;
        !           402:             }
        !           403:         }
        !           404:     }
        !           405: #else
        !           406:   mem_mapped = 0;
        !           407:   mem_ptr_phys = mem_ptr_virt = NULL;
        !           408: #endif
        !           409: 
        !           410:   if ( ( dev -> priv = kmalloc( sizeof( struct hp100_private ), GFP_KERNEL ) ) == NULL )
        !           411:     return -ENOMEM;
        !           412:   memset( dev -> priv, 0, sizeof( struct hp100_private ) );
        !           413: 
        !           414:   lp = (struct hp100_private *)dev -> priv;
        !           415:   lp -> id = eid;
        !           416:   lp -> mem_mapped = mem_mapped;
        !           417:   lp -> mem_ptr_phys = mem_ptr_phys;
        !           418:   lp -> mem_ptr_virt = mem_ptr_virt;
        !           419:   hp100_page( ID_MAC_ADDR );
        !           420:   lp -> soft_model = hp100_inb( SOFT_MODEL );
        !           421:   lp -> mac1_mode = HP100_MAC1MODE3;
        !           422:   lp -> mac2_mode = HP100_MAC2MODE3;
        !           423:   
        !           424:   dev -> base_addr = ioaddr;
        !           425:   hp100_page( HW_MAP );
        !           426:   dev -> irq = hp100_inb( IRQ_CHANNEL ) & HP100_IRQ_MASK;
        !           427:   if ( dev -> irq == 2 ) dev -> irq = 9;
        !           428:   lp -> memory_size = 0x200 << ( ( hp100_inb( SRAM ) & 0xe0 ) >> 5 );
        !           429:   lp -> rx_ratio = hp100_rx_ratio;
        !           430: 
        !           431:   dev -> open = hp100_open;
        !           432:   dev -> stop = hp100_close;
        !           433:   dev -> hard_start_xmit = hp100_start_xmit;
        !           434:   dev -> get_stats = hp100_get_stats;
        !           435:   dev -> set_multicast_list = &hp100_set_multicast_list;
        !           436: 
        !           437:   request_region( dev -> base_addr, HP100_REGION_SIZE, eid -> name );
        !           438: 
        !           439:   hp100_page( ID_MAC_ADDR );
        !           440:   for ( i = uc = 0; i < 6; i++ )
        !           441:     dev -> dev_addr[ i ] = hp100_inb( LAN_ADDR + i );
        !           442: 
        !           443:   hp100_clear_stats( ioaddr );
        !           444: 
        !           445:   ether_setup( dev );
        !           446: 
        !           447:   lp -> lan_type = hp100_sense_lan( dev );
        !           448:      
        !           449:   printk( "%s: %s at 0x%x, IRQ %d, ",
        !           450:     dev -> name, lp -> id -> name, ioaddr, dev -> irq );
        !           451:   switch ( bus ) {
        !           452:     case HP100_BUS_EISA: printk( "EISA" ); break;
        !           453:     case HP100_BUS_PCI:  printk( "PCI" );  break;
        !           454:     default:            printk( "ISA" );  break;
        !           455:   }
        !           456:   printk( " bus, %dk SRAM (rx/tx %d%%).\n",
        !           457:     lp -> memory_size >> ( 10 - 4 ), lp -> rx_ratio );
        !           458:   if ( mem_mapped )
        !           459:     {
        !           460:       printk( "%s: Memory area at 0x%lx-0x%lx",
        !           461:                dev -> name, (u_long)mem_ptr_phys, (u_long)mem_ptr_phys + 0x1fff );
        !           462:       if ( mem_ptr_virt )
        !           463:         printk( " (virtual base 0x%lx)", (u_long)mem_ptr_virt );
        !           464:       printk( ".\n" );
        !           465:     }
        !           466:   printk( "%s: ", dev -> name );
        !           467:   if ( lp -> lan_type != HP100_LAN_ERR )
        !           468:     printk( "Adapter is attached to " );
        !           469:   switch ( lp -> lan_type ) {
        !           470:     case HP100_LAN_100:
        !           471:       printk( "100Mb/s Voice Grade AnyLAN network.\n" );
        !           472:       break;
        !           473:     case HP100_LAN_10:
        !           474:       printk( "10Mb/s network.\n" );
        !           475:       break;
        !           476:     default:
        !           477:       printk( "Warning! Link down.\n" );
        !           478:   }
        !           479:                
        !           480:   hp100_stop_interface( dev );
        !           481:   
        !           482:   return 0;
        !           483: }
        !           484: 
        !           485: /*
        !           486:  *  open/close functions
        !           487:  */
        !           488: 
        !           489: static int hp100_open( struct device *dev )
        !           490: {
        !           491:   int i;
        !           492:   int ioaddr = dev -> base_addr;
        !           493:   struct hp100_private *lp = (struct hp100_private *)dev -> priv;
        !           494: 
        !           495:   if ( request_irq( dev -> irq, hp100_interrupt, SA_INTERRUPT, lp -> id -> name ) )
        !           496:     {
        !           497:       printk( "%s: unable to get IRQ %d\n", dev -> name, dev -> irq );
        !           498:       return -EAGAIN;
        !           499:     }
        !           500:   irq2dev_map[ dev -> irq ] = dev;
        !           501: 
        !           502:   MOD_INC_USE_COUNT;
        !           503:   
        !           504:   dev -> tbusy = 0;
        !           505:   dev -> trans_start = jiffies;
        !           506:   dev -> interrupt = 0;
        !           507:   dev -> start = 1;
        !           508: 
        !           509:   lp -> lan_type = hp100_sense_lan( dev );
        !           510:   lp -> mac1_mode = HP100_MAC1MODE3;
        !           511:   lp -> mac2_mode = HP100_MAC2MODE3;
        !           512:   
        !           513:   hp100_page( MAC_CTRL );
        !           514:   hp100_orw( HP100_LINK_BEAT_DIS | HP100_RESET_LB, LAN_CFG_10 );
        !           515: 
        !           516:   hp100_stop_interface( dev );
        !           517:   hp100_load_eeprom( dev );
        !           518: 
        !           519:   hp100_outw( HP100_MMAP_DIS | HP100_SET_HB | 
        !           520:               HP100_IO_EN | HP100_SET_LB, OPTION_LSW );
        !           521:   hp100_outw( HP100_DEBUG_EN | HP100_RX_HDR | HP100_EE_EN | HP100_RESET_HB |
        !           522:               HP100_FAKE_INT | HP100_RESET_LB, OPTION_LSW );
        !           523:   hp100_outw( HP100_ADV_NXT_PKT | HP100_TX_CMD | HP100_RESET_LB |
        !           524:                 HP100_PRIORITY_TX | ( hp100_priority_tx ? HP100_SET_HB : HP100_RESET_HB ),
        !           525:               OPTION_MSW );
        !           526:                                        
        !           527:   hp100_page( MAC_ADDRESS );
        !           528:   for ( i = 0; i < 6; i++ )
        !           529:     hp100_outb( dev -> dev_addr[ i ], MAC_ADDR + i );
        !           530:   for ( i = 0; i < 8; i++ )            /* setup multicast filter to receive all */
        !           531:     hp100_outb( 0xff, HASH_BYTE0 + i );
        !           532:   hp100_page( PERFORMANCE );
        !           533:   hp100_outw( 0xfefe, IRQ_MASK );      /* mask off all ints */
        !           534:   hp100_outw( 0xffff, IRQ_STATUS );    /* ack IRQ */
        !           535:   hp100_outw( (HP100_RX_PACKET | HP100_RX_ERROR | HP100_SET_HB) |
        !           536:               (HP100_TX_ERROR | HP100_SET_LB ), IRQ_MASK );
        !           537:                                        /* and enable few */
        !           538:   hp100_reset_card();
        !           539:   hp100_page( MMU_CFG );
        !           540:   hp100_outw( ( lp -> memory_size * lp -> rx_ratio ) / 100, RX_MEM_STOP );
        !           541:   hp100_outw( lp -> memory_size - 1, TX_MEM_STOP );
        !           542:   hp100_unreset_card();
        !           543: 
        !           544:   if ( lp -> lan_type == HP100_LAN_100 )
        !           545:     lp -> hub_status = hp100_login_to_vg_hub( dev );
        !           546: 
        !           547:   hp100_start_interface( dev );
        !           548: 
        !           549:   return 0;
        !           550: }
        !           551: 
        !           552: static int hp100_close( struct device *dev )
        !           553: {
        !           554:   int ioaddr = dev -> base_addr;
        !           555:   struct hp100_private *lp = (struct hp100_private *)dev -> priv;
        !           556: 
        !           557:   hp100_page( PERFORMANCE );
        !           558:   hp100_outw( 0xfefe, IRQ_MASK );              /* mask off all IRQs */
        !           559: 
        !           560:   hp100_stop_interface( dev );
        !           561: 
        !           562:   if ( lp -> lan_type == HP100_LAN_100 )       /* relogin */
        !           563:     hp100_login_to_vg_hub( dev );
        !           564: 
        !           565:   dev -> tbusy = 1;
        !           566:   dev -> start = 0;
        !           567: 
        !           568:   free_irq( dev -> irq );
        !           569:   irq2dev_map[ dev -> irq ] = NULL;
        !           570:   MOD_DEC_USE_COUNT;
        !           571:   return 0;
        !           572: }
        !           573: 
        !           574: /* 
        !           575:  *  transmit
        !           576:  */
        !           577: 
        !           578: static int hp100_start_xmit( struct sk_buff *skb, struct device *dev )
        !           579: {
        !           580:   int i, ok_flag;
        !           581:   int ioaddr = dev -> base_addr;
        !           582:   u_short val;
        !           583:   struct hp100_private *lp = (struct hp100_private *)dev -> priv;
        !           584: 
        !           585:   if ( lp -> lan_type < 0 )
        !           586:     {
        !           587:       hp100_stop_interface( dev );
        !           588:       if ( ( lp -> lan_type = hp100_sense_lan( dev ) ) < 0 )
        !           589:         {
        !           590:           printk( "%s: no connection found - check wire\n", dev -> name );
        !           591:           hp100_start_interface( dev );        /* 10Mb/s RX packets maybe handled */
        !           592:           return -EIO;
        !           593:         }
        !           594:       if ( lp -> lan_type == HP100_LAN_100 )
        !           595:         lp -> hub_status = hp100_login_to_vg_hub( dev );
        !           596:       hp100_start_interface( dev );
        !           597:     }
        !           598:   
        !           599:   if ( ( i = ( hp100_inl( TX_MEM_FREE ) & ~0x7fffffff ) ) < skb -> len + 16 )
        !           600:     {
        !           601: #ifdef HP100_DEBUG
        !           602:       printk( "hp100_start_xmit: rx free mem = 0x%x\n", i );
        !           603: #endif
        !           604:       if ( jiffies - dev -> trans_start < 2 * HZ ) return -EAGAIN;
        !           605:       if ( lp -> lan_type == HP100_LAN_100 && lp -> hub_status < 0 )
        !           606:                                /* 100Mb/s adapter isn't connected to hub */
        !           607:         {
        !           608:           printk( "%s: login to 100Mb/s hub retry\n", dev -> name );
        !           609:           hp100_stop_interface( dev );
        !           610:           lp -> hub_status = hp100_login_to_vg_hub( dev );
        !           611:           hp100_start_interface( dev );
        !           612:         }
        !           613:        else
        !           614:         {
        !           615:           hp100_ints_off();
        !           616:           i = hp100_sense_lan( dev );
        !           617:           hp100_page( PERFORMANCE );
        !           618:           hp100_ints_on();
        !           619:           if ( i == HP100_LAN_ERR )
        !           620:             printk( "%s: link down detected\n", dev -> name );
        !           621:            else
        !           622:           if ( lp -> lan_type != i )
        !           623:             {
        !           624:               /* it's very heavy - all network setting must be changed!!! */
        !           625:               printk( "%s: cable change 10Mb/s <-> 100Mb/s detected\n", dev -> name );
        !           626:               lp -> lan_type = i;
        !           627:               hp100_stop_interface( dev );
        !           628:               if ( lp -> lan_type == HP100_LAN_100 )
        !           629:                 lp -> hub_status = hp100_login_to_vg_hub( dev );
        !           630:               hp100_start_interface( dev );
        !           631:             }
        !           632:            else
        !           633:             {
        !           634:               printk( "%s: interface reset\n", dev -> name );
        !           635:               hp100_stop_interface( dev );
        !           636:               hp100_start_interface( dev );
        !           637:             }
        !           638:         }
        !           639:       dev -> trans_start = jiffies;
        !           640:       return -EAGAIN;
        !           641:     }
        !           642:     
        !           643:   if ( skb == NULL )
        !           644:     {
        !           645:       dev_tint( dev );
        !           646:       return 0;
        !           647:     }
        !           648:     
        !           649:   if ( skb -> len <= 0 ) return 0;
        !           650: 
        !           651:   for ( i = 0; i < 6000 && ( hp100_inw( OPTION_MSW ) & HP100_TX_CMD ); i++ )
        !           652:     {
        !           653: #ifdef HP100_DEBUG_TX
        !           654:       printk( "hp100_start_xmit: busy\n" );
        !           655: #endif    
        !           656:     }
        !           657: 
        !           658:   hp100_ints_off();
        !           659:   val = hp100_inw( IRQ_STATUS );
        !           660:   hp100_outw( val & HP100_TX_COMPLETE, IRQ_STATUS );
        !           661: #ifdef HP100_DEBUG_TX
        !           662:   printk( "hp100_start_xmit: irq_status = 0x%x, len = %d\n", val, (int)skb -> len );
        !           663: #endif
        !           664:   ok_flag = skb -> len >= HP100_MIN_PACKET_SIZE;
        !           665:   i = ok_flag ? skb -> len : HP100_MIN_PACKET_SIZE;
        !           666:   hp100_outw( i, DATA32 );             /* length to memory manager */
        !           667:   hp100_outw( i, FRAGMENT_LEN );
        !           668:   if ( lp -> mem_mapped )
        !           669:     {
        !           670:       if ( lp -> mem_ptr_virt )
        !           671:         {
        !           672:           memcpy( lp -> mem_ptr_virt, skb -> data, skb -> len );
        !           673:           if ( !ok_flag )
        !           674:             memset( lp -> mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb -> len );
        !           675:         }
        !           676:        else
        !           677:         {
        !           678:           memcpy_toio( lp -> mem_ptr_phys, skb -> data, skb -> len );
        !           679:           if ( !ok_flag )
        !           680:             memset_io( lp -> mem_ptr_phys, 0, HP100_MIN_PACKET_SIZE - skb -> len );
        !           681:         }
        !           682:     }
        !           683:    else
        !           684:     {
        !           685:       outsl( ioaddr + HP100_REG_DATA32, skb -> data, ( skb -> len + 3 ) >> 2 );
        !           686:       if ( !ok_flag )
        !           687:         for ( i = ( skb -> len + 3 ) & ~3; i < HP100_MIN_PACKET_SIZE; i += 4 )
        !           688:           hp100_outl( 0, DATA32 );
        !           689:     }
        !           690:   hp100_outw( HP100_TX_CMD | HP100_SET_LB, OPTION_MSW ); /* send packet */
        !           691:   lp -> stats.tx_packets++;
        !           692:   dev -> trans_start = jiffies;
        !           693:   hp100_ints_on();
        !           694: 
        !           695:   dev_kfree_skb( skb, FREE_WRITE );
        !           696: 
        !           697: #ifdef HP100_DEBUG_TX
        !           698:   printk( "hp100_start_xmit: end\n" );
        !           699: #endif
        !           700: 
        !           701:   return 0;
        !           702: }
        !           703: 
        !           704: /*
        !           705:  *  receive - called from interrupt handler
        !           706:  */
        !           707: 
        !           708: static void hp100_rx( struct device *dev )
        !           709: {
        !           710:   int packets, pkt_len;
        !           711:   int ioaddr = dev -> base_addr;
        !           712:   struct hp100_private *lp = (struct hp100_private *)dev -> priv;
        !           713:   u_int header;
        !           714:   struct sk_buff *skb;
        !           715: 
        !           716: #if 0
        !           717:   if ( lp -> lan_type < 0 )
        !           718:     {
        !           719:       if ( ( lp -> lan_type = hp100_sense_lan( dev ) ) == HP100_LAN_100 )
        !           720:         lp -> hub_status = hp100_login_to_vg_hub( dev );
        !           721:       hp100_page( PERFORMANCE );
        !           722:     }
        !           723: #endif
        !           724:   
        !           725:   packets = hp100_inb( RX_PKT_CNT );
        !           726: #ifdef HP100_DEBUG
        !           727:   if ( packets > 1 )
        !           728:     printk( "hp100_rx: waiting packets = %d\n", packets );
        !           729: #endif
        !           730:   while ( packets-- > 0 )
        !           731:     {
        !           732:       for ( pkt_len = 0; pkt_len < 6000 && ( hp100_inw( OPTION_MSW ) & HP100_ADV_NXT_PKT ); pkt_len++ )
        !           733:         {
        !           734: #ifdef HP100_DEBUG_TX
        !           735:           printk( "hp100_rx: busy, remaining packets = %d\n", packets );
        !           736: #endif    
        !           737:         }
        !           738:       if ( lp -> mem_mapped )
        !           739:         {
        !           740:           if ( lp -> mem_ptr_virt )
        !           741:             header = *(__u32 *)lp -> mem_ptr_virt;
        !           742:            else
        !           743:             header = readl( lp -> mem_ptr_phys );
        !           744:         }
        !           745:        else
        !           746:         header = hp100_inl( DATA32 );
        !           747:       pkt_len = header & HP100_PKT_LEN_MASK;
        !           748: #ifdef HP100_DEBUG_RX
        !           749:       printk( "hp100_rx: new packet - length = %d, errors = 0x%x, dest = 0x%x\n",
        !           750:        header & HP100_PKT_LEN_MASK, ( header >> 16 ) & 0xfff8, ( header >> 16 ) & 7 );
        !           751: #endif
        !           752:       /*
        !           753:        * NOTE! This (and the skb_put() below) depends on the skb-functions
        !           754:        * allocating more than asked (notably, aligning the request up to
        !           755:        * the next 16-byte length).
        !           756:        */
        !           757:       skb = dev_alloc_skb( pkt_len );
        !           758:       if ( skb == NULL )
        !           759:         {
        !           760: #ifdef HP100_DEBUG
        !           761:           printk( "hp100_rx: couldn't allocate a sk_buff of size %d\n", pkt_len );
        !           762: #endif
        !           763:           lp -> stats.rx_dropped++;
        !           764:         }
        !           765:        else
        !           766:         {
        !           767:           u_char *ptr;
        !           768:         
        !           769:           skb -> dev = dev;
        !           770:           ptr = (u_char *)skb_put( skb, pkt_len );
        !           771:           if ( lp -> mem_mapped )
        !           772:             {
        !           773:               if ( lp -> mem_ptr_virt )
        !           774:                 memcpy( ptr, lp -> mem_ptr_virt, ( pkt_len + 3 ) & ~3 );
        !           775:                else
        !           776:                 memcpy_fromio( ptr, lp -> mem_ptr_phys, ( pkt_len + 3 ) & ~3 );
        !           777:             }
        !           778:            else
        !           779:             insl( ioaddr + HP100_REG_DATA32, ptr, ( pkt_len + 3 ) >> 2 );
        !           780:           skb -> protocol = eth_type_trans( skb, dev );
        !           781:           netif_rx( skb );
        !           782:           lp -> stats.rx_packets++;
        !           783: #ifdef HP100_DEBUG_RX
        !           784:           printk( "rx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
        !           785:                ptr[ 0 ], ptr[ 1 ], ptr[ 2 ], ptr[ 3 ], ptr[ 4 ], ptr[ 5 ],
        !           786:                ptr[ 6 ], ptr[ 7 ], ptr[ 8 ], ptr[ 9 ], ptr[ 10 ], ptr[ 11 ] );
        !           787: #endif
        !           788:         }
        !           789:       hp100_outw( HP100_ADV_NXT_PKT | HP100_SET_LB, OPTION_MSW );
        !           790:       switch ( header & 0x00070000 ) {
        !           791:         case (HP100_MULTI_ADDR_HASH<<16):
        !           792:         case (HP100_MULTI_ADDR_NO_HASH<<16):
        !           793:           lp -> stats.multicast++; break;
        !           794:       }
        !           795:     }
        !           796: #ifdef HP100_DEBUG_RX
        !           797:    printk( "hp100_rx: end\n" );
        !           798: #endif
        !           799: }
        !           800: 
        !           801: /*
        !           802:  *  statistics
        !           803:  */
        !           804:  
        !           805: static struct enet_statistics *hp100_get_stats( struct device *dev )
        !           806: {
        !           807:   int ioaddr = dev -> base_addr;
        !           808: 
        !           809:   hp100_ints_off();
        !           810:   hp100_update_stats( dev );
        !           811:   hp100_ints_on();
        !           812:   return &((struct hp100_private *)dev -> priv) -> stats;
        !           813: }
        !           814: 
        !           815: static void hp100_update_stats( struct device *dev )
        !           816: {
        !           817:   int ioaddr = dev -> base_addr;
        !           818:   u_short val;
        !           819:   struct hp100_private *lp = (struct hp100_private *)dev -> priv;
        !           820:          
        !           821:   hp100_page( MAC_CTRL );              /* get all statistics bytes */
        !           822:   val = hp100_inw( DROPPED ) & 0x0fff;
        !           823:   lp -> stats.rx_errors += val;
        !           824:   lp -> stats.rx_over_errors += val;
        !           825:   val = hp100_inb( CRC );
        !           826:   lp -> stats.rx_errors += val;
        !           827:   lp -> stats.rx_crc_errors += val;
        !           828:   val = hp100_inb( ABORT );
        !           829:   lp -> stats.tx_errors += val;
        !           830:   lp -> stats.tx_aborted_errors += val;
        !           831:   hp100_page( PERFORMANCE );
        !           832: }
        !           833: 
        !           834: static void hp100_clear_stats( int ioaddr )
        !           835: {
        !           836:   cli();
        !           837:   hp100_page( MAC_CTRL );              /* get all statistics bytes */
        !           838:   hp100_inw( DROPPED );
        !           839:   hp100_inb( CRC );
        !           840:   hp100_inb( ABORT );
        !           841:   hp100_page( PERFORMANCE );
        !           842:   sti();
        !           843: }
        !           844: 
        !           845: /*
        !           846:  *  multicast setup
        !           847:  */
        !           848: 
        !           849: /*
        !           850:  *  Set or clear the multicast filter for this adapter.
        !           851:  */
        !           852:                                                           
        !           853: static void hp100_set_multicast_list( struct device *dev)
        !           854: {
        !           855:   int ioaddr = dev -> base_addr;
        !           856:   struct hp100_private *lp = (struct hp100_private *)dev -> priv;
        !           857: 
        !           858: #ifdef HP100_DEBUG_MULTI
        !           859:   printk( "hp100_set_multicast_list: num_addrs = %d\n", dev->mc_count);
        !           860: #endif
        !           861:   cli();
        !           862:   hp100_ints_off();
        !           863:   hp100_page( MAC_CTRL );
        !           864:   hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 );       /* stop rx/tx */
        !           865: 
        !           866:   if ( dev->flags&IFF_PROMISC)
        !           867:     {
        !           868:       lp -> mac2_mode = HP100_MAC2MODE6;  /* promiscuous mode, all good */
        !           869:       lp -> mac1_mode = HP100_MAC1MODE6;  /* packets on the net */
        !           870:     }
        !           871:    else
        !           872:   if ( dev->mc_count || dev->flags&IFF_ALLMULTI )
        !           873:     {
        !           874:       lp -> mac2_mode = HP100_MAC2MODE5;  /* multicast mode, packets for me */
        !           875:       lp -> mac1_mode = HP100_MAC1MODE5;  /* broadcasts and all multicasts */
        !           876:     }
        !           877:    else
        !           878:     {
        !           879:       lp -> mac2_mode = HP100_MAC2MODE3;  /* normal mode, packets for me */
        !           880:       lp -> mac1_mode = HP100_MAC1MODE3;  /* and broadcasts */
        !           881:     }
        !           882: 
        !           883:   hp100_outb( lp -> mac2_mode, MAC_CFG_2 );
        !           884:   hp100_andb( HP100_MAC1MODEMASK, MAC_CFG_1 );
        !           885:   hp100_orb( lp -> mac1_mode |
        !           886:             HP100_RX_EN | HP100_RX_IDLE |              /* enable rx */
        !           887:             HP100_TX_EN | HP100_TX_IDLE, MAC_CFG_1 );  /* enable tx */
        !           888:   hp100_page( PERFORMANCE );
        !           889:   hp100_ints_on();
        !           890:   sti();
        !           891: }
        !           892: 
        !           893: /*
        !           894:  *  hardware interrupt handling
        !           895:  */
        !           896: 
        !           897: static void hp100_interrupt( int irq, struct pt_regs *regs )
        !           898: {
        !           899:   struct device *dev = (struct device *)irq2dev_map[ irq ];
        !           900:   struct hp100_private *lp;
        !           901:   int ioaddr;
        !           902:   u_short val;
        !           903: 
        !           904:   if ( dev == NULL ) return;
        !           905:   ioaddr = dev -> base_addr;
        !           906:   if ( dev -> interrupt )
        !           907:     printk( "%s: re-entering the interrupt handler\n", dev -> name );
        !           908:   hp100_ints_off();
        !           909:   dev -> interrupt = 1;
        !           910:   hp100_page( PERFORMANCE );
        !           911:   val = hp100_inw( IRQ_STATUS );
        !           912: #ifdef HP100_DEBUG_IRQ
        !           913:   printk( "hp100_interrupt: irq_status = 0x%x\n", val );
        !           914: #endif
        !           915:   if ( val & HP100_RX_PACKET )
        !           916:     {
        !           917:       hp100_rx( dev );
        !           918:       hp100_outw( HP100_RX_PACKET, IRQ_STATUS );
        !           919:     }
        !           920:   if ( val & (HP100_TX_SPACE_AVAIL | HP100_TX_COMPLETE) )
        !           921:     {
        !           922:       hp100_outw( val & (HP100_TX_SPACE_AVAIL | HP100_TX_COMPLETE), IRQ_STATUS );
        !           923:     }
        !           924:   if ( val & ( HP100_TX_ERROR | HP100_RX_ERROR ) )
        !           925:     {
        !           926:       lp = (struct hp100_private *)dev -> priv;
        !           927:       hp100_update_stats( dev );
        !           928:       hp100_outw( val & (HP100_TX_ERROR | HP100_RX_ERROR), IRQ_STATUS );
        !           929:     }
        !           930: #ifdef HP100_DEBUG_IRQ
        !           931:   printk( "hp100_interrupt: end\n" );
        !           932: #endif
        !           933:   dev -> interrupt = 0;
        !           934:   hp100_ints_on();
        !           935: }
        !           936: 
        !           937: /*
        !           938:  *  some misc functions
        !           939:  */
        !           940: 
        !           941: static void hp100_start_interface( struct device *dev )
        !           942: {
        !           943:   int ioaddr = dev -> base_addr;
        !           944:   struct hp100_private *lp = (struct hp100_private *)dev -> priv;
        !           945: 
        !           946:   cli();
        !           947:   hp100_unreset_card();
        !           948:   hp100_page( MAC_CTRL );
        !           949:   hp100_outb( lp -> mac2_mode, MAC_CFG_2 );
        !           950:   hp100_andb( HP100_MAC1MODEMASK, MAC_CFG_1 );
        !           951:   hp100_orb( lp -> mac1_mode |
        !           952:              HP100_RX_EN | HP100_RX_IDLE |
        !           953:              HP100_TX_EN | HP100_TX_IDLE, MAC_CFG_1 );
        !           954:   hp100_page( PERFORMANCE );
        !           955:   hp100_outw( HP100_INT_EN | HP100_SET_LB, OPTION_LSW );
        !           956:   hp100_outw( HP100_TRI_INT | HP100_RESET_HB, OPTION_LSW );
        !           957:   if ( lp -> mem_mapped )
        !           958:     {
        !           959:       /* enable memory mapping */
        !           960:       hp100_outw( HP100_MMAP_DIS | HP100_RESET_HB, OPTION_LSW );
        !           961:     }
        !           962:   sti();
        !           963: } 
        !           964: 
        !           965: static void hp100_stop_interface( struct device *dev )
        !           966: {
        !           967:   int ioaddr = dev -> base_addr;
        !           968:   u_short val;
        !           969: 
        !           970:   hp100_outw( HP100_INT_EN | HP100_RESET_LB | 
        !           971:               HP100_TRI_INT | HP100_MMAP_DIS | HP100_SET_HB, OPTION_LSW );
        !           972:   val = hp100_inw( OPTION_LSW );
        !           973:   hp100_page( HW_MAP );
        !           974:   hp100_andb( HP100_BM_SLAVE, BM );
        !           975:   hp100_page( MAC_CTRL );
        !           976:   hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 );
        !           977:   if ( !(val & HP100_HW_RST) ) return;
        !           978:   for ( val = 0; val < 6000; val++ )
        !           979:     if ( ( hp100_inb( MAC_CFG_1 ) & (HP100_TX_IDLE | HP100_RX_IDLE) ) ==
        !           980:                                     (HP100_TX_IDLE | HP100_RX_IDLE) )
        !           981:       return;
        !           982:   printk( "%s: hp100_stop_interface - timeout\n", dev -> name );
        !           983: }
        !           984: 
        !           985: static void hp100_load_eeprom( struct device *dev )
        !           986: {
        !           987:   int i;
        !           988:   int ioaddr = dev -> base_addr;
        !           989: 
        !           990:   hp100_page( EEPROM_CTRL );
        !           991:   hp100_andw( ~HP100_EEPROM_LOAD, EEPROM_CTRL );
        !           992:   hp100_orw( HP100_EEPROM_LOAD, EEPROM_CTRL );
        !           993:   for ( i = 0; i < 6000; i++ )
        !           994:     if ( !( hp100_inw( OPTION_MSW ) & HP100_EE_LOAD ) ) return;
        !           995:   printk( "%s: hp100_load_eeprom - timeout\n", dev -> name );
        !           996: }
        !           997: 
        !           998: /* return values: LAN_10, LAN_100 or LAN_ERR (not connected or hub is down)... */
        !           999: 
        !          1000: static int hp100_sense_lan( struct device *dev )
        !          1001: {
        !          1002:   int i;
        !          1003:   int ioaddr = dev -> base_addr;
        !          1004:   u_short val_VG, val_10;
        !          1005:   struct hp100_private *lp = (struct hp100_private *)dev -> priv;
        !          1006: 
        !          1007:   hp100_page( MAC_CTRL );
        !          1008:   hp100_orw( HP100_VG_RESET, LAN_CFG_VG );
        !          1009:   val_10 = hp100_inw( LAN_CFG_10 );
        !          1010:   val_VG = hp100_inw( LAN_CFG_VG );
        !          1011: #ifdef HP100_DEBUG_SENSE
        !          1012:   printk( "hp100_sense_lan: val_VG = 0x%04x, val_10 = 0x%04x\n", val_VG, val_10 );
        !          1013: #endif
        !          1014:   if ( val_10 & HP100_LINK_BEAT_ST ) return HP100_LAN_10;
        !          1015:   if ( lp -> id -> id == 0x02019F022 ) /* HP J27248B doesn't have 100Mb/s interface */
        !          1016:     return HP100_LAN_ERR;
        !          1017:   for ( i = 0; i < 2500; i++ )
        !          1018:     {
        !          1019:       val_VG = hp100_inw( LAN_CFG_VG );
        !          1020:       if ( val_VG & HP100_LINK_CABLE_ST ) return HP100_LAN_100;
        !          1021:     }
        !          1022:   return HP100_LAN_ERR;
        !          1023: }
        !          1024: 
        !          1025: static int hp100_down_vg_link( struct device *dev )
        !          1026: {
        !          1027:   int ioaddr = dev -> base_addr;
        !          1028:   unsigned long time;
        !          1029:   int i;
        !          1030: 
        !          1031:   hp100_page( MAC_CTRL );
        !          1032:   for ( i = 2500; i > 0; i-- )
        !          1033:     if ( hp100_inw( LAN_CFG_VG ) & HP100_LINK_CABLE_ST ) break;
        !          1034:   if ( i <= 0 )                                /* not signal - not logout */
        !          1035:     return 0;
        !          1036:   hp100_andw( ~HP100_LINK_CMD, LAN_CFG_VG );
        !          1037:   time = jiffies + 10; 
        !          1038:   while ( time > jiffies )
        !          1039:     if ( !( hp100_inw( LAN_CFG_VG ) & ( HP100_LINK_UP_ST | 
        !          1040:                                         HP100_LINK_CABLE_ST | 
        !          1041:                                         HP100_LINK_GOOD_ST ) ) )
        !          1042:       return 0;
        !          1043: #ifdef HP100_DEBUG
        !          1044:   printk( "hp100_down_vg_link: timeout\n" );
        !          1045: #endif
        !          1046:   return -EIO;
        !          1047: }
        !          1048: 
        !          1049: static int hp100_login_to_vg_hub( struct device *dev )
        !          1050: {
        !          1051:   int i;
        !          1052:   int ioaddr = dev -> base_addr;
        !          1053:   u_short val;
        !          1054:   unsigned long time;  
        !          1055: 
        !          1056:   hp100_page( MAC_CTRL );
        !          1057:   hp100_orw( HP100_VG_RESET, LAN_CFG_VG );
        !          1058:   time = jiffies + ( HZ / 2 );
        !          1059:   do {
        !          1060:     if ( hp100_inw( LAN_CFG_VG ) & HP100_LINK_CABLE_ST ) break;
        !          1061:   } while ( time > jiffies );
        !          1062:   if ( time <= jiffies )
        !          1063:     {
        !          1064: #ifdef HP100_DEBUG
        !          1065:       printk( "hp100_login_to_vg_hub: timeout for link\n" );
        !          1066: #endif
        !          1067:       return -EIO;
        !          1068:     }
        !          1069:     
        !          1070:   if ( hp100_down_vg_link( dev ) < 0 ) /* if fail, try reset VG link */
        !          1071:     {
        !          1072:       hp100_andw( ~HP100_VG_RESET, LAN_CFG_VG );
        !          1073:       hp100_orw( HP100_VG_RESET, LAN_CFG_VG );
        !          1074:     }
        !          1075:   /* bring up link */
        !          1076:   hp100_orw( HP100_LOAD_ADDR | HP100_LINK_CMD, LAN_CFG_VG );
        !          1077:   for ( i = 2500; i > 0; i-- )
        !          1078:     if ( hp100_inw( LAN_CFG_VG ) & HP100_LINK_CABLE_ST ) break;
        !          1079:   if ( i <= 0 )
        !          1080:     {
        !          1081: #ifdef HP100_DEBUG
        !          1082:       printk( "hp100_login_to_vg_hub: timeout for link (bring up)\n" );
        !          1083: #endif
        !          1084:       goto down_link;
        !          1085:     }
        !          1086: 
        !          1087:   time = jiffies + ( HZ / 2 );
        !          1088:   do {   
        !          1089:     val = hp100_inw( LAN_CFG_VG );
        !          1090:     if ( ( val & ( HP100_LINK_UP_ST | HP100_LINK_GOOD_ST ) ) == 
        !          1091:                  ( HP100_LINK_UP_ST | HP100_LINK_GOOD_ST ) )
        !          1092:       return 0;        /* success */
        !          1093:   } while ( time > jiffies );
        !          1094:   if ( val & HP100_LINK_GOOD_ST )
        !          1095:     printk( "%s: 100Mb cable training failed, check cable.\n", dev -> name );
        !          1096:    else
        !          1097:     printk( "%s: 100Mb node not accepted by hub, check frame type or security.\n", dev -> name );
        !          1098: 
        !          1099: down_link:
        !          1100:   hp100_down_vg_link( dev );
        !          1101:   hp100_page( MAC_CTRL );
        !          1102:   hp100_andw( ~( HP100_LOAD_ADDR | HP100_PROM_MODE ), LAN_CFG_VG );
        !          1103:   hp100_orw( HP100_LINK_CMD, LAN_CFG_VG );
        !          1104:   return -EIO;
        !          1105: }
        !          1106: 
        !          1107: /*
        !          1108:  *  module section
        !          1109:  */
        !          1110:  
        !          1111: #ifdef MODULE
        !          1112: 
        !          1113: static int hp100_port = -1;
        !          1114: 
        !          1115: static char devicename[9] = { 0, };
        !          1116: static struct device dev_hp100 = {
        !          1117:        devicename, /* device name is inserted by linux/drivers/net/net_init.c */
        !          1118:        0, 0, 0, 0,
        !          1119:        0, 0,
        !          1120:        0, 0, 0, NULL, hp100_probe
        !          1121: };
        !          1122: 
        !          1123: int init_module( void )
        !          1124: {
        !          1125:   if (hp100_port == 0 && !EISA_bus)
        !          1126:     printk("HP100: You should not use auto-probing with insmod!\n");
        !          1127:   if ( hp100_port > 0 )
        !          1128:     dev_hp100.base_addr = hp100_port;
        !          1129:   if ( register_netdev( &dev_hp100 ) != 0 )
        !          1130:     return -EIO;
        !          1131:   return 0;
        !          1132: }         
        !          1133: 
        !          1134: void cleanup_module( void )
        !          1135: {
        !          1136:   unregister_netdev( &dev_hp100 );
        !          1137:   release_region( dev_hp100.base_addr, HP100_REGION_SIZE );
        !          1138:   if ( ((struct hp100_private *)dev_hp100.priv) -> mem_ptr_virt )
        !          1139:     vfree( ((struct hp100_private *)dev_hp100.priv) -> mem_ptr_virt );
        !          1140:   kfree_s( dev_hp100.priv, sizeof( struct hp100_private ) );
        !          1141:   dev_hp100.priv = NULL;
        !          1142: }
        !          1143: 
        !          1144: #endif

unix.superglobalmegacorp.com

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