This message generated a parse failure. Raw output follows here. Please use 'back' to navigate. From devnull@lkml.org Fri May 31 04:49:36 2024 Received: from nic2.funet.fi (nic2.funet.fi [128.214.248.46]) by herbie.ucs.indiana.edu (8.9.3/8.9.3) with ESMTP id TAA01248 for ; Tue, 28 Sep 1999 19:19:11 -0500 (EST) Received: from vger.rutgers.edu ([128.6.190.2]:13004 "EHLO vger.rutgers.edu") by nic2.funet.fi with ESMTP id ; Wed, 29 Sep 1999 03:18:32 +0300 Received: by vger.rutgers.edu via listexpand id ; Tue, 28 Sep 1999 20:16:33 -0400 Received: by vger.rutgers.edu id ; Tue, 28 Sep 1999 20:16:22 -0400 Received: from zikova.cvut.cz ([147.32.235.100]:4409 "EHLO zikova.cvut.cz") by vger.rutgers.edu with ESMTP id ; Tue, 28 Sep 1999 20:16:13 -0400 Received: from vana.vc.cvut.cz (root@vana.vc.cvut.cz [147.32.240.57]) by zikova.cvut.cz (8.9.0.Beta5/8.9.0.Beta5) with ESMTP id XAA17640; Tue, 28 Sep 1999 23:38:22 +0200 Received: (from root@localhost) by vana.vc.cvut.cz (8.9.3/8.9.3/Debian/GNU) id XAA02115; Tue, 28 Sep 1999 23:38:22 +0200 Date: Tue, 28 Sep 1999 23:38:22 +0200 From: Petr Vandrovec To: linux-kernel@vger.rutgers.edu Cc: alan@lxorguk.ukuu.org.uk, becker@cesdis1.gsfc.nasa.gov, jgarzik@pobox.com Subject: Re: pci_scan, tulip, 3c59x, multiple detections and others Message-Id: <19990928233822.A916@vana.vc.cvut.cz> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii User-Agent: Mutt/1.0pre2i Sender: owner-linux-kernel@vger.rutgers.edu Precedence: bulk X-Loop: majordomo@vger.rutgers.edu X-Orcpt: rfc822;linux-kernel-outgoing-dig Ok, so as I promised, this is first proposal, how things could work. It is not intended for inclusion in kernel, Alan... It does everything I want except that pci_drv_release and pci_drv_physbase API is a bit strange - you have to pass two parameters to it, one and half of other you got from registration callback, other half of second parameter you know when you were registrationg your callback with system. For sure it is not perfect, for example there is no way how to obtain parameter to pwe_event... I had to change return value from callback from void* to char*, otherwise driver could not dictate registration name. You must return name under which region will be registered, if you return NULL, initialization failed and all resources passed to callback are released. From my _current_ point of view we should end up with 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/