Commit 1d07e29e authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (20/42) hp100-T10

NE44-hp100
	* convert to dynamic allocation
	* use device model for PCI and EISA
	* use pci id's to find PCI devices
	* fix missing id's for 10 Mbit only PCI boards
parent 50b94f1d
......@@ -41,7 +41,7 @@
*/
extern int ne2_probe(struct net_device *dev);
extern int hp100_probe(struct net_device *dev);
extern struct net_device *hp100_probe(int unit);
extern struct net_device *ultra_probe(int unit);
extern int ultra32_probe(struct net_device *dev);
extern struct net_device *wd_probe(int unit);
......@@ -197,14 +197,10 @@ static struct devprobe mca_probes[] __initdata = {
* ISA probes that touch addresses < 0x400 (including those that also
* look for EISA/PCI/MCA cards in addition to ISA cards).
*/
static struct devprobe isa_probes[] __initdata = {
static struct devprobe2 isa_probes2[] __initdata = {
#ifdef CONFIG_HP100 /* ISA, EISA & PCI */
{hp100_probe, 0},
#endif
{NULL, 0},
};
static struct devprobe2 isa_probes2[] __initdata = {
#ifdef CONFIG_3C515
{tc515_probe, 0},
#endif
......@@ -382,8 +378,7 @@ static int __init ethif_probe(int unit)
if (probe_list(dev, m68k_probes) == 0 ||
probe_list(dev, mips_probes) == 0 ||
probe_list(dev, eisa_probes) == 0 ||
probe_list(dev, mca_probes) == 0 ||
probe_list(dev, isa_probes) == 0)
probe_list(dev, mca_probes) == 0)
err = register_netdev(dev);
if (err)
......
......@@ -118,8 +118,6 @@
#include <asm/bitops.h>
#include <asm/io.h>
typedef struct net_device_stats hp100_stats_t;
#include "hp100.h"
/*
......@@ -130,23 +128,8 @@ typedef struct net_device_stats hp100_stats_t;
#define HP100_BUS_EISA 1
#define HP100_BUS_PCI 2
#ifndef PCI_DEVICE_ID_HP_J2585B
#define PCI_DEVICE_ID_HP_J2585B 0x1031
#endif
#ifndef PCI_VENDOR_ID_COMPEX
#define PCI_VENDOR_ID_COMPEX 0x11f6
#endif
#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 */
#define HP100_SIG_LEN 8 /* same as EISA_SIG_LEN */
#define HP100_MAX_PACKET_SIZE (1536+4)
#define HP100_MIN_PACKET_SIZE 60
......@@ -165,20 +148,9 @@ typedef struct net_device_stats hp100_stats_t;
* structures
*/
struct hp100_eisa_id {
u_int id;
const char *name;
u_char bus;
};
struct hp100_pci_id {
u_short vendor;
u_short device;
};
struct hp100_private {
struct hp100_eisa_id *id;
spinlock_t lock;
char id[HP100_SIG_LEN];
u_short chip;
u_short soft_model;
u_int memory_size;
......@@ -196,7 +168,7 @@ struct hp100_private {
u_char mac1_mode;
u_char mac2_mode;
u_char hash_bytes[8];
hp100_stats_t stats;
struct net_device_stats stats;
/* Rings for busmaster mode: */
hp100_ring_t *rxrhead; /* Head (oldest) index into rxring */
......@@ -216,83 +188,36 @@ struct hp100_private {
/*
* variables
*/
static struct hp100_eisa_id hp100_eisa_ids[] = {
/* 10/100 EISA card with revision A Cascade chip */
{0x80F1F022, "HP J2577 rev A", HP100_BUS_EISA},
/* 10/100 ISA card with revision A Cascade chip */
{0x50F1F022, "HP J2573 rev A", HP100_BUS_ISA},
/* 10 only EISA card with Cascade chip */
{0x2019F022, "HP 27248B", HP100_BUS_EISA},
/* 10/100 EISA card with Cascade chip */
{0x4019F022, "HP J2577", HP100_BUS_EISA},
/* 10/100 ISA card with Cascade chip */
{0x5019F022, "HP J2573", HP100_BUS_ISA},
/* 10/100 EISA card with AT&T chip */
{0x9019f022, "HP J2577", HP100_BUS_EISA },
/* 10/100 PCI card - old J2585A */
{0x1030103c, "HP J2585A", HP100_BUS_PCI},
/* 10/100 PCI card - new J2585B - master capable */
{0x1041103c, "HP J2585B", HP100_BUS_PCI},
/* 10 Mbit Combo Adapter */
{0x1042103c, "HP J2970", HP100_BUS_PCI},
/* 10 Mbit 10baseT Adapter */
{0x1040103c, "HP J2973", HP100_BUS_PCI},
/* 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},
/* 10/100 PCI card from KTI */
{0x40008e2e, "KTI DP-200", HP100_BUS_PCI }
static const char *hp100_isa_tbl[] = {
"HWPF150", /* HP J2573 rev A */
"HWP1950", /* HP J2573 */
};
#define HP100_EISA_IDS_SIZE (sizeof(hp100_eisa_ids)/sizeof(struct hp100_eisa_id))
#ifdef CONFIG_PCI
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}
#ifdef CONFIG_EISA
static struct eisa_device_id hp100_eisa_tbl[] = {
{ "HWPF180" }, /* HP J2577 rev A */
{ "HWP1920" }, /* HP 27248B */
{ "HWP1940" }, /* HP J2577 */
{ "HWP1990" }, /* HP J2577 */
{ "CPX0301" }, /* ReadyLink ENET100-VG4 */
{ "CPX0401" }, /* FreedomLine 100/VG */
};
MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl);
#endif
#define HP100_PCI_IDS_SIZE (sizeof(hp100_pci_ids)/sizeof(struct hp100_pci_id))
#ifdef CONFIG_PCI
static struct pci_device_id hp100_pci_tbl[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID,},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID,},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2970A, PCI_ANY_ID, PCI_ANY_ID,},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2973A, PCI_ANY_ID, PCI_ANY_ID,},
{PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_ENET100VG4, PCI_ANY_ID, PCI_ANY_ID,},
{PCI_VENDOR_ID_COMPEX2, PCI_DEVICE_ID_COMPEX2_100VG, PCI_ANY_ID, PCI_ANY_ID,},
/* {PCI_VENDOR_ID_KTI, PCI_DEVICE_ID_KTI_DP200, PCI_ANY_ID, PCI_ANY_ID }, */
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, hp100_pci_tbl);
#endif
static int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO;
static int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX;
......@@ -316,7 +241,7 @@ static int hp100_start_xmit(struct sk_buff *skb, struct net_device *dev);
static int hp100_start_xmit_bm(struct sk_buff *skb,
struct net_device *dev);
static void hp100_rx(struct net_device *dev);
static hp100_stats_t *hp100_get_stats(struct net_device *dev);
static struct net_device_stats *hp100_get_stats(struct net_device *dev);
static void hp100_misc_interrupt(struct net_device *dev);
static void hp100_update_stats(struct net_device *dev);
static void hp100_clear_stats(struct hp100_private *lp, int ioaddr);
......@@ -370,196 +295,180 @@ static void wait(void)
* since this could cause problems when the card is not installed.
*/
int __init hp100_probe(struct net_device *dev)
/*
* Read board id and convert to string.
* Effectively same code as decode_eisa_sig
*/
static __init const char *hp100_read_id(int ioaddr)
{
int base_addr = dev ? dev->base_addr : 0;
int ioaddr = 0;
int pci_start_index = 0;
int i;
static char str[HP100_SIG_LEN];
unsigned char sig[4], sum;
unsigned short rev;
#ifdef HP100_DEBUG_B
hp100_outw(0x4200, TRACE);
printk("hp100: %s: probe\n", dev->name);
#endif
hp100_page(ID_MAC_ADDR);
sum = 0;
for (i = 0; i < 4; i++) {
sig[i] = hp100_inb(BOARD_ID + i);
sum += sig[i];
}
if (base_addr > 0xff) { /* Check a single specified location. */
if (check_region(base_addr, HP100_REGION_SIZE))
return -EINVAL;
if (base_addr < 0x400)
return hp100_probe1(dev, base_addr, HP100_BUS_ISA,
NULL);
if (EISA_bus && base_addr >= 0x1c38 && ((base_addr - 0x1c38) & 0x3ff) == 0)
return hp100_probe1(dev, base_addr, HP100_BUS_EISA, NULL);
#ifdef CONFIG_PCI
printk("hp100: %s: You must specify card # in i/o address parameter for PCI bus...", dev->name);
#else
return -ENODEV;
#endif
} else
#ifdef CONFIG_PCI
if (base_addr > 0 && base_addr < 8 + 1)
pci_start_index = 0x100 | (base_addr - 1);
else
#endif
if (base_addr != 0)
return -ENXIO;
sum += hp100_inb(BOARD_ID + i);
if (sum != 0xff)
return NULL; /* bad checksum */
/* First: scan PCI bus(es) */
str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1);
str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1);
str[2] = (sig[1] & 0x1f) + ('A' - 1);
rev = (sig[2] << 8) | sig[3];
sprintf(str + 3, "%04X", rev);
return str;
}
static __init int hp100_isa_probe1(struct net_device *dev, int addr)
{
const char *sig;
int i;
if (!request_region(addr, HP100_REGION_SIZE, "hp100"))
goto err;
sig = hp100_read_id(addr);
release_region(addr, HP100_REGION_SIZE);
if (sig == NULL)
goto err;
for (i = 0; i < ARRAY_SIZE(hp100_isa_tbl); i++) {
if (!strcmp(hp100_isa_tbl[i], sig))
break;
#ifdef CONFIG_PCI
{
int pci_index;
struct pci_dev *pci_dev = NULL;
int pci_id_index;
u_short pci_command;
#ifdef HP100_DEBUG_PCI
printk("hp100: %s: PCI BIOS is present, checking for devices..\n", dev->name);
#endif
pci_index = 0;
for (pci_id_index = 0; pci_id_index < HP100_PCI_IDS_SIZE;
pci_id_index++) {
while ((pci_dev = pci_find_device(hp100_pci_ids[pci_id_index].vendor,
hp100_pci_ids[pci_id_index].device,
pci_dev)) != NULL) {
if (pci_index < (pci_start_index & 7)) {
pci_index++;
continue;
}
if (pci_enable_device(pci_dev))
continue;
/* found... */
ioaddr = pci_resource_start(pci_dev, 0);
if (check_region(ioaddr, HP100_REGION_SIZE))
continue;
pci_read_config_word(pci_dev, 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;
pci_write_config_word(pci_dev, PCI_COMMAND, pci_command);
}
if (!(pci_command & PCI_COMMAND_MASTER)) {
#ifdef HP100_DEBUG
printk("hp100: %s: PCI Master Bit has not been set. Setting...\n", dev->name);
#endif
pci_command |= PCI_COMMAND_MASTER;
pci_write_config_word(pci_dev, PCI_COMMAND, pci_command);
}
#ifdef HP100_DEBUG
printk("hp100: %s: PCI adapter found at 0x%x\n", dev->name, ioaddr);
#endif
if (hp100_probe1(dev, ioaddr, HP100_BUS_PCI, pci_dev) == 0)
return 0;
}
}
}
if (pci_start_index > 0)
return -ENODEV;
#endif /* CONFIG_PCI */
/* Second: Probe all EISA possible port regions (if EISA bus present) */
for (ioaddr = 0x1c38; EISA_bus && ioaddr < 0x10000; ioaddr += 0x400) {
if (check_region(ioaddr, HP100_REGION_SIZE))
continue;
if (hp100_probe1(dev, ioaddr, HP100_BUS_EISA, NULL) == 0)
return 0;
if (i < ARRAY_SIZE(hp100_isa_tbl))
return hp100_probe1(dev, addr, HP100_BUS_ISA, NULL);
err:
return -ENODEV;
}
/*
* Probe for ISA board.
* EISA and PCI are handled by device infrastructure.
*/
static int __init hp100_isa_probe(struct net_device *dev, int addr)
{
int err = -ENODEV;
/* Probe for a specific ISA address */
if (addr > 0xff && addr < 0x400)
err = hp100_isa_probe1(dev, addr);
else if (addr != 0)
err = -ENXIO;
else {
/* Probe all ISA possible port regions */
for (addr = 0x100; addr < 0x400; addr += 0x20) {
err = hp100_isa_probe1(dev, addr);
if (!err)
break;
}
}
return err;
}
/* Third: Probe all ISA possible port regions */
for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) {
if (check_region(ioaddr, HP100_REGION_SIZE))
continue;
if (hp100_probe1(dev, ioaddr, HP100_BUS_ISA, NULL) == 0)
return 0;
struct net_device * __init hp100_probe(int unit)
{
struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private));
int err;
if (!dev)
return ERR_PTR(-ENODEV);
SET_MODULE_OWNER(dev);
#ifdef HP100_DEBUG_B
hp100_outw(0x4200, TRACE);
printk("hp100: %s: probe\n", dev->name);
#endif
if (unit >= 0) {
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
}
return -ENODEV;
err = hp100_isa_probe(dev, dev->base_addr);
if (err)
goto out;
err = register_netdev(dev);
if (err)
goto out1;
return dev;
out1:
release_region(dev->base_addr, HP100_REGION_SIZE);
out:
free_netdev(dev);
return ERR_PTR(err);
}
static int __init hp100_probe1(struct net_device *dev, int ioaddr,
u_char bus, struct pci_dev *pci_dev)
{
int i;
u_char uc, uc_1;
u_int eisa_id;
int err = -ENODEV;
const char *eid;
u_int chip;
u_char uc;
u_int memory_size = 0, virt_memory_size = 0;
u_short local_mode, lsw;
short mem_mapped;
unsigned long mem_ptr_phys;
void **mem_ptr_virt;
struct hp100_private *lp;
struct hp100_eisa_id *eid;
#ifdef HP100_DEBUG_B
hp100_outw(0x4201, TRACE);
printk("hp100: %s: probe1\n", dev->name);
#endif
if (dev == NULL) {
#ifdef HP100_DEBUG
printk("hp100_probe1: %s: dev == NULL ?\n", dev->name);
#endif
return -EIO;
}
/* memory region for programmed i/o */
if (!request_region(ioaddr, HP100_REGION_SIZE, "hp100"))
goto out1;
if (hp100_inw(HW_ID) != HP100_HW_ID_CASCADE) {
return -ENODEV;
} else {
chip = hp100_inw(PAGING) & HP100_CHIPID_MASK;
if (hp100_inw(HW_ID) != HP100_HW_ID_CASCADE)
goto out2;
chip = hp100_inw(PAGING) & HP100_CHIPID_MASK;
#ifdef HP100_DEBUG
if (chip == HP100_CHIPID_SHASTA)
printk("hp100: %s: Shasta Chip detected. (This is a pre 802.12 chip)\n", dev->name);
else if (chip == HP100_CHIPID_RAINIER)
printk("hp100: %s: Rainier Chip detected. (This is a pre 802.12 chip)\n", dev->name);
else if (chip == HP100_CHIPID_LASSEN)
printk("hp100: %s: Lassen Chip detected.\n", dev->name);
else
printk("hp100: %s: Warning: Unknown CASCADE chip (id=0x%.4x).\n", dev->name, chip);
if (chip == HP100_CHIPID_SHASTA)
printk("hp100: %s: Shasta Chip detected. (This is a pre 802.12 chip)\n", dev->name);
else if (chip == HP100_CHIPID_RAINIER)
printk("hp100: %s: Rainier Chip detected. (This is a pre 802.12 chip)\n", dev->name);
else if (chip == HP100_CHIPID_LASSEN)
printk("hp100: %s: Lassen Chip detected.\n", dev->name);
else
printk("hp100: %s: Warning: Unknown CASCADE chip (id=0x%.4x).\n", dev->name, chip);
#endif
}
dev->base_addr = ioaddr;
hp100_page(ID_MAC_ADDR);
for (i = uc = eisa_id = 0; i < 4; i++) {
eisa_id >>= 8;
uc_1 = hp100_inb(BOARD_ID + i);
eisa_id |= uc_1 << 24;
uc += uc_1;
}
uc += hp100_inb(BOARD_ID + 4);
if (uc != 0xff) { /* bad checksum? */
printk("hp100_probe: %s: bad EISA ID checksum at base port 0x%x\n", dev->name, ioaddr);
return -ENODEV;
}
for (i = 0; i < HP100_EISA_IDS_SIZE; i++)
if (hp100_eisa_ids[i].id == eisa_id)
break;
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;
}
}
eid = &hp100_eisa_ids[i];
if ((eid->id & 0x0f000000) < (eisa_id & 0x0f000000)) {
printk("hp100_probe: %s: newer version of card %s at port 0x%x - unsupported\n", dev->name, eid->name, ioaddr);
return -ENODEV;
eid = hp100_read_id(ioaddr);
if (eid == NULL) { /* bad checksum? */
printk(KERN_WARNING "hp100_probe: bad ID checksum at base port 0x%x\n", ioaddr);
goto out2;
}
hp100_page(ID_MAC_ADDR);
for (i = uc = 0; i < 7; i++)
uc += hp100_inb(LAN_ADDR + i);
if (uc != 0xff) {
printk("hp100_probe: %s: bad lan address checksum (card %s at port 0x%x)\n", dev->name, eid->name, ioaddr);
return -EIO;
printk(KERN_WARNING "hp100_probe: bad lan address checksum at port 0x%x)\n", ioaddr);
err = -EIO;
goto out2;
}
/* Make sure, that all registers are correctly updated... */
......@@ -607,17 +516,17 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
hp100_outw(HP100_MEM_EN | HP100_RESET_LB, OPTION_LSW);
hp100_outw(HP100_IO_EN | HP100_SET_LB, OPTION_LSW);
hp100_outw(HP100_BM_WRITE | HP100_BM_READ | HP100_RESET_HB, OPTION_LSW);
printk("hp100: %s: IO mapped mode forced.\n", dev->name);
printk("hp100: IO mapped mode forced.\n");
} else if (local_mode == 2) {
hp100_outw(HP100_MEM_EN | HP100_SET_LB, OPTION_LSW);
hp100_outw(HP100_IO_EN | HP100_SET_LB, OPTION_LSW);
hp100_outw(HP100_BM_WRITE | HP100_BM_READ | HP100_RESET_HB, OPTION_LSW);
printk("hp100: %s: Shared memory mode requested.\n", dev->name);
printk("hp100: Shared memory mode requested.\n");
} else if (local_mode == 4) {
if (chip == HP100_CHIPID_LASSEN) {
hp100_outw(HP100_BM_WRITE | HP100_BM_READ | HP100_SET_HB, OPTION_LSW);
hp100_outw(HP100_IO_EN | HP100_MEM_EN | HP100_RESET_LB, OPTION_LSW);
printk("hp100: %s: Busmaster mode requested.\n", dev->name);
printk("hp100: Busmaster mode requested.\n");
}
local_mode = 1;
}
......@@ -643,7 +552,7 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
/* Gracefully fallback to shared memory */
goto busmasterfail;
}
printk("hp100: %s: Busmaster mode enabled.\n", dev->name);
printk("hp100: Busmaster mode enabled.\n");
hp100_outw(HP100_MEM_EN | HP100_IO_EN | HP100_RESET_LB, OPTION_LSW);
} else {
busmasterfail:
......@@ -675,7 +584,7 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
mem_ptr_phys &= ~0x1fff; /* 8k alignment */
if (bus == HP100_BUS_ISA && (mem_ptr_phys & ~0xfffff) != 0) {
printk("hp100: %s: Can only use programmed i/o mode.\n", dev->name);
printk("hp100: Can only use programmed i/o mode.\n");
mem_ptr_phys = 0;
mem_mapped = 0;
local_mode = 3; /* Use programmed i/o */
......@@ -699,7 +608,7 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
}
if (mem_ptr_virt == NULL) { /* all ioremap tries failed */
printk("hp100: %s: Failed to ioremap the PCI card memory. Will have to use i/o mapped mode.\n", dev->name);
printk("hp100: Failed to ioremap the PCI card memory. Will have to use i/o mapped mode.\n");
local_mode = 3;
virt_memory_size = 0;
}
......@@ -710,17 +619,14 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
mem_mapped = 0;
mem_ptr_phys = 0;
mem_ptr_virt = NULL;
printk("hp100: %s: Using (slow) programmed i/o mode.\n", dev->name);
printk("hp100: Using (slow) programmed i/o mode.\n");
}
/* Initialise the "private" data structure for this card. */
if ((dev->priv = kmalloc(sizeof(struct hp100_private), GFP_KERNEL)) == NULL)
return -ENOMEM;
lp = (struct hp100_private *) dev->priv;
memset(lp, 0, sizeof(struct hp100_private));
spin_lock_init(&lp->lock);
lp->id = eid;
strlcpy(lp->id, eid, HP100_SIG_LEN);
lp->chip = chip;
lp->mode = local_mode;
lp->bus = bus;
......@@ -741,9 +647,6 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
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 */
request_region(dev->base_addr, HP100_REGION_SIZE, eid->name);
dev->open = hp100_open;
dev->stop = hp100_close;
......@@ -776,10 +679,6 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
/* Reset statistics (counters) */
hp100_clear_stats(lp, ioaddr);
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pci_dev->dev);
ether_setup(dev);
/* If busmaster mode is wanted, a dma-capable memory area is needed for
* the rx and tx PDLs
* PCI cards can access the whole PC memory. Therefore GFP_DMA is not
......@@ -795,8 +694,10 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
/* Conversion to new PCI API :
* Pages are always aligned and zeroed, no need to it ourself.
* Doc says should be OK for EISA bus as well - Jean II */
if ((lp->page_vaddr_algn = pci_alloc_consistent(lp->pci_dev, MAX_RINGSIZE, &page_baddr)) == NULL)
return -ENOMEM;
if ((lp->page_vaddr_algn = pci_alloc_consistent(lp->pci_dev, MAX_RINGSIZE, &page_baddr)) == NULL) {
err = -ENOMEM;
goto out2;
}
lp->whatever_offset = ((u_long) page_baddr) - ((u_long) lp->page_vaddr_algn);
#ifdef HP100_DEBUG_BM
......@@ -818,7 +719,7 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
lp->lan_type = hp100_sense_lan(dev);
/* Print out a message what about what we think we have probed. */
printk("hp100: %s: %s at 0x%x, IRQ %d, ", dev->name, lp->id->name, ioaddr, dev->irq);
printk("hp100: at 0x%x, IRQ %d, ", ioaddr, dev->irq);
switch (bus) {
case HP100_BUS_EISA:
printk("EISA");
......@@ -833,7 +734,7 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
printk(" bus, %dk SRAM (rx/tx %d%%).\n", lp->memory_size >> 10, lp->rx_ratio);
if (lp->mode == 2) { /* memory mapped */
printk("hp100: %s: Memory area at 0x%lx-0x%lx", dev->name, mem_ptr_phys,
printk("hp100: Memory area at 0x%lx-0x%lx", mem_ptr_phys,
(mem_ptr_phys + (mem_ptr_phys > 0x100000 ? (u_long) lp->memory_size : 16 * 1024)) - 1);
if (mem_ptr_virt)
printk(" (virtual base %p)", mem_ptr_virt);
......@@ -843,7 +744,8 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
dev->mem_start = mem_ptr_phys;
dev->mem_end = mem_ptr_phys + lp->memory_size;
}
printk("hp100: %s: ", dev->name);
printk("hp100: ");
if (lp->lan_type != HP100_LAN_ERR)
printk("Adapter is attached to ");
switch (lp->lan_type) {
......@@ -861,6 +763,10 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr,
}
return 0;
out2:
release_region(ioaddr, HP100_REGION_SIZE);
out1:
return -ENODEV;
}
/* This procedure puts the card into a stable init state */
......@@ -950,6 +856,7 @@ static void hp100_hwinit(struct net_device *dev)
/* Finally try to log in the Hub if there may be a VG connection. */
if ((lp->lan_type == HP100_LAN_100) || (lp->lan_type == HP100_LAN_ERR))
hp100_login_to_vg_hub(dev, 0); /* relogin */
}
......@@ -1152,7 +1059,7 @@ static int hp100_open(struct net_device *dev)
if (request_irq(dev->irq, hp100_interrupt,
lp->bus == HP100_BUS_PCI || lp->bus ==
HP100_BUS_EISA ? SA_SHIRQ : SA_INTERRUPT,
lp->id->name, dev)) {
"hp100", dev)) {
printk("hp100: %s: unable to get IRQ %d\n", dev->name, dev->irq);
return -EAGAIN;
}
......@@ -2054,7 +1961,7 @@ static void hp100_rx_bm(struct net_device *dev)
/*
* statistics
*/
static hp100_stats_t *hp100_get_stats(struct net_device *dev)
static struct net_device_stats *hp100_get_stats(struct net_device *dev)
{
unsigned long flags;
int ioaddr = dev->base_addr;
......@@ -2558,10 +2465,14 @@ static int hp100_sense_lan(struct net_device *dev)
return HP100_LAN_COAX;
}
if ((lp->id->id == 0x02019F022) ||
(lp->id->id == 0x01042103c) || (lp->id->id == 0x01040103c))
return HP100_LAN_ERR; /* Those cards don't have a 100 Mbit connector */
/* Those cards don't have a 100 Mbit connector */
if ( !strcmp(lp->id, "HWP1920") ||
(lp->pci_dev &&
lp->pci_dev->vendor == PCI_VENDOR_ID &&
(lp->pci_dev->device == PCI_DEVICE_ID_HP_J2970A ||
lp->pci_dev->device == PCI_DEVICE_ID_HP_J2973A)))
return HP100_LAN_ERR;
if (val_VG & HP100_LINK_CABLE_ST) /* Can hear the HUBs tone. */
return HP100_LAN_100;
return HP100_LAN_ERR;
......@@ -2915,122 +2826,248 @@ void hp100_RegisterDump(struct net_device *dev)
#endif
static void cleanup_dev(struct net_device *d)
{
struct hp100_private *p = (struct hp100_private *) d->priv;
unregister_netdev(d);
release_region(d->base_addr, HP100_REGION_SIZE);
if (p->mode == 1) /* busmaster */
pci_free_consistent(p->pci_dev, MAX_RINGSIZE + 0x0f,
p->page_vaddr_algn,
virt_to_whatever(d, p->page_vaddr_algn));
if (p->mem_ptr_virt)
iounmap(p->mem_ptr_virt);
free_netdev(d);
}
#ifdef CONFIG_EISA
static int __init hp100_eisa_probe (struct device *gendev)
{
struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private));
struct eisa_device *edev = to_eisa_device(gendev);
int err;
if (!dev)
return -ENOMEM;
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &edev->dev);
err = hp100_probe1(dev, edev->base_addr, HP100_BUS_EISA, NULL);
if (err)
goto out1;
err = register_netdev(dev);
if (err)
goto out2;
#ifdef HP100_DEBUG
printk("hp100: %s: EISA adapter found at 0x%x\n", dev->name,
dev->base_addr);
#endif
gendev->driver_data = dev;
return 0;
out2:
release_region(dev->base_addr, HP100_REGION_SIZE);
out1:
free_netdev(dev);
return err;
}
static int __devexit hp100_eisa_remove (struct device *gendev)
{
struct net_device *dev = gendev->driver_data;
cleanup_dev(dev);
return 0;
}
static struct eisa_driver hp100_eisa_driver = {
.id_table = hp100_eisa_tbl,
.driver = {
.name = "hp100",
.probe = hp100_eisa_probe,
.remove = __devexit_p (hp100_eisa_remove),
}
};
#endif
#ifdef CONFIG_PCI
static int __devinit hp100_pci_probe (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private));
int ioaddr = pci_resource_start(pdev, 0);
u_short pci_command;
int err;
if (!dev)
return -ENOMEM;
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
pci_read_config_word(pdev, 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;
pci_write_config_word(pdev, PCI_COMMAND, pci_command);
}
if (!(pci_command & PCI_COMMAND_MASTER)) {
#ifdef HP100_DEBUG
printk("hp100: %s: PCI Master Bit has not been set. Setting...\n", dev->name);
#endif
pci_command |= PCI_COMMAND_MASTER;
pci_write_config_word(pdev, PCI_COMMAND, pci_command);
}
err = hp100_probe1(dev, ioaddr, HP100_BUS_PCI, pdev);
if (err)
goto out1;
err = register_netdev(dev);
if (err)
goto out2;
#ifdef HP100_DEBUG
printk("hp100: %s: PCI adapter found at 0x%x\n", dev->name, ioaddr);
#endif
pci_set_drvdata(pdev, dev);
return 0;
out2:
release_region(dev->base_addr, HP100_REGION_SIZE);
out1:
free_netdev(dev);
return err;
}
static void __devexit hp100_pci_remove (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
cleanup_dev(dev);
}
static struct pci_driver hp100_pci_driver = {
.name = "hp100",
.id_table = hp100_pci_tbl,
.probe = hp100_pci_probe,
.remove = __devexit_p(hp100_pci_remove),
};
#endif
/*
* module section
*/
#ifdef MODULE
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, "
"Siegfried \"Frieder\" Loeffler (dg1sek) <floeff@mathematik.uni-stuttgart.de>");
MODULE_DESCRIPTION("HP CASCADE Architecture Driver for 100VG-AnyLan Network Adapters");
/*
* Note: if you have more than five 100vg cards in your pc, feel free to
* increase this value
*/
#define HP100_DEVICES 5
/*
* Note: to register three eisa or pci devices, use:
* Note: to register three isa devices, use:
* option hp100 hp100_port=0,0,0
* to register one card at io 0x280 as eth239, use:
* option hp100 hp100_port=0x280 hp100_name=eth239
* option hp100 hp100_port=0x280
*/
#if defined(MODULE) && defined(CONFIG_ISA)
#define HP100_DEVICES 5
/* Parameters set by insmod */
static int hp100_port[HP100_DEVICES] = { 0, [1 ... (HP100_DEVICES-1)] = -1 };
MODULE_PARM(hp100_port, "1-" __MODULE_STRING(HP100_DEVICES) "i");
/* Allocate HP100_DEVICES strings of length IFNAMSIZ, one string for each device */
static char hp100_name[HP100_DEVICES][IFNAMSIZ] = { "", "", "", "", "" };
/* Allow insmod to write those HP100_DEVICES strings individually */
MODULE_PARM(hp100_name, "1-" __MODULE_STRING(HP100_DEVICES) "c" __MODULE_STRING(IFNAMSIZ));
/* List of devices */
static struct net_device *hp100_devlist[HP100_DEVICES];
static void release_dev(int i)
static int __init hp100_isa_init(void)
{
struct net_device *d = hp100_devlist[i];
struct hp100_private *p = (struct hp100_private *) d->priv;
struct net_device *dev;
int i, err, cards = 0;
unregister_netdev(d);
release_region(d->base_addr, HP100_REGION_SIZE);
/* Don't autoprobe ISA bus */
if (hp100_port[0] == 0)
return -ENODEV;
if (p->mode == 1) /* busmaster */
pci_free_consistent(p->pci_dev, MAX_RINGSIZE + 0x0f, p->page_vaddr_algn, virt_to_whatever(d, p->page_vaddr_algn));
if (p->mem_ptr_virt)
iounmap(p->mem_ptr_virt);
kfree(d->priv);
d->priv = NULL;
free_netdev(d);
hp100_devlist[i] = NULL;
/* Loop on all possible base addresses */
for (i = 0; i < HP100_DEVICES && hp100_port[i] != -1; ++i) {
dev = alloc_etherdev(sizeof(struct hp100_private));
if (!dev) {
printk(KERN_WARNING "hp100: no memory for network device\n");
while (cards > 0)
cleanup_dev(hp100_devlist[--cards]);
return -ENOMEM;
}
SET_MODULE_OWNER(dev);
err = hp100_isa_probe(dev, hp100_port[i]);
if (!err) {
err = register_netdev(dev);
if (!err)
hp100_devlist[cards++] = dev;
else
release_region(dev->base_addr, HP100_REGION_SIZE);
}
if (err)
free_netdev(dev);
}
return cards > 0 ? 0 : -ENODEV;
}
static int __init hp100_module_init(void)
static void __exit hp100_isa_cleanup(void)
{
int i, cards;
int i;
#ifndef CONFIG_PCI
if (hp100_port == 0 && !EISA_bus)
printk("hp100: You should not use auto-probing with insmod!\n");
for (i = 0; i < HP100_DEVICES; i++) {
struct net_device *dev = hp100_devlist[i];
if (dev)
cleanup_dev(dev);
}
}
#else
#define hp100_isa_init() (0)
#define hp100_isa_cleanup() do { } while(0)
#endif
/* Loop on all possible base addresses */
i = -1;
cards = 0;
while ((hp100_port[++i] != -1) && (i < HP100_DEVICES)) {
/* Create device and set basics args */
hp100_devlist[i] = kmalloc(sizeof(struct net_device), GFP_KERNEL);
if (!hp100_devlist[i])
goto fail;
memset(hp100_devlist[i], 0x00, sizeof(struct net_device));
#if LINUX_VERSION_CODE >= 0x020362 /* 2.3.99-pre7 */
memcpy(hp100_devlist[i]->name, hp100_name[i], IFNAMSIZ); /* Copy name */
#else
hp100_devlist[i]->name = hp100_name[i];
#endif /* LINUX_VERSION_CODE >= 0x020362 */
hp100_devlist[i]->base_addr = hp100_port[i];
hp100_devlist[i]->init = &hp100_probe;
/* Try to create the device */
if (register_netdev(hp100_devlist[i]) != 0) {
/* DeAllocate everything */
/* Note: if dev->priv is mallocated, there is no way to fail */
kfree(hp100_devlist[i]);
hp100_devlist[i] = (struct net_device *) NULL;
} else
cards++;
} /* Loop over all devices */
static int __init hp100_module_init(void)
{
int err;
return cards > 0 ? 0 : -ENODEV;
fail:
while (cards && --i)
if (hp100_devlist[i]) {
release_dev(i);
--cards;
}
return -ENOMEM;
err = hp100_isa_init();
#ifdef CONFIG_EISA
err |= eisa_driver_register(&hp100_eisa_driver);
#endif
#ifdef CONFIG_PCI
err |= pci_module_init(&hp100_pci_driver);
#endif
return err;
}
static void __exit hp100_module_exit(void)
{
int i;
/* TODO: Check if all skb's are released/freed. */
for (i = 0; i < HP100_DEVICES; i++)
if (hp100_devlist[i] != (struct net_device *) NULL)
release_dev(i);
hp100_isa_cleanup();
#ifdef CONFIG_EISA
eisa_driver_unregister (&hp100_eisa_driver);
#endif
#ifdef CONFIG_PCI
pci_unregister_driver (&hp100_pci_driver);
#endif
}
module_init(hp100_module_init)
module_exit(hp100_module_exit)
#endif /* MODULE */
/*
* Local variables:
......
......@@ -631,6 +631,8 @@
#define PCI_DEVICE_ID_HP_TACHLITE 0x1029
#define PCI_DEVICE_ID_HP_J2585A 0x1030
#define PCI_DEVICE_ID_HP_J2585B 0x1031
#define PCI_DEVICE_ID_HP_J2973A 0x1040
#define PCI_DEVICE_ID_HP_J2970A 0x1042
#define PCI_DEVICE_ID_HP_DIVA 0x1048
#define PCI_DEVICE_ID_HP_DIVA_TOSCA1 0x1049
#define PCI_DEVICE_ID_HP_DIVA_TOSCA2 0x104A
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment