patch-2.4.0-test2 linux/drivers/net/dmfe.c
Next file: linux/drivers/net/dummy.c
Previous file: linux/drivers/net/dgrs.c
Back to the patch index
Back to the overall index
- Lines: 386
- Date:
Wed Jun 21 09:32:44 2000
- Orig file:
v2.4.0-test1/linux/drivers/net/dmfe.c
- Orig date:
Thu May 11 15:30:07 2000
diff -u --recursive --new-file v2.4.0-test1/linux/drivers/net/dmfe.c linux/drivers/net/dmfe.c
@@ -1,8 +1,9 @@
/*
- dmfe.c: Version 1.28 01/18/2000
+ dmfe.c: Version 1.30 06/11/2000
A Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver for Linux.
Copyright (C) 1997 Sten Wang
+ (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -46,20 +47,29 @@
Made it compile in 2.3 (device to net_device)
Alan Cox <alan@redhat.com> :
+ Cleaned up for kernel merge.
Removed the back compatibility support
Reformatted, fixing spelling etc as I went
Removed IRQ 0-15 assumption
-
+
+ Jeff Garzik <jgarzik@mandrakesoft.com> :
+ Updated to use new PCI driver API.
+ Resource usage cleanups.
+ Report driver version to user.
+
TODO
-
+
+ Implement pci_driver::suspend() and pci_driver::resume()
+ power management methods.
+
Check and fix on 64bit and big endian boxes.
- Sort out the PCI latency.
-
- (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
-
- Cleaned up for kernel merge by Alan Cox (alan@redhat.com)
+
+ Test and make sure PCI latency is now correct for all cases.
+
*/
+#define DMFE_VERSION "1.30 (June 11, 2000)"
+
#include <linux/module.h>
#include <linux/kernel.h>
@@ -118,7 +128,7 @@
#define DMFE_AUTO 8
#define DMFE_TIMER_WUT jiffies+(HZ*2)/2 /* timer wakeup time : 1 second */
-#define DMFE_TX_TIMEOUT HZ*1.5 /* tx packet time-out time 1.5 s" */
+#define DMFE_TX_TIMEOUT ((HZ*3)/2) /* tx packet time-out time 1.5 s" */
#define DMFE_DBUG(dbug_now, msg, vaule) if (dmfe_debug || dbug_now) printk("DBUG: %s %x\n", msg, vaule)
@@ -142,7 +152,9 @@
#define SROM_CLK_WRITE(data, ioaddr) outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);DELAY_5US;outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr);DELAY_5US;outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);DELAY_5US;
-#define CHK_IO_SIZE(pci_id, dev_rev) ( (pci_id==PCI_DM9132_ID) || (dev_rev >= 0x02000030) ) ? DM9102A_IO_SIZE: DM9102_IO_SIZE
+#define __CHK_IO_SIZE(pci_id, dev_rev) ( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? DM9102A_IO_SIZE: DM9102_IO_SIZE
+#define CHK_IO_SIZE(pci_dev, dev_rev) \
+ __CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev)
/* Structure/enum declaration ------------------------------- */
@@ -164,7 +176,7 @@
struct dmfe_board_info {
u32 chip_id; /* Chip vendor/Device ID */
- u32 chip_revesion; /* Chip revesion */
+ u32 chip_revision; /* Chip revision */
struct net_device *next_dev; /* next device */
struct pci_dev *net_dev; /* PCI device */
@@ -221,7 +233,6 @@
/* Global variable declaration ----------------------------- */
static int dmfe_debug = 0;
static unsigned char dmfe_media_mode = 8;
-static struct net_device *dmfe_root_dev = NULL; /* First device */
static u32 dmfe_cr6_user_set = 0;
/* For module input parameter */
@@ -299,7 +310,6 @@
};
/* function declaration ------------------------------------- */
-static int dmfe_probe(void);
static int dmfe_open(struct net_device *);
static int dmfe_start_xmit(struct sk_buff *, struct net_device *);
static int dmfe_stop(struct net_device *);
@@ -333,111 +343,117 @@
* Search DM910X board, allocate space and register it
*/
-static int __init dmfe_probe(void)
+
+static int __init dmfe_init_one (struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
unsigned long pci_iobase;
- u16 dm9102_count = 0;
u8 pci_irqline;
- static int index = 0; /* For multiple call */
struct dmfe_board_info *db; /* Point a board information structure */
int i;
- struct pci_dev *net_dev = NULL;
struct net_device *dev;
+ u32 dev_rev;
DMFE_DBUG(0, "dmfe_probe()", 0);
- if (!pci_present())
- return -ENODEV;
+ pci_iobase = pci_resource_start(pdev, 0);
+ pci_irqline = pdev->irq;
- index = 0;
- while ((net_dev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, net_dev)))
- {
- u32 pci_id;
- u32 dev_rev;
-
- index++;
- if (pci_read_config_dword(net_dev, PCI_VENDOR_ID, &pci_id) != DMFE_SUCC)
- continue;
-
- if ((pci_id != PCI_DM9102_ID) && (pci_id != PCI_DM9132_ID))
- continue;
-
- pci_iobase = net_dev->resource[0].start;
- pci_irqline = net_dev->irq;
-
- /* Enable Master/IO access, Disable memory access */
-
- pci_enable_device (net_dev); /* XXX check return val */
- pci_set_master(net_dev);
-
- /* Set Latency Timer 80h */
-
- /* FIXME: setting values > 32 breaks some SiS 559x stuff.
- Need a PCI quirk.. */
-
- pci_write_config_byte(net_dev, PCI_LATENCY_TIMER, 0x80);
+ /* Interrupt check */
+ if (pci_irqline == 0) {
+ printk(KERN_ERR "dmfe: Interrupt wrong : IRQ=%d\n",
+ pci_irqline);
+ goto err_out;
+ }
- /* Read Chip revesion */
- pci_read_config_dword(net_dev, PCI_REVISION_ID, &dev_rev);
-
- /* IO range check */
- if (check_region(pci_iobase, CHK_IO_SIZE(pci_id, dev_rev))) {
- printk(KERN_ERR "dmfe: I/O conflict : IO=%lx Range=%x\n", pci_iobase, CHK_IO_SIZE(pci_id, dev_rev));
- continue;
- }
- /* Interrupt check */
- if (pci_irqline == 0) {
- printk(KERN_ERR "dmfe: Interrupt wrong : IRQ=%d\n", pci_irqline);
- continue;
- }
+ /* iobase check */
+ if (pci_iobase == 0) {
+ printk(KERN_ERR "dmfe: I/O base is zero\n");
+ goto err_out;
+ }
- /* Found DM9102 card and PCI resource allocated OK */
- dm9102_count++; /* Found a DM9102 card */
+ /* Enable Master/IO access, Disable memory access */
+ if (pci_enable_device(pdev))
+ goto err_out;
+ pci_set_master(pdev);
- /* Init network device */
- dev = init_etherdev(NULL, sizeof(*db));
- if (dev == NULL)
- continue;
-
- db = dev->priv;
+#if 0 /* pci_{enable_device,set_master} sets minimum latency for us now */
- memset(db, 0, sizeof(*db));
- db->next_dev = dmfe_root_dev;
- dmfe_root_dev = dev;
+ /* Set Latency Timer 80h */
+ /* FIXME: setting values > 32 breaks some SiS 559x stuff.
+ Need a PCI quirk.. */
- db->chip_id = pci_id; /* keep Chip vandor/Device ID */
- db->ioaddr = pci_iobase;
- db->chip_revesion = dev_rev;
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);
+#endif
- db->net_dev = net_dev;
+ /* Read Chip revision */
+ pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev);
- dev->base_addr = pci_iobase;
- dev->irq = pci_irqline;
- dev->open = &dmfe_open;
- dev->hard_start_xmit = &dmfe_start_xmit;
- dev->stop = &dmfe_stop;
- dev->get_stats = &dmfe_get_stats;
- dev->set_multicast_list = &dmfe_set_filter_mode;
- dev->do_ioctl = &dmfe_do_ioctl;
+ /* Init network device */
+ dev = init_etherdev(NULL, sizeof(*db));
+ if (dev == NULL)
+ goto err_out;
- request_region(pci_iobase, CHK_IO_SIZE(pci_id, dev_rev), dev->name);
+ /* IO range check */
+ if (!request_region(pci_iobase, CHK_IO_SIZE(pdev, dev_rev), dev->name)) {
+ printk(KERN_ERR "dmfe: I/O conflict : IO=%lx Range=%x\n",
+ pci_iobase, CHK_IO_SIZE(pdev, dev_rev));
+ goto err_out_netdev;
+ }
- /* read 64 word srom data */
- for (i = 0; i < 64; i++)
- ((u16 *) db->srom)[i] = read_srom_word(pci_iobase, i);
+ db = dev->priv;
+ pdev->driver_data = dev;
- /* Set Node address */
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = db->srom[20 + i];
+ db->chip_id = ent->driver_data;
+ db->ioaddr = pci_iobase;
+ db->chip_revision = dev_rev;
- }
+ db->net_dev = pdev;
+
+ dev->base_addr = pci_iobase;
+ dev->irq = pci_irqline;
+ dev->open = &dmfe_open;
+ dev->hard_start_xmit = &dmfe_start_xmit;
+ dev->stop = &dmfe_stop;
+ dev->get_stats = &dmfe_get_stats;
+ dev->set_multicast_list = &dmfe_set_filter_mode;
+ dev->do_ioctl = &dmfe_do_ioctl;
- if (!dm9102_count)
- printk(KERN_WARNING "dmfe: Can't find DM910X board\n");
+ /* read 64 word srom data */
+ for (i = 0; i < 64; i++)
+ ((u16 *) db->srom)[i] = read_srom_word(pci_iobase, i);
- return dm9102_count ? 0 : -ENODEV;
+ /* Set Node address */
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = db->srom[20 + i];
+
+ return 0;
+
+err_out_netdev:
+ unregister_netdev(dev);
+ kfree(dev);
+err_out:
+ return -ENODEV;
+}
+
+
+static void __exit dmfe_remove_one (struct pci_dev *pdev)
+{
+ struct net_device *dev = pdev->driver_data;
+ struct dmfe_board_info *db;
+
+ DMFE_DBUG(0, "dmfe_remove_one()", 0);
+
+ db = dev->priv;
+
+ unregister_netdev(dev);
+ release_region(dev->base_addr, CHK_IO_SIZE(pdev, db->chip_revision));
+ kfree(dev); /* free board information */
+
+ DMFE_DBUG(0, "dmfe_remove_one() exit", 0);
}
+
/*
* Open the interface.
* The interface is opened whenever "ifconfig" actives it.
@@ -482,7 +498,7 @@
db->in_reset_state = 0;
db->rx_error_cnt = 0;
- if (!chkmode || (db->chip_id == PCI_DM9132_ID) || (db->chip_revesion >= 0x02000030)) {
+ if (!chkmode || (db->chip_id == PCI_DM9132_ID) || (db->chip_revision >= 0x02000030)) {
//db->cr6_data &= ~CR6_SFT; /* Used Tx threshold */
//db->cr6_data |= CR6_NO_PURGE; /* No purge if rx unavailable */
db->cr0_data = 0xc00000; /* TX/RX desc burst mode */
@@ -933,8 +949,8 @@
else
tmp_cr12 = inb(db->ioaddr + DCR12); /* DM9102/DM9102A */
- if (((db->chip_id == PCI_DM9102_ID) && (db->chip_revesion == 0x02000030)) ||
- ((db->chip_id == PCI_DM9132_ID) && (db->chip_revesion == 0x02000010))) {
+ if (((db->chip_id == PCI_DM9102_ID) && (db->chip_revision == 0x02000030)) ||
+ ((db->chip_id == PCI_DM9132_ID) && (db->chip_revision == 0x02000010))) {
/* DM9102A Chip */
if (tmp_cr12 & 2)
tmp_cr12 = 0x0; /* Link failed */
@@ -1532,6 +1548,21 @@
}
+static struct pci_device_id dmfe_pci_tbl[] __initdata = {
+ { 0x1282, 0x9132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9132_ID },
+ { 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9102_ID },
+ { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9100_ID },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, dmfe_pci_tbl);
+
+static struct pci_driver dmfe_driver = {
+ name: "dmfe",
+ id_table: dmfe_pci_tbl,
+ probe: dmfe_init_one,
+ remove: dmfe_remove_one,
+};
+
MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");
MODULE_DESCRIPTION("Davicom DM910X fast ethernet driver");
MODULE_PARM(debug, "i");
@@ -1546,6 +1577,8 @@
static int __init dmfe_init_module(void)
{
+ int rc;
+
DMFE_DBUG(0, "init_module() ", debug);
if (debug)
@@ -1565,32 +1598,26 @@
break;
}
- return dmfe_probe(); /* search board and register */
+ rc = pci_register_driver(&dmfe_driver);
+ if (rc < 0)
+ return rc;
+ if (rc > 0) {
+ printk (KERN_INFO "Davicom DM91xx net driver loaded, version "
+ DMFE_VERSION "\n");
+ return 0;
+ }
+ return -ENODEV;
}
/*
* Description:
* when user used rmmod to delete module, system invoked clean_module()
- * to un-register device.
+ * to un-register all registered services.
*/
static void __exit dmfe_cleanup_module(void)
{
- struct net_device *next_dev;
- struct dmfe_board_info *db;
-
- DMFE_DBUG(0, "clean_module()", 0);
-
- while (dmfe_root_dev) {
- db = dmfe_root_dev->priv;
- next_dev = db->next_dev;
- unregister_netdev(dmfe_root_dev);
- release_region(dmfe_root_dev->base_addr, CHK_IO_SIZE(db->chip_id, db->chip_revesion));
- kfree(db); /* free board information */
- kfree(dmfe_root_dev); /* free device structure */
- dmfe_root_dev = next_dev;
- }
- DMFE_DBUG(0, "clean_module() exit", 0);
+ pci_unregister_driver(&dmfe_driver);
}
module_init(dmfe_init_module);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)