patch-2.0.34 linux/drivers/net/hp100.c
Next file: linux/drivers/net/lance.c
Previous file: linux/drivers/net/eth16i.c
Back to the patch index
Back to the overall index
- Lines: 663
- Date:
Wed Jun 3 15:17:47 1998
- Orig file:
v2.0.33/linux/drivers/net/hp100.c
- Orig date:
Tue Aug 5 09:11:35 1997
diff -u --recursive --new-file v2.0.33/linux/drivers/net/hp100.c linux/drivers/net/hp100.c
@@ -2,7 +2,7 @@
** hp100.c
** HP CASCADE Architecture Driver for 100VG-AnyLan Network Adapters
**
-** $Id: hp100.c,v 1.54 1997/06/12 10:37:07 perex Exp perex $
+** $Id: hp100.c,v 1.56 1998/03/04 15:23:59 perex Exp perex $
**
** Based on the HP100 driver written by Jaroslav Kysela <perex@jcu.cz>
** Extended for new busmaster capable chipsets by
@@ -17,6 +17,7 @@
** -- HP J2973 10 Mbit/s PCI 10base-T
** -- HP J2573 10/100 ISA
** -- Compex ReadyLink ENET100-VG4 10/100 Mbit/s PCI / EISA
+** -- Compex FreedomLine 100/VG 10/100 Mbit/s ISA / EISA / PCI
**
** but it should also work with the other CASCADE based adapters.
**
@@ -27,6 +28,7 @@
** - To reduce interrupt load in busmaster, one could switch off
** the interrupts that are used to refill the queues whenever the
** queues are filled up to more than a certain threshold.
+** - some updates for EISA version of card
**
**
** This source/code is public free; you can distribute it and/or modify
@@ -34,6 +36,18 @@
** Free Software Foundation) either version two of this License, or any
** later version.
**
+** 1.55 -> 1.56
+** - removed printk in misc. interrupt and update statistics to allow
+** monitoring of card status
+** - timing changes in xmit routines, relogin to 100VG hub added when
+** driver does reset
+** - included fix for Compex FreedomLine PCI adapter
+**
+** 1.54 -> 1.55
+** - fixed bad initialization in init_module
+** - added Compex FreedomLine adapter
+** - some fixes in card initialization
+**
** 1.53 -> 1.54
** - added hardware multicast filter support (doesn't work)
** - little changes in hp100_sense_lan routine
@@ -115,6 +129,12 @@
#ifndef PCI_DEVICE_ID_COMPEX_ENET100VG4
#define PCI_DEVICE_ID_COMPEX_ENET100VG4 0x0112
#endif
+#ifndef PCI_VENDOR_ID_COMPEX2
+#define PCI_VENDOR_ID_COMPEX2 0x101a
+#endif
+#ifndef PCI_DEVICE_ID_COMPEX2_100VG
+#define PCI_DEVICE_ID_COMPEX2_100VG 0x0005
+#endif
#define HP100_REGION_SIZE 0x20 /* for ioports */
@@ -141,11 +161,17 @@
u_char bus;
};
+struct hp100_pci_id {
+ u_short vendor;
+ u_short device;
+};
+
struct hp100_private {
struct hp100_eisa_id *id;
u_short chip;
u_short soft_model;
u_int memory_size;
+ u_int virt_memory_size;
u_short rx_ratio; /* 1 - 99 */
u_short priority_tx; /* != 0 - priority tx */
u_short mode; /* PIO, Shared Mem or Busmaster */
@@ -213,10 +239,35 @@
/* 10/100 EISA card from Compex */
{ 0x0103180e, "ReadyLink ENET100-VG4", HP100_BUS_EISA },
+ /* 10/100 EISA card from Compex - FreedomLine (sq5bpf) */
+ /* Note: plhbrod@mbox.vol.cz reported that same ID have ISA */
+ /* version of adapter, too... */
+ { 0x0104180e, "FreedomLine 100/VG", HP100_BUS_EISA },
+
+ /* 10/100 PCI card from Compex - FreedomLine
+ *
+ * I think this card doesn't like aic7178 scsi controller, but
+ * I haven't tested this much. It works fine on diskless machines.
+ * Jacek Lipkowski <sq5bpf@acid.ch.pw.edu.pl>
+ */
+ { 0x021211f6, "FreedomLine 100/VG", HP100_BUS_PCI },
+
/* 10/100 PCI card from Compex (J2585A compatible) */
{ 0x011211f6, "ReadyLink ENET100-VG4", HP100_BUS_PCI }
+
};
+#define HP100_EISA_IDS_SIZE (sizeof(hp100_eisa_ids)/sizeof(struct hp100_eisa_id))
+
+static struct hp100_pci_id hp100_pci_ids[] = {
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A },
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B },
+ { PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_ENET100VG4 },
+ { PCI_VENDOR_ID_COMPEX2, PCI_DEVICE_ID_COMPEX2_100VG }
+};
+
+#define HP100_PCI_IDS_SIZE (sizeof(hp100_pci_ids)/sizeof(struct hp100_pci_id))
+
static int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO;
static int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX;
static int hp100_mode = 1;
@@ -238,13 +289,14 @@
static int hp100_start_xmit_bm (struct sk_buff *skb, struct device *dev );
static void hp100_rx( struct device *dev );
static hp100_stats_t *hp100_get_stats( struct device *dev );
+static void hp100_misc_interrupt( struct device *dev );
static void hp100_update_stats( struct device *dev );
static void hp100_clear_stats( int ioaddr );
static void hp100_set_multicast_list( struct device *dev);
static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs );
static void hp100_start_interface( struct device *dev );
static void hp100_stop_interface( struct device *dev );
-static void hp100_load_eeprom( struct device *dev );
+static void hp100_load_eeprom( struct device *dev, u_short ioaddr );
static int hp100_sense_lan( struct device *dev );
static int hp100_login_to_vg_hub( struct device *dev, u_short force_relogin );
static int hp100_down_vg_link( struct device *dev );
@@ -272,7 +324,7 @@
* These functions should - if possible - avoid doing write operations
* since this could cause problems when the card is not installed.
*/
-
+
__initfunc(int hp100_probe( struct device *dev ))
{
int base_addr = dev ? dev -> base_addr : 0;
@@ -322,17 +374,16 @@
{
u_char pci_bus, pci_device_fn;
u_short pci_command;
+ int pci_id_index;
- if ((pcibios_find_device( PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A,
- pci_index, &pci_bus,
- &pci_device_fn ) != 0 ) &&
- (pcibios_find_device( PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B,
- pci_index, &pci_bus,
- &pci_device_fn ) != 0 ) &&
- (pcibios_find_device( PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_ENET100VG4,
- pci_index, &pci_bus,
- &pci_device_fn ) != 0 ) ) break;
+ for ( pci_id_index = 0; pci_id_index < HP100_PCI_IDS_SIZE; pci_id_index++ )
+ if ( pcibios_find_device( hp100_pci_ids[ pci_id_index ].vendor,
+ hp100_pci_ids[ pci_id_index ].device,
+ pci_index, &pci_bus,
+ &pci_device_fn ) == 0 ) goto __pci_found;
+ break;
+ __pci_found:
pcibios_read_config_dword( pci_bus, pci_device_fn,
PCI_BASE_ADDRESS_0, &ioaddr );
@@ -342,6 +393,15 @@
pcibios_read_config_word( pci_bus, pci_device_fn,
PCI_COMMAND, &pci_command );
+ if ( !( pci_command & PCI_COMMAND_IO ) )
+ {
+#ifdef HP100_DEBUG
+ printk( "hp100: %s: PCI I/O Bit has not been set. Setting...\n", dev->name );
+#endif
+ pci_command |= PCI_COMMAND_IO;
+ pcibios_write_config_word( pci_bus, pci_device_fn,
+ PCI_COMMAND, pci_command );
+ }
if ( !( pci_command & PCI_COMMAND_MASTER ) )
{
#ifdef HP100_DEBUG
@@ -386,7 +446,7 @@
u_char uc, uc_1;
u_int eisa_id;
u_int chip;
- u_int memory_size = 0;
+ u_int memory_size = 0, virt_memory_size = 0;
u_short local_mode, lsw;
short mem_mapped;
u_int *mem_ptr_phys, *mem_ptr_virt;
@@ -443,14 +503,18 @@
return -ENODEV;
}
- for ( i=0; i<sizeof(hp100_eisa_ids)/sizeof(struct hp100_eisa_id); i++)
- if ( ( hp100_eisa_ids[ i ].id & 0xf0ffffff ) == ( eisa_id & 0xf0ffffff ) )
+ for ( i=0; i < HP100_EISA_IDS_SIZE; i++)
+ if ( hp100_eisa_ids[ i ].id == eisa_id )
break;
- if ( i >= sizeof( hp100_eisa_ids ) / sizeof( struct hp100_eisa_id ) )
- {
+ if ( i >= HP100_EISA_IDS_SIZE ) {
+ for ( i = 0; i < HP100_EISA_IDS_SIZE; i++)
+ if ( ( hp100_eisa_ids[ i ].id & 0xf0ffffff ) == ( eisa_id & 0xf0ffffff ) )
+ break;
+ if ( i >= HP100_EISA_IDS_SIZE ) {
printk( "hp100_probe: %s: card at port 0x%x isn't known (id = 0x%x)\n", dev -> name, ioaddr, eisa_id );
- return -ENODEV;
+ return -ENODEV;
}
+ }
eid = &hp100_eisa_ids[ i ];
if ( ( eid->id & 0x0f000000 ) < ( eisa_id & 0x0f000000 ) )
{
@@ -468,7 +532,13 @@
return -EIO;
}
- /* Determine driver operation mode
+ /* Make sure, that all registers are correctly updated... */
+
+ hp100_load_eeprom( dev, ioaddr );
+ wait();
+
+ /*
+ * Determine driver operation mode
*
* Use the variable "hp100_mode" upon insmod or as kernel parameter to
* force driver modes:
@@ -478,6 +548,22 @@
* hp100_mode=4 -> same as 1, but re-set the enable bit on the card.
*/
+ /*
+ * LSW values:
+ * 0x2278 -> J2585B, PnP shared memory mode
+ * 0x2270 -> J2585B, shared memory mode, 0xdc000
+ * 0xa23c -> J2585B, I/O mapped mode
+ * 0x2240 -> EISA COMPEX, BusMaster (Shasta Chip)
+ * 0x2220 -> EISA HP, I/O (Shasta Chip)
+ * 0x2260 -> EISA HP, BusMaster (Shasta Chip)
+ */
+
+#if 0
+ local_mode = 0x2270;
+ hp100_outw(0xfefe,OPTION_LSW);
+ hp100_outw(local_mode|HP100_SET_LB|HP100_SET_HB,OPTION_LSW);
+#endif
+
/* hp100_mode value maybe used in future by another card */
local_mode=hp100_mode;
if ( local_mode < 1 || local_mode > 4 )
@@ -536,7 +622,8 @@
else
{
#ifdef HP100_DEBUG
- printk("hp100: %s: Card not configured for BM or BM not supported with this card. Trying shared memory mode.\n", dev->name);
+ printk("hp100: %s: Card not configured for BM or BM not supported with this card.\n", dev->name );
+ printk("hp100: %s: Trying shared memory mode.\n", dev->name);
#endif
/* In this case, try shared memory mode */
local_mode=2;
@@ -554,6 +641,7 @@
mem_mapped = (( hp100_inw( OPTION_LSW ) & ( HP100_MEM_EN ) ) != 0);
mem_ptr_phys = mem_ptr_virt = NULL;
memory_size = (8192<<( (hp100_inb(SRAM)>>5)&0x07));
+ virt_memory_size = 0;
/* For memory mapped or busmaster mode, we want the memory address */
if ( mem_mapped || (local_mode==1))
@@ -574,21 +662,21 @@
/* However in slave mode we need to remap high (>1GB) card memory */
if(local_mode!=1) /* = not busmaster */
{
- if ( bus == HP100_BUS_PCI )
+ if ( bus == HP100_BUS_PCI && mem_ptr_phys >= (u_int *)0x100000 )
{
/* We try with smaller memory sizes, if ioremap fails */
- for(; memory_size>16383; memory_size=memory_size/2)
+ for(virt_memory_size = memory_size; virt_memory_size>16383; virt_memory_size>>=1)
{
- if((mem_ptr_virt=ioremap((u_long)mem_ptr_phys,memory_size))==NULL)
+ if((mem_ptr_virt=ioremap((u_long)mem_ptr_phys,virt_memory_size))==NULL)
{
#ifdef HP100_DEBUG
- printk( "hp100: %s: ioremap for 0x%x bytes high PCI memory at 0x%lx failed\n", dev->name, memory_size, (u_long)mem_ptr_phys );
+ printk( "hp100: %s: ioremap for 0x%x bytes high PCI memory at 0x%lx failed\n", dev->name, virt_memory_size, (u_long)mem_ptr_phys );
#endif
}
else
{
#ifdef HP100_DEBUG
- printk( "hp100: %s: remapped 0x%x bytes high PCI memory at 0x%lx to 0x%lx.\n", dev->name, memory_size, (u_long)mem_ptr_phys, (u_long)mem_ptr_virt);
+ printk( "hp100: %s: remapped 0x%x bytes high PCI memory at 0x%lx to 0x%lx.\n", dev->name, virt_memory_size, (u_long)mem_ptr_phys, (u_long)mem_ptr_virt);
#endif
break;
}
@@ -598,7 +686,7 @@
{
printk("hp100: %s: Failed to ioremap the PCI card memory. Will have to use i/o mapped mode.\n", dev->name);
local_mode=3;
- memory_size = (8192<<( (hp100_inb(SRAM)>>5)&0x07) );
+ virt_memory_size = 0;
}
}
}
@@ -637,6 +725,7 @@
dev->base_addr = ioaddr;
lp->memory_size = memory_size;
+ lp->virt_memory_size = virt_memory_size;
lp->rx_ratio = hp100_rx_ratio; /* can be conf'd with insmod */
/* memory region for programmed i/o */
@@ -724,7 +813,8 @@
if ( lp->mode==2 ) /* memory mapped */
{
printk( "hp100: %s: Memory area at 0x%lx-0x%lx",
- dev->name,(u_long)mem_ptr_phys,(u_long)mem_ptr_phys+(u_long)lp->memory_size );
+ dev->name,(u_long)mem_ptr_phys,
+ ((u_long)mem_ptr_phys+(mem_ptr_phys>(u_int *)0x100000?(u_long)lp->memory_size:16*1024))-1 );
if ( mem_ptr_virt )
printk( " (virtual base 0x%lx)", (u_long)mem_ptr_virt );
printk( ".\n" );
@@ -786,7 +876,7 @@
}
/* Initiate EEPROM reload */
- hp100_load_eeprom( dev );
+ hp100_load_eeprom( dev, 0 );
wait();
@@ -1447,6 +1537,7 @@
/* tx function for busmaster mode */
static int hp100_start_xmit_bm( struct sk_buff *skb, struct device *dev )
{
+ unsigned long flags;
int i, ok_flag;
int ioaddr = dev->base_addr;
struct hp100_private *lp = (struct hp100_private *)dev->priv;
@@ -1459,7 +1550,9 @@
if ( skb==NULL )
{
+#ifndef LINUX_2_1
dev_tint( dev );
+#endif
return 0;
}
@@ -1473,7 +1566,7 @@
printk("hp100: %s: start_xmit_bm: No TX PDL available.\n", dev->name);
#endif
/* not waited long enough since last tx? */
- if ( jiffies - dev->trans_start < HZ/10 ) return -EAGAIN;
+ if ( jiffies - dev->trans_start < HZ ) return -EAGAIN;
if ( lp->lan_type < 0 ) /* no LAN type detected yet? */
{
@@ -1519,6 +1612,8 @@
{
printk( "hp100: %s: interface reset\n", dev->name );
hp100_stop_interface( dev );
+ if ( lp->lan_type == HP100_LAN_100 )
+ lp->hub_status = hp100_login_to_vg_hub( dev, FALSE );
hp100_start_interface( dev );
}
}
@@ -1531,6 +1626,7 @@
* we have to turn int's off before modifying this, otherwise
* a tx_pdl_cleanup could occur at the same time
*/
+ save_flags( flags );
cli();
ringptr=lp->txrtail;
lp->txrtail=ringptr->next;
@@ -1557,7 +1653,7 @@
hp100_outl( ringptr->pdl_paddr, TX_PDA_L ); /* Low Prio. Queue */
lp->txrcommit++;
- sti();
+ restore_flags( flags );
/* Update statistics */
lp->stats.tx_packets++;
@@ -1606,7 +1702,11 @@
hp100_inb(TX_PDL),
donecount);
#endif
+#ifdef LINUX_2_1
+ dev_kfree_skb( lp->txrhead->skb );
+#else
dev_kfree_skb( lp->txrhead->skb, FREE_WRITE );
+#endif
lp->txrhead->skb=(void *)NULL;
lp->txrhead=lp->txrhead->next;
lp->txrcommit--;
@@ -1627,6 +1727,16 @@
printk("hp100: %s: start_xmit\n", dev->name);
#endif
+ if ( skb==NULL )
+ {
+#ifndef LINUX_2_1
+ dev_tint( dev );
+#endif
+ return 0;
+ }
+
+ if ( skb->len <= 0 ) return 0;
+
if ( lp->lan_type < 0 ) /* no LAN type detected yet? */
{
hp100_stop_interface( dev );
@@ -1649,7 +1759,7 @@
printk( "hp100: %s: start_xmit: tx free mem = 0x%x\n", dev->name, i );
#endif
/* not waited long enough since last failed tx try? */
- if ( jiffies - dev->trans_start < HZ/2 )
+ if ( jiffies - dev->trans_start < HZ )
{
#ifdef HP100_DEBUG
printk("hp100: %s: trans_start timing problem\n", dev->name);
@@ -1686,6 +1796,8 @@
{
printk( "hp100: %s: interface reset\n", dev->name );
hp100_stop_interface( dev );
+ if ( lp->lan_type == HP100_LAN_100 )
+ lp->hub_status = hp100_login_to_vg_hub( dev, FALSE );
hp100_start_interface( dev );
udelay(1000);
}
@@ -1721,13 +1833,14 @@
if ( lp->mem_ptr_virt ) /* high pci memory was remapped */
{
/* Note: The J2585B needs alignment to 32bits here! */
- memcpy( lp->mem_ptr_virt, skb->data, ( skb->len +3 ) & ~3 );
+ memcpy( lp->mem_ptr_virt, skb->data, ( skb->len + 3 ) & ~3 );
if ( !ok_flag )
memset( lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len );
}
else
{
- memcpy_toio( lp->mem_ptr_phys, skb->data, skb->len );
+ /* Note: The J2585B needs alignment to 32bits here! */
+ memcpy_toio( lp->mem_ptr_phys, skb->data, (skb->len + 3) & ~3 );
if ( !ok_flag )
memset_io( lp->mem_ptr_phys, 0, HP100_MIN_PACKET_SIZE - skb->len );
}
@@ -1749,7 +1862,11 @@
dev->trans_start=jiffies;
hp100_ints_on();
+#ifdef LINUX_2_1
+ dev_kfree_skb( skb );
+#else
dev_kfree_skb( skb, FREE_WRITE );
+#endif
#ifdef HP100_DEBUG_TX
printk( "hp100: %s: start_xmit: end\n", dev->name );
@@ -1814,7 +1931,7 @@
else /* programmed i/o */
header = hp100_inl( DATA32 );
- pkt_len = header & HP100_PKT_LEN_MASK;
+ pkt_len = ((header & HP100_PKT_LEN_MASK) + 3) & ~3;
#ifdef HP100_DEBUG_RX
printk( "hp100: %s: rx: new packet - length=%d, errors=0x%x, dest=0x%x\n",
@@ -1824,10 +1941,6 @@
#endif
/* Now we allocate the skb and transfer the data into it. */
- /* NOTE! This (and the skb_put() below) depends on the skb-functions
- * allocating more than asked (notably, aligning the request up to
- * the next 16-byte length).
- */
skb = dev_alloc_skb( pkt_len );
if ( skb == NULL ) /* Not enough memory->drop packet */
{
@@ -1849,13 +1962,13 @@
if ( lp->mode==2 )
{
if ( lp->mem_ptr_virt )
- memcpy( ptr, lp->mem_ptr_virt, ( pkt_len + 3 ) & ~3 );
+ memcpy( ptr, lp->mem_ptr_virt, pkt_len );
/* Note alignment to 32bit transfers */
else
- memcpy_fromio( ptr, lp->mem_ptr_phys, ( pkt_len + 3 ) & ~3 );
+ memcpy_fromio( ptr, lp->mem_ptr_phys, pkt_len );
}
else /* io mapped */
- insl( ioaddr + HP100_REG_DATA32, ptr, ( pkt_len + 3 ) >> 2 );
+ insl( ioaddr + HP100_REG_DATA32, ptr, pkt_len >> 2 );
skb->protocol = eth_type_trans( skb, dev );
@@ -1987,7 +2100,11 @@
printk("hp100: %s: rx_bm: Received bad packet (length=%d)\n",dev->name,pkt_len);
#endif
if(ptr->skb!=NULL)
+#ifdef LINUX_2_1
+ dev_kfree_skb( ptr->skb );
+#else
dev_kfree_skb( ptr->skb, FREE_READ );
+#endif
lp->stats.rx_errors++;
}
@@ -2055,20 +2172,37 @@
hp100_page( PERFORMANCE );
}
+static void hp100_misc_interrupt( struct device *dev )
+{
+ struct hp100_private *lp = (struct hp100_private *)dev->priv;
+
+#ifdef HP100_DEBUG_B
+ hp100_outw( 0x4216, TRACE );
+ printk("hp100: %s: misc_interrupt\n", dev->name);
+#endif
+
+ /* Note: Statistics counters clear when read. */
+ lp->stats.rx_errors++;
+ lp->stats.tx_errors++;
+}
+
static void hp100_clear_stats( int ioaddr )
{
+ unsigned long flags;
+
#ifdef HP100_DEBUG_B
hp100_outw( 0x4217, TRACE );
printk("hp100: %s: clear_stats\n", dev->name);
#endif
+ save_flags( flags );
cli();
hp100_page( MAC_CTRL ); /* get all statistics bytes */
hp100_inw( DROPPED );
hp100_inb( CRC );
hp100_inb( ABORT );
hp100_page( PERFORMANCE );
- sti();
+ restore_flags( flags );
}
@@ -2080,8 +2214,9 @@
* Set or clear the multicast filter for this adapter.
*/
-static void hp100_set_multicast_list( struct device *dev)
+static void hp100_set_multicast_list( struct device *dev )
{
+ unsigned long flags;
int ioaddr = dev->base_addr;
struct hp100_private *lp = (struct hp100_private *)dev->priv;
@@ -2090,6 +2225,7 @@
printk("hp100: %s: set_mc_list\n", dev->name);
#endif
+ save_flags( flags );
cli();
hp100_ints_off();
hp100_page( MAC_CTRL );
@@ -2223,7 +2359,7 @@
hp100_page( PERFORMANCE );
hp100_ints_on();
- sti();
+ restore_flags( flags );
}
@@ -2354,12 +2490,15 @@
*/
if ( val & HP100_MISC_ERROR ) /* New for J2585B */
{
+#ifdef HP100_DEBUG_IRQ
printk("hp100: %s: Misc. Error Interrupt - Check cabling.\n", dev->name);
+#endif
if(lp->mode==1)
{
hp100_clean_txring( dev );
hp100_rxfill( dev );
}
+ hp100_misc_interrupt( dev );
}
dev->interrupt = 0;
@@ -2373,6 +2512,7 @@
static void hp100_start_interface( struct device *dev )
{
+ unsigned long flags;
int ioaddr = dev->base_addr;
struct hp100_private *lp = (struct hp100_private *)dev->priv;
@@ -2381,6 +2521,7 @@
printk("hp100: %s: hp100_start_interface\n",dev->name);
#endif
+ save_flags( flags );
cli();
/* Ensure the adapter does not want to request an interrupt when */
@@ -2430,8 +2571,9 @@
}
/* Enable MAC Tx and RX, set MAC modes, ... */
- /* Note: This function also turns on the interrupts. */
hp100_set_multicast_list( dev );
+
+ restore_flags( flags );
}
@@ -2473,10 +2615,10 @@
}
-static void hp100_load_eeprom( struct device *dev )
+static void hp100_load_eeprom( struct device *dev, u_short probe_ioaddr )
{
int i;
- int ioaddr = dev->base_addr;
+ int ioaddr = probe_ioaddr > 0 ? probe_ioaddr : dev->base_addr;
#ifdef HP100_DEBUG_B
hp100_outw( 0x4222, TRACE );
@@ -2915,14 +3057,13 @@
int init_module( void )
{
- int i;
- int ret = 0;
+ int i, cards;
if (hp100_port == 0 && !EISA_bus && !pcibios_present())
printk("hp100: You should not use auto-probing with insmod!\n");
/* Loop on all possible base addresses */
- i = -1;
+ i = -1; cards = 0;
while((hp100_port[++i] != -1) && (i < 5))
{
/* Create device and set basics args */
@@ -2939,11 +3080,12 @@
/* Note: if dev->priv is mallocated, there is no way to fail */
kfree_s(hp100_devlist[i], sizeof(struct device));
hp100_devlist[i] = (struct device *) NULL;
- ret = -EIO;
}
+ else
+ cards++;
} /* Loop over all devices */
- return ret;
+ return cards > 0 ? 0 : -ENODEV;
}
void cleanup_module( void )
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov