struct registered_device {
void* vbase_addr; /* virtual base of region */
struct pci_dev* pdev; /* or any device? */
struct pci_id_info* dev_info; /* matched scan entry */
int irq; /* unregistered, we are not
ready for IRQ events yet... */
/*
struct resource resource; /* eventually, if we'll use
request_resource; otherwise we can use normal
request_region/release_region */
*/
void* private;
/* do not kill me, just idea how to build tulip with
I/O and MMIO support together
u8 (*readb)(void* base, int offset);
...
*/
};
struct drv_id_info {
const char* name;
int flags;
int pci_class;
struct pci_id_info *pci_dev_tbl;
char *(*probe1)(struct registered_device *dev, void *dev_ptr, int fnd_cnt);
int (*pwr_event)(struct registered_device *dev, int event);
/* CardBus stuff */
};
extern int pci_drv_register(struct drv_id_info *drv_id, void *initial_device);
extern void pci_drv_unregister(struct drv_id_info *drv_id);
extern void pci_dev_release(struct registered_device *dev);
Comments? Ideas? Thanks.
Now current output of /proc/iomem... I'm satisfied:
00000000-0009ffff : System RAM
000a0000-000bffff : Video RAM area
000c0000-000c7fff : Video ROM
000f0000-000fffff : System ROM
00100000-0fffffff : System RAM
00100000-001e6e97 : Kernel code
001e6e98-002077f3 : Kernel data
d8000000-dbffffff : Intel 440BX - 82443BX Host
dc000000-dc003fff : Matrox G400
dd000000-dd7fffff : Matrox G400
e0000000-e1ffffff : Matrox G400
e2000000-e203ffff : DEC DC21142
e3000000-e300007f : DEC DC21142
e3000000-e300007f : eth0
e3001000-e3001fff : Brooktree Bt848
e3002000-e3002fff : Brooktree Bt878 2nd Contr. (?)
e3003000-e3003fff : Brooktree Bt878
And diff. First hunk is tulip, rest are changes to scan code. This scanning
code is not compatible with current network drivers! I added virtual address
into tulip private structure instead of to net_device, as each procedure used
tulip private data anyway, so no speed loss should occur. I do not know what
networking gurus thinks about adding strange fields to net_device.
Best regards,
Petr Vandrovec
vandrove@vc.cvut.cz
diff -urdN linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- linux/drivers/net/tulip.c Mon Sep 27 14:30:23 1999
+++ linux/drivers/net/tulip.c Tue Sep 28 20:33:55 1999
@@ -151,10 +151,6 @@
#define outb writeb
#define outw writew
#define outl writel
-#undef request_region
-#undef release_region
-#define request_region request_mem_region
-#define release_region release_mem_region
#endif
/*
@@ -260,7 +256,7 @@
*/
-static void *tulip_probe1(struct pci_dev *pdev, void *init_dev,
+static char *tulip_probe1(struct pci_dev *pdev, void *init_dev,
long ioaddr, int irq, int chip_idx, int find_cnt);
#ifdef USE_IO_OPS
#define TULIP_IOTYPE PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0
@@ -289,7 +285,7 @@
{ "Digital DS21140 Tulip", { 0x00091011, 0xffffffff },
TULIP_IOTYPE, TULIP_SIZEL, DC21140 },
{ "Digital DS21143 Tulip", { 0x00191011, 0xffffffff },
- TULIP_IOTYPE, TULIP_SIZEB, DC21142 },
+ TULIP_IOTYPE, TULIP_SIZEL, DC21142 },
{ "Lite-On 82c168 PNIC", { 0x000211AD, 0xffffffff },
TULIP_IOTYPE, 256, LC82C168 },
{ "Macronix 98713 PMAC", { 0x051210d9, 0xffffffff },
@@ -501,6 +497,7 @@
int cur_index; /* Current media index. */
int saved_if_port;
struct pci_dev *pci_dev;
+ long vbase_addr;
};
static void parse_eeprom(struct net_device *dev);
@@ -530,7 +527,7 @@
/* A list of all installed Tulip devices. */
static struct net_device *root_tulip_dev = NULL;
-static void *tulip_probe1(struct pci_dev *pdev, void *init_dev,
+static char *tulip_probe1(struct pci_dev *pdev, void *init_dev,
long ioaddr, int irq, int chip_idx, int board_idx)
{
struct net_device *dev;
@@ -578,7 +575,8 @@
pci_write_config_dword(pdev, 0x40, 0x00000000);
printk(KERN_INFO "%s: %s rev %d at %#3lx,",
- dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
+ dev->name, tulip_tbl[chip_idx].chip_name, chip_rev,
+ pci_drv_physbase(pci_tbl+chip_idx, pdev));
/* Stop the chip's Tx and Rx processes. */
outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6);
@@ -674,10 +672,9 @@
printk(", IRQ %d.\n", irq);
last_irq = irq;
- /* We do a request_region() only to register /proc/ioports info. */
- request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);
-
- dev->base_addr = ioaddr;
+ /* Caller did request_region()... */
+
+ dev->base_addr = pci_drv_physbase(pci_tbl+chip_idx, pdev);
dev->irq = irq;
tp->pci_dev = pdev;
@@ -685,6 +682,7 @@
tp->revision = chip_rev;
tp->flags = tulip_tbl[chip_idx].flags;
tp->csr0 = csr0;
+ tp->vbase_addr = ioaddr;
/* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles.
And the ASIX must have a burst limit or horrible things happen. */
@@ -858,7 +856,7 @@
if (tulip_tbl[chip_idx].flags & HAS_PWRDWN)
pci_write_config_dword(pdev, 0x40, 0x40000000);
- return dev;
+ return dev->name;
}
/* Serial EEPROM section. */
@@ -1154,7 +1152,7 @@
int i;
int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
int retval = 0;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
long mdio_addr = ioaddr + CSR9;
if (tp->chip_id == LC82C168) {
@@ -1212,7 +1210,7 @@
struct tulip_private *tp = (struct tulip_private *)dev->priv;
int i;
int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
long mdio_addr = ioaddr + CSR9;
if (tp->chip_id == LC82C168) {
@@ -1267,7 +1265,7 @@
tulip_open(struct net_device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
int next_tick = 3*HZ;
int i;
@@ -1469,8 +1467,8 @@
/* Set up the transceiver control registers for the selected media type. */
static void select_media(struct net_device *dev, int startup)
{
- long ioaddr = dev->base_addr;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = tp->vbase_addr;
struct mediatable *mtable = tp->mtable;
u32 new_csr6;
int i;
@@ -1681,8 +1679,8 @@
*/
static int check_duplex(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = tp->vbase_addr;
int mii_reg1, mii_reg5, negotiated, duplex;
if (tp->full_duplex_lock)
@@ -1729,7 +1727,7 @@
{
struct net_device *dev = (struct net_device *)data;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
u32 csr12 = inl(ioaddr + CSR12);
int next_tick = 2*HZ;
@@ -1887,7 +1885,7 @@
{
struct net_device *dev = (struct net_device *)data;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
int csr12 = inl(ioaddr + CSR12);
int next_tick = 60*HZ;
int new_csr6 = 0;
@@ -1960,7 +1958,7 @@
static void nway_start(struct net_device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
int csr14 = ((tp->to_advertise & 0x0780) << 9) |
((tp->to_advertise&0x0020)<<1) | 0xffbf;
@@ -1992,7 +1990,7 @@
static void nway_lnk_change(struct net_device *dev, int csr5)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
int csr12 = inl(ioaddr + CSR12);
if (tp->chip_id == PNIC2) {
@@ -2117,7 +2115,7 @@
{
struct net_device *dev = (struct net_device *)data;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
int next_tick = 60*HZ;
if (tulip_debug > 3) {
@@ -2131,7 +2129,7 @@
static void pnic_do_nway(struct net_device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
u32 phy_reg = inl(ioaddr + 0xB8);
u32 new_csr6 = tp->csr6 & ~0x40C40200;
@@ -2163,7 +2161,7 @@
static void pnic_lnk_change(struct net_device *dev, int csr5)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
int phy_reg = inl(ioaddr + 0xB8);
if (tulip_debug > 1)
@@ -2187,7 +2185,7 @@
{
struct net_device *dev = (struct net_device *)data;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
int next_tick = 60*HZ;
if (media_cap[dev->if_port] & MediaIsMII) {
@@ -2252,7 +2250,7 @@
{
struct net_device *dev = (struct net_device *)data;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
int next_tick = 60*HZ;
if (tulip_debug > 1)
@@ -2266,7 +2264,7 @@
static void tulip_tx_timeout(struct net_device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
if (media_cap[dev->if_port] & MediaIsMII) {
/* Do nothing -- the media monitor should handle this. */
@@ -2455,7 +2453,7 @@
dev->trans_start = jiffies;
/* Trigger an immediate transmit demand. */
- outl(0, dev->base_addr + CSR1);
+ outl(0, tp->vbase_addr + CSR1);
return 0;
}
@@ -2466,7 +2464,7 @@
{
struct net_device *dev = (struct net_device *)dev_instance;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
int csr5, work_budget = max_interrupt_work;
#if defined(__i386__) && defined(SMP_CHECK)
@@ -2495,7 +2493,7 @@
if (tulip_debug > 3)
printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n",
- dev->name, csr5, inl(dev->base_addr + CSR5));
+ dev->name, csr5, inl(tp->vbase_addr + CSR5));
if (csr5 & (RxIntr | RxNoBuf))
work_budget -= tulip_rx(dev);
@@ -2766,8 +2764,8 @@
static int tulip_close(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = tp->vbase_addr;
dev->start = 0;
dev->tbusy = 1;
@@ -2806,7 +2804,7 @@
static struct net_device_stats *tulip_get_stats(struct net_device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
int csr8 = inl(ioaddr + CSR8);
if (dev->start && csr8 != 0xffffffff)
@@ -2819,7 +2817,7 @@
static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
u16 *data = (u16 *)&rq->ifr_data;
int phy = tp->phys[0] & 0x1f;
long flags;
@@ -2933,7 +2931,7 @@
static void set_rx_mode(struct net_device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ long ioaddr = tp->vbase_addr;
int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
tp->csr6 &= ~0x00D5;
@@ -3056,7 +3054,7 @@
static dev_node_t *tulip_attach(dev_locator_t *loc)
{
- struct net_device *dev;
+ char *name;
long ioaddr;
struct pci_dev *pdev;
u8 bus, devfn, irq;
@@ -3089,14 +3087,23 @@
if(node==NULL)
return NULL;
- dev = tulip_probe1(pdev, NULL, ioaddr, irq, DC21142, 0);
- if (dev) {
- strcpy(node->dev_name, dev->name);
+ name = tulip_probe1(pdev, NULL, ioaddr, irq, DC21142, 0);
+ if (name) {
+#ifdef USE_IO_OPS
+ request_region(ioaddr, pci_tbl[DC21142].io_size, name);
+#else
+ request_mem_region(pciaddr & PCI_BASE_ADDRESS_MEM_MASK,
+ pci_tbl[DC21142].io_size, name);
+#endif
+ strcpy(node->dev_name, name);
node->major = node->minor = 0;
node->next = NULL;
MOD_INC_USE_COUNT;
return node;
}
+#ifdef USE_IO_OPS
+ iounmap((void*)ioaddr);
+#endif
kfree(node);
return NULL;
}
@@ -3110,8 +3117,8 @@
if (strcmp((*devp)->name, node->dev_name) == 0) break;
}
if (*devp) {
- long ioaddr = (*devp)->base_addr;
struct tulip_private *tp = (struct tulip_private *)(*devp)->priv;
+ long ioaddr = tp->vbase_addr;
int csr6 = inl(ioaddr + CSR6);
/* Disable interrupts, stop the chip, gather stats. */
if (csr6 != 0xffffffff) {
@@ -3135,7 +3142,7 @@
}
if (*devp) {
struct tulip_private *tp = (struct tulip_private *)(*devp)->priv;
- long ioaddr = (*devp)->base_addr;
+ long ioaddr = tp->vbase_addr;
pci_write_config_dword(tp->pci_dev, 0x40, 0x0000);
outl(tp->csr0, ioaddr + CSR0);
tulip_init_ring(*devp);
@@ -3160,10 +3167,8 @@
if (*devp) {
struct tulip_private *tp = (struct tulip_private *)(*devp)->priv;
unregister_netdev(*devp);
- release_region((*devp)->base_addr, pci_tbl[DC21142].io_size);
-#ifndef USE_IO_OPS
- iounmap((char *)(*devp)->base_addr);
-#endif
+ pci_drv_release(pci_tbl+tp->chip_id, tp->pci_dev,
+ tp->vbase_addr);
kfree(*devp);
if (tp->priv_addr)
kfree(tp->priv_addr);
@@ -3208,10 +3213,7 @@
while (root_tulip_dev) {
struct tulip_private *tp = (struct tulip_private*)root_tulip_dev->priv;
unregister_netdev(root_tulip_dev);
- release_region(root_tulip_dev->base_addr, pci_tbl[tp->chip_id].io_size);
-#ifndef USE_IO_OPS
- iounmap((char *)root_tulip_dev->base_addr);
-#endif
+ pci_drv_release(pci_tbl+tp->chip_id, tp->pci_dev, tp->vbase_addr);
next_dev = tp->next_module;
if (tp->priv_addr)
kfree(tp->priv_addr);
diff -urdN linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c
--- linux/drivers/pci/pcisyms.c Mon Sep 27 14:30:27 1999
+++ linux/drivers/pci/pcisyms.c Tue Sep 28 18:30:02 1999
@@ -49,6 +49,8 @@
EXPORT_SYMBOL(pci_drv_register);
EXPORT_SYMBOL(pci_drv_unregister);
+EXPORT_SYMBOL(pci_drv_release);
+EXPORT_SYMBOL(pci_drv_physbase);
EXPORT_SYMBOL(acpi_wake);
EXPORT_SYMBOL(acpi_set_pwr_state);
EXPORT_SYMBOL(register_cb_hook);
diff -urdN linux/drivers/pci/scan.c linux/drivers/pci/scan.c
--- linux/drivers/pci/scan.c Mon Sep 27 14:30:27 1999
+++ linux/drivers/pci/scan.c Tue Sep 28 18:49:39 1999
@@ -61,6 +61,10 @@
than half of the drivers for common hardware would benefit from the feature.
*/
+unsigned long pci_drv_physbase(struct pci_id_info* info, struct pci_dev *pdev) {
+ return pdev->resource[(info->pci_flags >> 4) & 7].start;
+}
+
/*
Ideally we would detect and number all cards of a type (e.g. network) in
PCI slot order.
@@ -81,8 +85,6 @@
int chip_idx, cards_found = 0;
struct pci_dev *pdev = NULL;
struct pci_id_info *pci_tbl = drv_id->pci_dev_tbl;
- void *newdev;
- struct resource *res;
if ( ! pci_present())
return -ENODEV;
@@ -94,6 +96,8 @@
int pci_flags, irq;
unsigned long pciaddr;
unsigned long ioaddr;
+ struct resource* res;
+ char* devname;
int free = 0;
pci_id = (pdev->device << 16) | pdev->vendor;
@@ -150,24 +154,29 @@
pci_write_config_word(pdev, PCI_COMMAND, new_command);
}
- newdev = drv_id->probe1(pdev, initial_device,
+ devname = drv_id->probe1(pdev, initial_device,
ioaddr, irq, chip_idx, cards_found);
/*
* Not attached.
*/
- if (newdev == 0)
+ if (!devname)
{
if(free)
iounmap((void *)ioaddr);
continue;
}
- if (newdev && (pci_flags & PCI_COMMAND_MASTER))
+ if (pci_flags & PCI_USES_IO)
+ request_region(pciaddr, pci_tbl[chip_idx].io_size, devname);
+ else
+ request_mem_region(pciaddr, pci_tbl[chip_idx].io_size, devname);
+
+ if (pci_flags & PCI_COMMAND_MASTER)
pci_set_master(pdev);
- if (newdev && (pci_flags & PCI_COMMAND_MASTER) &&
- ! (pci_flags & PCI_NO_MIN_LATENCY)) {
+ if ((pci_flags & PCI_COMMAND_MASTER) &&
+ ! (pci_flags & PCI_NO_MIN_LATENCY)) {
u8 pci_latency;
pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < min_pci_latency) {
@@ -199,6 +208,17 @@
return;
}
+void pci_drv_release(struct pci_id_info *info, struct pci_dev *pdev, unsigned long ioaddr) {
+ unsigned long phys_base;
+
+ phys_base = pci_drv_physbase(info, pdev);
+ if (info->pci_flags & PCI_USES_IO)
+ release_region(phys_base, info->io_size);
+ else {
+ iounmap((void*)ioaddr);
+ release_mem_region(phys_base, info->io_size);
+ }
+}
/* Change a device from D3 (sleep) to D0 (active).
Return the old power state.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/