|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.