From b454cc6636d254fbf6049b73e9560aee76fb04a3 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 5 Feb 2007 16:28:25 -0800 Subject: [TC] MIPS: TURBOchannel update to the driver model This is a set of changes to convert support for the TURBOchannel bus to the driver model. It implements the usual set of calls similar to what other bus drivers have: tc_register_driver(), tc_unregister_driver(), etc. All the platform-specific bits have been removed and headers from asm-mips/dec/ have been merged into linux/tc.h, which should be included by drivers. Signed-off-by: Maciej W. Rozycki Signed-off-by: Andrew Morton Signed-off-by: Ralf Baechle --- drivers/tc/Makefile | 2 +- drivers/tc/tc-driver.c | 110 ++++++++++++++++ drivers/tc/tc.c | 339 ++++++++++++++++++++----------------------------- 3 files changed, 250 insertions(+), 201 deletions(-) create mode 100644 drivers/tc/tc-driver.c (limited to 'drivers') diff --git a/drivers/tc/Makefile b/drivers/tc/Makefile index 83b5bd75ce26..967342692211 100644 --- a/drivers/tc/Makefile +++ b/drivers/tc/Makefile @@ -4,7 +4,7 @@ # Object file lists. -obj-$(CONFIG_TC) += tc.o +obj-$(CONFIG_TC) += tc.o tc-driver.o obj-$(CONFIG_ZS) += zs.o obj-$(CONFIG_VT) += lk201.o lk201-map.o lk201-remap.o diff --git a/drivers/tc/tc-driver.c b/drivers/tc/tc-driver.c new file mode 100644 index 000000000000..16b5bae63c74 --- /dev/null +++ b/drivers/tc/tc-driver.c @@ -0,0 +1,110 @@ +/* + * TURBOchannel driver services. + * + * Copyright (c) 2005 James Simmons + * Copyright (c) 2006 Maciej W. Rozycki + * + * Loosely based on drivers/dio/dio-driver.c and + * drivers/pci/pci-driver.c. + * + * This file is subject to the terms and conditions of the GNU + * General Public License. See the file "COPYING" in the main + * directory of this archive for more details. + */ + +#include +#include +#include + +/** + * tc_register_driver - register a new TC driver + * @drv: the driver structure to register + * + * Adds the driver structure to the list of registered drivers + * Returns a negative value on error, otherwise 0. + * If no error occurred, the driver remains registered even if + * no device was claimed during registration. + */ +int tc_register_driver(struct tc_driver *tdrv) +{ + return driver_register(&tdrv->driver); +} +EXPORT_SYMBOL(tc_register_driver); + +/** + * tc_unregister_driver - unregister a TC driver + * @drv: the driver structure to unregister + * + * Deletes the driver structure from the list of registered TC drivers, + * gives it a chance to clean up by calling its remove() function for + * each device it was responsible for, and marks those devices as + * driverless. + */ +void tc_unregister_driver(struct tc_driver *tdrv) +{ + driver_unregister(&tdrv->driver); +} +EXPORT_SYMBOL(tc_unregister_driver); + +/** + * tc_match_device - tell if a TC device structure has a matching + * TC device ID structure + * @tdrv: the TC driver to earch for matching TC device ID strings + * @tdev: the TC device structure to match against + * + * Used by a driver to check whether a TC device present in the + * system is in its list of supported devices. Returns the matching + * tc_device_id structure or %NULL if there is no match. + */ +const struct tc_device_id *tc_match_device(struct tc_driver *tdrv, + struct tc_dev *tdev) +{ + const struct tc_device_id *id = tdrv->id_table; + + if (id) { + while (id->name[0] || id->vendor[0]) { + if (strcmp(tdev->name, id->name) == 0 && + strcmp(tdev->vendor, id->vendor) == 0) + return id; + id++; + } + } + return NULL; +} +EXPORT_SYMBOL(tc_match_device); + +/** + * tc_bus_match - Tell if a device structure has a matching + * TC device ID structure + * @dev: the device structure to match against + * @drv: the device driver to search for matching TC device ID strings + * + * Used by a driver to check whether a TC device present in the + * system is in its list of supported devices. Returns 1 if there + * is a match or 0 otherwise. + */ +static int tc_bus_match(struct device *dev, struct device_driver *drv) +{ + struct tc_dev *tdev = to_tc_dev(dev); + struct tc_driver *tdrv = to_tc_driver(drv); + const struct tc_device_id *id; + + id = tc_match_device(tdrv, tdev); + if (id) + return 1; + + return 0; +} + +struct bus_type tc_bus_type = { + .name = "tc", + .match = tc_bus_match, +}; +EXPORT_SYMBOL(tc_bus_type); + +static int __init tc_driver_init(void) +{ + return bus_register(&tc_bus_type); +} + +postcore_initcall(tc_driver_init); diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c index 4a51e56f85b6..5514e5283616 100644 --- a/drivers/tc/tc.c +++ b/drivers/tc/tc.c @@ -1,254 +1,193 @@ /* - * tc-init: We assume the TURBOchannel to be up and running so - * just probe for Modules and fill in the global data structure - * tc_bus. + * TURBOchannel bus services. * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. + * Copyright (c) Harald Koerfgen, 1998 + * Copyright (c) 2001, 2003, 2005, 2006 Maciej W. Rozycki + * Copyright (c) 2005 James Simmons * - * Copyright (c) Harald Koerfgen, 1998 - * Copyright (c) 2001, 2003, 2005 Maciej W. Rozycki + * This file is subject to the terms and conditions of the GNU + * General Public License. See the file "COPYING" in the main + * directory of this archive for more details. */ +#include +#include #include +#include #include +#include #include #include +#include #include -#include -#include #include -#include -#include -#include -#include -#include -#include - -MODULE_LICENSE("GPL"); -slot_info tc_bus[MAX_SLOT]; -static int num_tcslots; -static tcinfo *info; +static struct tc_bus tc_bus = { + .name = "TURBOchannel", +}; /* - * Interface to the world. Read comment in include/asm-mips/tc.h. + * Probing for TURBOchannel modules. */ - -int search_tc_card(const char *name) -{ - int slot; - slot_info *sip; - - for (slot = 0; slot < num_tcslots; slot++) { - sip = &tc_bus[slot]; - if ((sip->flags & FREE) && - (strncmp(sip->name, name, strlen(name)) == 0)) { - return slot; - } - } - - return -ENODEV; -} - -void claim_tc_card(int slot) -{ - if (tc_bus[slot].flags & IN_USE) { - printk("claim_tc_card: attempting to claim a card already in use\n"); - return; - } - tc_bus[slot].flags &= ~FREE; - tc_bus[slot].flags |= IN_USE; -} - -void release_tc_card(int slot) +static void __init tc_bus_add_devices(struct tc_bus *tbus) { - if (tc_bus[slot].flags & FREE) { - printk("release_tc_card: " - "attempting to release a card already free\n"); - return; - } - tc_bus[slot].flags &= ~IN_USE; - tc_bus[slot].flags |= FREE; -} - -unsigned long get_tc_base_addr(int slot) -{ - return tc_bus[slot].base_addr; -} - -unsigned long get_tc_irq_nr(int slot) -{ - return tc_bus[slot].interrupt; -} - -unsigned long get_tc_speed(void) -{ - return 100000 * (10000 / (unsigned long)info->clk_period); -} - -/* - * Probing for TURBOchannel modules - */ -static void __init tc_probe(unsigned long startaddr, unsigned long size, - int slots) -{ - unsigned long slotaddr; + resource_size_t slotsize = tbus->info.slot_size << 20; + resource_size_t extslotsize = tbus->ext_slot_size; + resource_size_t slotaddr; + resource_size_t extslotaddr; + resource_size_t devsize; + void __iomem *module; + struct tc_dev *tdev; int i, slot, err; - long offset; u8 pattern[4]; - volatile u8 *module; + long offset; - for (slot = 0; slot < slots; slot++) { - slotaddr = startaddr + slot * size; - module = ioremap_nocache(slotaddr, size); + for (slot = 0; slot < tbus->num_tcslots; slot++) { + slotaddr = tbus->slot_base + slot * slotsize; + extslotaddr = tbus->ext_slot_base + slot * extslotsize; + module = ioremap_nocache(slotaddr, slotsize); BUG_ON(!module); - offset = OLDCARD; + offset = TC_OLDCARD; err = 0; - err |= get_dbe(pattern[0], module + OLDCARD + TC_PATTERN0); - err |= get_dbe(pattern[1], module + OLDCARD + TC_PATTERN1); - err |= get_dbe(pattern[2], module + OLDCARD + TC_PATTERN2); - err |= get_dbe(pattern[3], module + OLDCARD + TC_PATTERN3); - if (err) { - iounmap(module); - continue; - } + err |= tc_preadb(pattern + 0, module + offset + TC_PATTERN0); + err |= tc_preadb(pattern + 1, module + offset + TC_PATTERN1); + err |= tc_preadb(pattern + 2, module + offset + TC_PATTERN2); + err |= tc_preadb(pattern + 3, module + offset + TC_PATTERN3); + if (err) + goto out_err; if (pattern[0] != 0x55 || pattern[1] != 0x00 || pattern[2] != 0xaa || pattern[3] != 0xff) { - offset = NEWCARD; + offset = TC_NEWCARD; err = 0; - err |= get_dbe(pattern[0], module + TC_PATTERN0); - err |= get_dbe(pattern[1], module + TC_PATTERN1); - err |= get_dbe(pattern[2], module + TC_PATTERN2); - err |= get_dbe(pattern[3], module + TC_PATTERN3); - if (err) { - iounmap(module); - continue; - } + err |= tc_preadb(pattern + 0, + module + offset + TC_PATTERN0); + err |= tc_preadb(pattern + 1, + module + offset + TC_PATTERN1); + err |= tc_preadb(pattern + 2, + module + offset + TC_PATTERN2); + err |= tc_preadb(pattern + 3, + module + offset + TC_PATTERN3); + if (err) + goto out_err; } if (pattern[0] != 0x55 || pattern[1] != 0x00 || - pattern[2] != 0xaa || pattern[3] != 0xff) { - iounmap(module); - continue; + pattern[2] != 0xaa || pattern[3] != 0xff) + goto out_err; + + /* Found a board, allocate it an entry in the list */ + tdev = kzalloc(sizeof(*tdev), GFP_KERNEL); + if (!tdev) { + printk(KERN_ERR "tc%x: unable to allocate tc_dev\n", + slot); + goto out_err; } + sprintf(tdev->dev.bus_id, "tc%x", slot); + tdev->bus = tbus; + tdev->dev.parent = &tbus->dev; + tdev->dev.bus = &tc_bus_type; + tdev->slot = slot; - tc_bus[slot].base_addr = slotaddr; for (i = 0; i < 8; i++) { - tc_bus[slot].firmware[i] = - module[TC_FIRM_VER + offset + 4 * i]; - tc_bus[slot].vendor[i] = - module[TC_VENDOR + offset + 4 * i]; - tc_bus[slot].name[i] = - module[TC_MODULE + offset + 4 * i]; + tdev->firmware[i] = + readb(module + offset + TC_FIRM_VER + 4 * i); + tdev->vendor[i] = + readb(module + offset + TC_VENDOR + 4 * i); + tdev->name[i] = + readb(module + offset + TC_MODULE + 4 * i); } - tc_bus[slot].firmware[8] = 0; - tc_bus[slot].vendor[8] = 0; - tc_bus[slot].name[8] = 0; - /* - * Looks unneccesary, but we may change - * TC? in the future - */ - switch (slot) { - case 0: - tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC0]; - break; - case 1: - tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC1]; - break; - case 2: - tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC2]; - break; - /* - * Yuck! DS5000/200 onboard devices - */ - case 5: - tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC5]; - break; - case 6: - tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC6]; - break; - default: - tc_bus[slot].interrupt = -1; - break; + tdev->firmware[8] = 0; + tdev->vendor[8] = 0; + tdev->name[8] = 0; + + pr_info("%s: %s %s %s\n", tdev->dev.bus_id, tdev->vendor, + tdev->name, tdev->firmware); + + devsize = readb(module + offset + TC_SLOT_SIZE); + devsize <<= 22; + if (devsize <= slotsize) { + tdev->resource.start = slotaddr; + tdev->resource.end = slotaddr + devsize - 1; + } else if (devsize <= extslotsize) { + tdev->resource.start = extslotaddr; + tdev->resource.end = extslotaddr + devsize - 1; + } else { + printk(KERN_ERR "%s: Cannot provide slot space " + "(%dMiB required, up to %dMiB supported)\n", + tdev->dev.bus_id, devsize >> 20, + max(slotsize, extslotsize) >> 20); + kfree(tdev); + goto out_err; } + tdev->resource.name = tdev->name; + tdev->resource.flags = IORESOURCE_MEM; + + tc_device_get_irq(tdev); + device_register(&tdev->dev); + list_add_tail(&tdev->node, &tbus->devices); + +out_err: iounmap(module); } } /* - * the main entry + * The main entry. */ static int __init tc_init(void) { - int tc_clock; - int i; - unsigned long slot0addr; - unsigned long slot_size; - - if (!TURBOCHANNEL) + /* Initialize the TURBOchannel bus */ + if (tc_bus_get_info(&tc_bus)) return 0; - for (i = 0; i < MAX_SLOT; i++) { - tc_bus[i].base_addr = 0; - tc_bus[i].name[0] = 0; - tc_bus[i].vendor[0] = 0; - tc_bus[i].firmware[0] = 0; - tc_bus[i].interrupt = -1; - tc_bus[i].flags = FREE; - } - - info = rex_gettcinfo(); - slot0addr = CPHYSADDR((long)rex_slot_address(0)); - - switch (mips_machtype) { - case MACH_DS5000_200: - num_tcslots = 7; - break; - case MACH_DS5000_1XX: - case MACH_DS5000_2X0: - case MACH_DS5900: - num_tcslots = 3; - break; - case MACH_DS5000_XX: - default: - num_tcslots = 2; - break; - } - - tc_clock = 10000 / info->clk_period; - - if (info->slot_size && slot0addr) { - pr_info("TURBOchannel rev. %d at %d.%d MHz (with%s parity)\n", - info->revision, tc_clock / 10, tc_clock % 10, - info->parity ? "" : "out"); - - slot_size = info->slot_size << 20; - - tc_probe(slot0addr, slot_size, num_tcslots); - - for (i = 0; i < num_tcslots; i++) { - if (!tc_bus[i].base_addr) - continue; - pr_info(" slot %d: %s %s %s\n", i, tc_bus[i].vendor, - tc_bus[i].name, tc_bus[i].firmware); + INIT_LIST_HEAD(&tc_bus.devices); + strcpy(tc_bus.dev.bus_id, "tc"); + device_register(&tc_bus.dev); + + if (tc_bus.info.slot_size) { + unsigned int tc_clock = tc_get_speed(&tc_bus) / 100000; + + pr_info("tc: TURBOchannel rev. %d at %d.%d MHz " + "(with%s parity)\n", tc_bus.info.revision, + tc_clock / 10, tc_clock % 10, + tc_bus.info.parity ? "" : "out"); + + tc_bus.resource[0].start = tc_bus.slot_base; + tc_bus.resource[0].end = tc_bus.slot_base + + (tc_bus.info.slot_size << 20) * + tc_bus.num_tcslots; + tc_bus.resource[0].name = tc_bus.name; + tc_bus.resource[0].flags = IORESOURCE_MEM; + if (request_resource(&iomem_resource, + &tc_bus.resource[0]) < 0) { + printk(KERN_ERR "tc: Cannot reserve resource\n"); + return 0; + } + if (tc_bus.ext_slot_size) { + tc_bus.resource[1].start = tc_bus.ext_slot_base; + tc_bus.resource[1].end = tc_bus.ext_slot_base + + tc_bus.ext_slot_size * + tc_bus.num_tcslots; + tc_bus.resource[1].name = tc_bus.name; + tc_bus.resource[1].flags = IORESOURCE_MEM; + if (request_resource(&iomem_resource, + &tc_bus.resource[1]) < 0) { + printk(KERN_ERR + "tc: Cannot reserve resource\n"); + release_resource(&tc_bus.resource[0]); + return 0; + } } + + tc_bus_add_devices(&tc_bus); } return 0; } subsys_initcall(tc_init); - -EXPORT_SYMBOL(search_tc_card); -EXPORT_SYMBOL(claim_tc_card); -EXPORT_SYMBOL(release_tc_card); -EXPORT_SYMBOL(get_tc_base_addr); -EXPORT_SYMBOL(get_tc_irq_nr); -EXPORT_SYMBOL(get_tc_speed); -- cgit v1.2.2 From 56a47da1b940b6d3812de67fd94af9bfda6ee93a Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 5 Feb 2007 16:28:26 -0800 Subject: [TC] MIPS: TURBOchannel resources off-by-one fix Fix resource reservation of TURBOchannel areas, where the end is one byte too far. Signed-off-by: Maciej W. Rozycki Signed-off-by: Andrew Morton Signed-off-by: Ralf Baechle --- drivers/tc/tc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c index 5514e5283616..f77f62a4b325 100644 --- a/drivers/tc/tc.c +++ b/drivers/tc/tc.c @@ -160,7 +160,7 @@ static int __init tc_init(void) tc_bus.resource[0].start = tc_bus.slot_base; tc_bus.resource[0].end = tc_bus.slot_base + (tc_bus.info.slot_size << 20) * - tc_bus.num_tcslots; + tc_bus.num_tcslots - 1; tc_bus.resource[0].name = tc_bus.name; tc_bus.resource[0].flags = IORESOURCE_MEM; if (request_resource(&iomem_resource, @@ -172,7 +172,7 @@ static int __init tc_init(void) tc_bus.resource[1].start = tc_bus.ext_slot_base; tc_bus.resource[1].end = tc_bus.ext_slot_base + tc_bus.ext_slot_size * - tc_bus.num_tcslots; + tc_bus.num_tcslots - 1; tc_bus.resource[1].name = tc_bus.name; tc_bus.resource[1].flags = IORESOURCE_MEM; if (request_resource(&iomem_resource, -- cgit v1.2.2 From e89a2cfb7d7b5a658295fef9be84b12e813163bd Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 5 Feb 2007 16:28:27 -0800 Subject: [TC] defxx: TURBOchannel support This is a set of changes to add TURBOchannel support to the defxx driver. As at this point the EISA support in the driver has become the only not having been converted to the driver model, I took the opportunity to convert it as well. Plus support for MMIO in addition to PIO operation as TURBOchannel requires it anyway. Signed-off-by: Maciej W. Rozycki Signed-off-by: Andrew Morton Acked-by: Jeff Garzik Signed-off-by: Ralf Baechle --- drivers/net/Kconfig | 32 +- drivers/net/defxx.c | 928 ++++++++++++++++++++++++++++++++++------------------ drivers/net/defxx.h | 58 ++-- 3 files changed, 664 insertions(+), 354 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ad92b6a76ee6..b79711d441a4 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2534,7 +2534,7 @@ config RIONET_RX_SIZE config FDDI bool "FDDI driver support" - depends on (PCI || EISA) + depends on (PCI || EISA || TC) help Fiber Distributed Data Interface is a high speed local area network design; essentially a replacement for high speed Ethernet. FDDI can @@ -2544,11 +2544,31 @@ config FDDI will say N. config DEFXX - tristate "Digital DEFEA and DEFPA adapter support" - depends on FDDI && (PCI || EISA) - help - This is support for the DIGITAL series of EISA (DEFEA) and PCI - (DEFPA) controllers which can connect you to a local FDDI network. + tristate "Digital DEFTA/DEFEA/DEFPA adapter support" + depends on FDDI && (PCI || EISA || TC) + ---help--- + This is support for the DIGITAL series of TURBOchannel (DEFTA), + EISA (DEFEA) and PCI (DEFPA) controllers which can connect you + to a local FDDI network. + + To compile this driver as a module, choose M here: the module + will be called defxx. If unsure, say N. + +config DEFXX_MMIO + bool + prompt "Use MMIO instead of PIO" if PCI || EISA + depends on DEFXX + default n if PCI || EISA + default y + ---help--- + This instructs the driver to use EISA or PCI memory-mapped I/O + (MMIO) as appropriate instead of programmed I/O ports (PIO). + Enabling this gives an improvement in processing time in parts + of the driver, but it may cause problems with EISA (DEFEA) + adapters. TURBOchannel does not have the concept of I/O ports, + so MMIO is always used for these (DEFTA) adapters. + + If unsure, say N. config SKFP tristate "SysKonnect FDDI PCI support" diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index dc3ab3b5c8cb..07d2731c1aa8 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -10,10 +10,12 @@ * * Abstract: * A Linux device driver supporting the Digital Equipment Corporation - * FDDI EISA and PCI controller families. Supported adapters include: + * FDDI TURBOchannel, EISA and PCI controller families. Supported + * adapters include: * - * DEC FDDIcontroller/EISA (DEFEA) - * DEC FDDIcontroller/PCI (DEFPA) + * DEC FDDIcontroller/TURBOchannel (DEFTA) + * DEC FDDIcontroller/EISA (DEFEA) + * DEC FDDIcontroller/PCI (DEFPA) * * The original author: * LVS Lawrence V. Stefani @@ -193,24 +195,27 @@ * 14 Aug 2004 macro Fix device names reported. * 14 Jun 2005 macro Use irqreturn_t. * 23 Oct 2006 macro Big-endian host support. + * 14 Dec 2006 macro TURBOchannel support. */ /* Include files */ - -#include -#include -#include -#include -#include -#include -#include -#include +#include #include +#include +#include +#include +#include #include +#include +#include +#include +#include #include -#include +#include #include -#include +#include +#include +#include #include #include @@ -219,8 +224,8 @@ /* Version information string should be updated prior to each new release! */ #define DRV_NAME "defxx" -#define DRV_VERSION "v1.09" -#define DRV_RELDATE "2006/10/23" +#define DRV_VERSION "v1.10" +#define DRV_RELDATE "2006/12/14" static char version[] __devinitdata = DRV_NAME ": " DRV_VERSION " " DRV_RELDATE @@ -235,12 +240,41 @@ static char version[] __devinitdata = */ #define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128) +#define __unused __attribute__ ((unused)) + +#ifdef CONFIG_PCI +#define DFX_BUS_PCI(dev) (dev->bus == &pci_bus_type) +#else +#define DFX_BUS_PCI(dev) 0 +#endif + +#ifdef CONFIG_EISA +#define DFX_BUS_EISA(dev) (dev->bus == &eisa_bus_type) +#else +#define DFX_BUS_EISA(dev) 0 +#endif + +#ifdef CONFIG_TC +#define DFX_BUS_TC(dev) (dev->bus == &tc_bus_type) +#else +#define DFX_BUS_TC(dev) 0 +#endif + +#ifdef CONFIG_DEFXX_MMIO +#define DFX_MMIO 1 +#else +#define DFX_MMIO 0 +#endif + /* Define module-wide (static) routines */ static void dfx_bus_init(struct net_device *dev); +static void dfx_bus_uninit(struct net_device *dev); static void dfx_bus_config_check(DFX_board_t *bp); -static int dfx_driver_init(struct net_device *dev, const char *print_name); +static int dfx_driver_init(struct net_device *dev, + const char *print_name, + resource_size_t bar_start); static int dfx_adap_init(DFX_board_t *bp, int get_buffers); static int dfx_open(struct net_device *dev); @@ -273,13 +307,13 @@ static void dfx_xmt_flush(DFX_board_t *bp); /* Define module-wide (static) variables */ -static struct net_device *root_dfx_eisa_dev; +static struct pci_driver dfx_pci_driver; +static struct eisa_driver dfx_eisa_driver; +static struct tc_driver dfx_tc_driver; /* * ======================= - * = dfx_port_write_byte = - * = dfx_port_read_byte = * = dfx_port_write_long = * = dfx_port_read_long = * ======================= @@ -291,12 +325,11 @@ static struct net_device *root_dfx_eisa_dev; * None * * Arguments: - * bp - pointer to board information - * offset - register offset from base I/O address - * data - for dfx_port_write_byte and dfx_port_write_long, this - * is a value to write. - * for dfx_port_read_byte and dfx_port_read_byte, this - * is a pointer to store the read value. + * bp - pointer to board information + * offset - register offset from base I/O address + * data - for dfx_port_write_long, this is a value to write; + * for dfx_port_read_long, this is a pointer to store + * the read value * * Functional Description: * These routines perform the correct operation to read or write @@ -310,7 +343,7 @@ static struct net_device *root_dfx_eisa_dev; * registers using the register offsets defined in DEFXX.H. * * PCI port block base addresses are assigned by the PCI BIOS or system - * firmware. There is one 128 byte port block which can be accessed. It + * firmware. There is one 128 byte port block which can be accessed. It * allows for I/O mapping of both PDQ and PFI registers using the register * offsets defined in DEFXX.H. * @@ -318,7 +351,7 @@ static struct net_device *root_dfx_eisa_dev; * None * * Assumptions: - * bp->base_addr is a valid base I/O address for this adapter. + * bp->base is a valid base I/O address for this adapter. * offset is a valid register offset for this adapter. * * Side Effects: @@ -329,69 +362,135 @@ static struct net_device *root_dfx_eisa_dev; * advantage of strict data type checking. */ -static inline void dfx_port_write_byte( - DFX_board_t *bp, - int offset, - u8 data - ) +static inline void dfx_writel(DFX_board_t *bp, int offset, u32 data) +{ + writel(data, bp->base.mem + offset); + mb(); +} - { - u16 port = bp->base_addr + offset; +static inline void dfx_outl(DFX_board_t *bp, int offset, u32 data) +{ + outl(data, bp->base.port + offset); +} - outb(data, port); - } +static void dfx_port_write_long(DFX_board_t *bp, int offset, u32 data) +{ + struct device __unused *bdev = bp->bus_dev; + int dfx_bus_tc = DFX_BUS_TC(bdev); + int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; -static inline void dfx_port_read_byte( - DFX_board_t *bp, - int offset, - u8 *data - ) + if (dfx_use_mmio) + dfx_writel(bp, offset, data); + else + dfx_outl(bp, offset, data); +} - { - u16 port = bp->base_addr + offset; - *data = inb(port); - } +static inline void dfx_readl(DFX_board_t *bp, int offset, u32 *data) +{ + mb(); + *data = readl(bp->base.mem + offset); +} -static inline void dfx_port_write_long( - DFX_board_t *bp, - int offset, - u32 data - ) +static inline void dfx_inl(DFX_board_t *bp, int offset, u32 *data) +{ + *data = inl(bp->base.port + offset); +} - { - u16 port = bp->base_addr + offset; +static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data) +{ + struct device __unused *bdev = bp->bus_dev; + int dfx_bus_tc = DFX_BUS_TC(bdev); + int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; - outl(data, port); - } + if (dfx_use_mmio) + dfx_readl(bp, offset, data); + else + dfx_inl(bp, offset, data); +} -static inline void dfx_port_read_long( - DFX_board_t *bp, - int offset, - u32 *data - ) - { - u16 port = bp->base_addr + offset; +/* + * ================ + * = dfx_get_bars = + * ================ + * + * Overview: + * Retrieves the address range used to access control and status + * registers. + * + * Returns: + * None + * + * Arguments: + * bdev - pointer to device information + * bar_start - pointer to store the start address + * bar_len - pointer to store the length of the area + * + * Assumptions: + * I am sure there are some. + * + * Side Effects: + * None + */ +static void dfx_get_bars(struct device *bdev, + resource_size_t *bar_start, resource_size_t *bar_len) +{ + int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_eisa = DFX_BUS_EISA(bdev); + int dfx_bus_tc = DFX_BUS_TC(bdev); + int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; - *data = inl(port); - } + if (dfx_bus_pci) { + int num = dfx_use_mmio ? 0 : 1; + *bar_start = pci_resource_start(to_pci_dev(bdev), num); + *bar_len = pci_resource_len(to_pci_dev(bdev), num); + } + if (dfx_bus_eisa) { + unsigned long base_addr = to_eisa_device(bdev)->base_addr; + resource_size_t bar; + + if (dfx_use_mmio) { + bar = inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_2); + bar <<= 8; + bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_1); + bar <<= 8; + bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_0); + bar <<= 16; + *bar_start = bar; + bar = inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_2); + bar <<= 8; + bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_1); + bar <<= 8; + bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_0); + bar <<= 16; + *bar_len = (bar | PI_MEM_ADD_MASK_M) + 1; + } else { + *bar_start = base_addr; + *bar_len = PI_ESIC_K_CSR_IO_LEN; + } + } + if (dfx_bus_tc) { + *bar_start = to_tc_dev(bdev)->resource.start + + PI_TC_K_CSR_OFFSET; + *bar_len = PI_TC_K_CSR_LEN; + } +} /* - * ============= - * = dfx_init_one_pci_or_eisa = - * ============= + * ================ + * = dfx_register = + * ================ * * Overview: - * Initializes a supported FDDI EISA or PCI controller + * Initializes a supported FDDI controller * * Returns: * Condition code * * Arguments: - * pdev - pointer to pci device information (NULL for EISA) - * ioaddr - pointer to port (NULL for PCI) + * bdev - pointer to device information * * Functional Description: * @@ -407,56 +506,74 @@ static inline void dfx_port_read_long( * initialized and the board resources are read and stored in * the device structure. */ -static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr) +static int __devinit dfx_register(struct device *bdev) { static int version_disp; - char *print_name = DRV_NAME; + int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_tc = DFX_BUS_TC(bdev); + int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; + char *print_name = bdev->bus_id; struct net_device *dev; DFX_board_t *bp; /* board pointer */ + resource_size_t bar_start = 0; /* pointer to port */ + resource_size_t bar_len = 0; /* resource length */ int alloc_size; /* total buffer size used */ - int err; + struct resource *region; + int err = 0; if (!version_disp) { /* display version info if adapter is found */ version_disp = 1; /* set display flag to TRUE so that */ printk(version); /* we only display this string ONCE */ } - if (pdev != NULL) - print_name = pci_name(pdev); - dev = alloc_fddidev(sizeof(*bp)); if (!dev) { - printk(KERN_ERR "%s: unable to allocate fddidev, aborting\n", + printk(KERN_ERR "%s: Unable to allocate fddidev, aborting\n", print_name); return -ENOMEM; } /* Enable PCI device. */ - if (pdev != NULL) { - err = pci_enable_device (pdev); - if (err) goto err_out; - ioaddr = pci_resource_start (pdev, 1); + if (dfx_bus_pci && pci_enable_device(to_pci_dev(bdev))) { + printk(KERN_ERR "%s: Cannot enable PCI device, aborting\n", + print_name); + goto err_out; } SET_MODULE_OWNER(dev); - if (pdev != NULL) - SET_NETDEV_DEV(dev, &pdev->dev); + SET_NETDEV_DEV(dev, bdev); + + bp = netdev_priv(dev); + bp->bus_dev = bdev; + dev_set_drvdata(bdev, dev); - bp = dev->priv; + dfx_get_bars(bdev, &bar_start, &bar_len); - if (!request_region(ioaddr, - pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, - print_name)) { + if (dfx_use_mmio) + region = request_mem_region(bar_start, bar_len, print_name); + else + region = request_region(bar_start, bar_len, print_name); + if (!region) { printk(KERN_ERR "%s: Cannot reserve I/O resource " - "0x%x @ 0x%lx, aborting\n", print_name, - pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, ioaddr); + "0x%lx @ 0x%lx, aborting\n", + print_name, (long)bar_len, (long)bar_start); err = -EBUSY; - goto err_out; + goto err_out_disable; } - /* Initialize new device structure */ + /* Set up I/O base address. */ + if (dfx_use_mmio) { + bp->base.mem = ioremap_nocache(bar_start, bar_len); + if (!bp->base.mem) { + printk(KERN_ERR "%s: Cannot map MMIO\n", print_name); + goto err_out_region; + } + } else { + bp->base.port = bar_start; + dev->base_addr = bar_start; + } - dev->base_addr = ioaddr; /* save port (I/O) base address */ + /* Initialize new device structure */ dev->get_stats = dfx_ctl_get_stats; dev->open = dfx_open; @@ -465,22 +582,12 @@ static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr) dev->set_multicast_list = dfx_ctl_set_multicast_list; dev->set_mac_address = dfx_ctl_set_mac_address; - if (pdev == NULL) { - /* EISA board */ - bp->bus_type = DFX_BUS_TYPE_EISA; - bp->next = root_dfx_eisa_dev; - root_dfx_eisa_dev = dev; - } else { - /* PCI board */ - bp->bus_type = DFX_BUS_TYPE_PCI; - bp->pci_dev = pdev; - pci_set_drvdata (pdev, dev); - pci_set_master (pdev); - } + if (dfx_bus_pci) + pci_set_master(to_pci_dev(bdev)); - if (dfx_driver_init(dev, print_name) != DFX_K_SUCCESS) { + if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) { err = -ENODEV; - goto err_out_region; + goto err_out_unmap; } err = register_netdev(dev); @@ -499,44 +606,28 @@ err_out_kfree: sizeof(PI_CONSUMER_BLOCK) + (PI_ALIGN_K_DESC_BLK - 1); if (bp->kmalloced) - pci_free_consistent(pdev, alloc_size, - bp->kmalloced, bp->kmalloced_dma); + dma_free_coherent(bdev, alloc_size, + bp->kmalloced, bp->kmalloced_dma); + +err_out_unmap: + if (dfx_use_mmio) + iounmap(bp->base.mem); + err_out_region: - release_region(ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN); + if (dfx_use_mmio) + release_mem_region(bar_start, bar_len); + else + release_region(bar_start, bar_len); + +err_out_disable: + if (dfx_bus_pci) + pci_disable_device(to_pci_dev(bdev)); + err_out: free_netdev(dev); return err; } -static int __devinit dfx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - return dfx_init_one_pci_or_eisa(pdev, 0); -} - -static int __init dfx_eisa_init(void) -{ - int rc = -ENODEV; - int i; /* used in for loops */ - u16 port; /* temporary I/O (port) address */ - u32 slot_id; /* EISA hardware (slot) ID read from adapter */ - - DBG_printk("In dfx_eisa_init...\n"); - - /* Scan for FDDI EISA controllers */ - - for (i=0; i < DFX_MAX_EISA_SLOTS; i++) /* only scan for up to 16 EISA slots */ - { - port = (i << 12) + PI_ESIC_K_SLOT_ID; /* port = I/O address for reading slot ID */ - slot_id = inl(port); /* read EISA HW (slot) ID */ - if ((slot_id & 0xF0FFFFFF) == DEFEA_PRODUCT_ID) - { - port = (i << 12); /* recalc base addr */ - - if (dfx_init_one_pci_or_eisa(NULL, port) == 0) rc = 0; - } - } - return rc; -} /* * ================ @@ -544,7 +635,7 @@ static int __init dfx_eisa_init(void) * ================ * * Overview: - * Initializes EISA and PCI controller bus-specific logic. + * Initializes the bus-specific controller logic. * * Returns: * None @@ -560,7 +651,7 @@ static int __init dfx_eisa_init(void) * None * * Assumptions: - * dev->base_addr has already been set with the proper + * bp->base has already been set with the proper * base I/O address for this device. * * Side Effects: @@ -571,87 +662,103 @@ static int __init dfx_eisa_init(void) static void __devinit dfx_bus_init(struct net_device *dev) { - DFX_board_t *bp = dev->priv; - u8 val; /* used for I/O read/writes */ + DFX_board_t *bp = netdev_priv(dev); + struct device *bdev = bp->bus_dev; + int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_eisa = DFX_BUS_EISA(bdev); + int dfx_bus_tc = DFX_BUS_TC(bdev); + int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; + u8 val; DBG_printk("In dfx_bus_init...\n"); - /* - * Initialize base I/O address field in bp structure - * - * Note: bp->base_addr is the same as dev->base_addr. - * It's useful because often we'll need to read - * or write registers where we already have the - * bp pointer instead of the dev pointer. Having - * the base address in the bp structure will - * save a pointer dereference. - * - * IMPORTANT!! This field must be defined before - * any of the dfx_port_* inline functions are - * called. - */ - - bp->base_addr = dev->base_addr; - - /* And a pointer back to the net_device struct */ + /* Initialize a pointer back to the net_device struct */ bp->dev = dev; /* Initialize adapter based on bus type */ - if (bp->bus_type == DFX_BUS_TYPE_EISA) - { - /* Get the interrupt level from the ESIC chip */ - - dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &val); - switch ((val & PI_CONFIG_STAT_0_M_IRQ) >> PI_CONFIG_STAT_0_V_IRQ) - { - case PI_CONFIG_STAT_0_IRQ_K_9: - dev->irq = 9; - break; - - case PI_CONFIG_STAT_0_IRQ_K_10: - dev->irq = 10; - break; + if (dfx_bus_tc) + dev->irq = to_tc_dev(bdev)->interrupt; + if (dfx_bus_eisa) { + unsigned long base_addr = to_eisa_device(bdev)->base_addr; - case PI_CONFIG_STAT_0_IRQ_K_11: - dev->irq = 11; - break; + /* Get the interrupt level from the ESIC chip. */ + val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0); + val &= PI_CONFIG_STAT_0_M_IRQ; + val >>= PI_CONFIG_STAT_0_V_IRQ; - case PI_CONFIG_STAT_0_IRQ_K_15: - dev->irq = 15; - break; - } - - /* Enable access to I/O on the board by writing 0x03 to Function Control Register */ + switch (val) { + case PI_CONFIG_STAT_0_IRQ_K_9: + dev->irq = 9; + break; - dfx_port_write_byte(bp, PI_ESIC_K_FUNCTION_CNTRL, PI_ESIC_K_FUNCTION_CNTRL_IO_ENB); + case PI_CONFIG_STAT_0_IRQ_K_10: + dev->irq = 10; + break; - /* Set the I/O decode range of the board */ + case PI_CONFIG_STAT_0_IRQ_K_11: + dev->irq = 11; + break; - val = ((dev->base_addr >> 12) << PI_IO_CMP_V_SLOT); - dfx_port_write_byte(bp, PI_ESIC_K_IO_CMP_0_1, val); - dfx_port_write_byte(bp, PI_ESIC_K_IO_CMP_1_1, val); + case PI_CONFIG_STAT_0_IRQ_K_15: + dev->irq = 15; + break; + } - /* Enable access to rest of module (including PDQ and packet memory) */ + /* + * Enable memory decoding (MEMCS0) and/or port decoding + * (IOCS1/IOCS0) as appropriate in Function Control + * Register. One of the port chip selects seems to be + * used for the Burst Holdoff register, but this bit of + * documentation is missing and as yet it has not been + * determined which of the two. This is also the reason + * the size of the decoded port range is twice as large + * as one required by the PDQ. + */ - dfx_port_write_byte(bp, PI_ESIC_K_SLOT_CNTRL, PI_SLOT_CNTRL_M_ENB); + /* Set the decode range of the board. */ + val = ((bp->base.port >> 12) << PI_IO_CMP_V_SLOT); + outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_1, val); + outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_0, 0); + outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_1, val); + outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_0, 0); + val = PI_ESIC_K_CSR_IO_LEN - 1; + outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_1, (val >> 8) & 0xff); + outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_0, val & 0xff); + outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_1, (val >> 8) & 0xff); + outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_0, val & 0xff); + + /* Enable the decoders. */ + val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0; + if (dfx_use_mmio) + val |= PI_FUNCTION_CNTRL_M_MEMCS0; + outb(base_addr + PI_ESIC_K_FUNCTION_CNTRL, val); /* - * Map PDQ registers into I/O space. This is done by clearing a bit - * in Burst Holdoff register. + * Enable access to the rest of the module + * (including PDQ and packet memory). */ + val = PI_SLOT_CNTRL_M_ENB; + outb(base_addr + PI_ESIC_K_SLOT_CNTRL, val); - dfx_port_read_byte(bp, PI_ESIC_K_BURST_HOLDOFF, &val); - dfx_port_write_byte(bp, PI_ESIC_K_BURST_HOLDOFF, (val & ~PI_BURST_HOLDOFF_M_MEM_MAP)); + /* + * Map PDQ registers into memory or port space. This is + * done with a bit in the Burst Holdoff register. + */ + val = inb(base_addr + PI_DEFEA_K_BURST_HOLDOFF); + if (dfx_use_mmio) + val |= PI_BURST_HOLDOFF_V_MEM_MAP; + else + val &= ~PI_BURST_HOLDOFF_V_MEM_MAP; + outb(base_addr + PI_DEFEA_K_BURST_HOLDOFF, val); /* Enable interrupts at EISA bus interface chip (ESIC) */ - - dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &val); - dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, (val | PI_CONFIG_STAT_0_M_INT_ENB)); - } - else - { - struct pci_dev *pdev = bp->pci_dev; + val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0); + val |= PI_CONFIG_STAT_0_M_INT_ENB; + outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val); + } + if (dfx_bus_pci) { + struct pci_dev *pdev = to_pci_dev(bdev); /* Get the interrupt level from the PCI Configuration Table */ @@ -660,17 +767,70 @@ static void __devinit dfx_bus_init(struct net_device *dev) /* Check Latency Timer and set if less than minimal */ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val); - if (val < PFI_K_LAT_TIMER_MIN) /* if less than min, override with default */ - { + if (val < PFI_K_LAT_TIMER_MIN) { val = PFI_K_LAT_TIMER_DEF; pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val); - } + } /* Enable interrupts at PCI bus interface chip (PFI) */ + val = PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB; + dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, val); + } +} - dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, (PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB)); - } +/* + * ================== + * = dfx_bus_uninit = + * ================== + * + * Overview: + * Uninitializes the bus-specific controller logic. + * + * Returns: + * None + * + * Arguments: + * dev - pointer to device information + * + * Functional Description: + * Perform bus-specific logic uninitialization. + * + * Return Codes: + * None + * + * Assumptions: + * bp->base has already been set with the proper + * base I/O address for this device. + * + * Side Effects: + * Interrupts are disabled at the adapter bus-specific logic. + */ + +static void __devinit dfx_bus_uninit(struct net_device *dev) +{ + DFX_board_t *bp = netdev_priv(dev); + struct device *bdev = bp->bus_dev; + int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_eisa = DFX_BUS_EISA(bdev); + u8 val; + + DBG_printk("In dfx_bus_uninit...\n"); + + /* Uninitialize adapter based on bus type */ + + if (dfx_bus_eisa) { + unsigned long base_addr = to_eisa_device(bdev)->base_addr; + + /* Disable interrupts at EISA bus interface chip (ESIC) */ + val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0); + val &= ~PI_CONFIG_STAT_0_M_INT_ENB; + outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val); + } + if (dfx_bus_pci) { + /* Disable interrupts at PCI bus interface chip (PFI) */ + dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, 0); } +} /* @@ -705,18 +865,16 @@ static void __devinit dfx_bus_init(struct net_device *dev) static void __devinit dfx_bus_config_check(DFX_board_t *bp) { + struct device __unused *bdev = bp->bus_dev; + int dfx_bus_eisa = DFX_BUS_EISA(bdev); int status; /* return code from adapter port control call */ - u32 slot_id; /* EISA-bus hardware id (DEC3001, DEC3002,...) */ u32 host_data; /* LW data returned from port control call */ DBG_printk("In dfx_bus_config_check...\n"); /* Configuration check only valid for EISA adapter */ - if (bp->bus_type == DFX_BUS_TYPE_EISA) - { - dfx_port_read_long(bp, PI_ESIC_K_SLOT_ID, &slot_id); - + if (dfx_bus_eisa) { /* * First check if revision 2 EISA controller. Rev. 1 cards used * PDQ revision B, so no workaround needed in this case. Rev. 3 @@ -724,14 +882,11 @@ static void __devinit dfx_bus_config_check(DFX_board_t *bp) * case, either. Only Rev. 2 cards used either Rev. D or E * chips, so we must verify the chip revision on Rev. 2 cards. */ - - if (slot_id == DEFEA_PROD_ID_2) - { + if (to_eisa_device(bdev)->id.driver_data == DEFEA_PROD_ID_2) { /* - * Revision 2 FDDI EISA controller found, so let's check PDQ - * revision of adapter. + * Revision 2 FDDI EISA controller found, + * so let's check PDQ revision of adapter. */ - status = dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_SUB_CMD, PI_SUB_CMD_K_PDQ_REV_GET, @@ -805,13 +960,20 @@ static void __devinit dfx_bus_config_check(DFX_board_t *bp) */ static int __devinit dfx_driver_init(struct net_device *dev, - const char *print_name) + const char *print_name, + resource_size_t bar_start) { - DFX_board_t *bp = dev->priv; - int alloc_size; /* total buffer size needed */ - char *top_v, *curr_v; /* virtual addrs into memory block */ - dma_addr_t top_p, curr_p; /* physical addrs into memory block */ - u32 data; /* host data register value */ + DFX_board_t *bp = netdev_priv(dev); + struct device *bdev = bp->bus_dev; + int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_eisa = DFX_BUS_EISA(bdev); + int dfx_bus_tc = DFX_BUS_TC(bdev); + int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; + int alloc_size; /* total buffer size needed */ + char *top_v, *curr_v; /* virtual addrs into memory block */ + dma_addr_t top_p, curr_p; /* physical addrs into memory block */ + u32 data, le32; /* host data register value */ + char *board_name = NULL; DBG_printk("In dfx_driver_init...\n"); @@ -860,8 +1022,8 @@ static int __devinit dfx_driver_init(struct net_device *dev, print_name); return(DFX_K_FAILURE); } - data = cpu_to_le32(data); - memcpy(&bp->factory_mac_addr[0], &data, sizeof(u32)); + le32 = cpu_to_le32(data); + memcpy(&bp->factory_mac_addr[0], &le32, sizeof(u32)); if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0, &data) != DFX_K_SUCCESS) { @@ -869,8 +1031,8 @@ static int __devinit dfx_driver_init(struct net_device *dev, print_name); return(DFX_K_FAILURE); } - data = cpu_to_le32(data); - memcpy(&bp->factory_mac_addr[4], &data, sizeof(u16)); + le32 = cpu_to_le32(data); + memcpy(&bp->factory_mac_addr[4], &le32, sizeof(u16)); /* * Set current address to factory address @@ -880,20 +1042,18 @@ static int __devinit dfx_driver_init(struct net_device *dev, */ memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN); - if (bp->bus_type == DFX_BUS_TYPE_EISA) - printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, " - "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", - print_name, dev->base_addr, dev->irq, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5]); - else - printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, " - "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", - print_name, dev->base_addr, dev->irq, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5]); + if (dfx_bus_tc) + board_name = "DEFTA"; + if (dfx_bus_eisa) + board_name = "DEFEA"; + if (dfx_bus_pci) + board_name = "DEFPA"; + pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, " + "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", + print_name, board_name, dfx_use_mmio ? "" : "I/O ", + (long long)bar_start, dev->irq, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); /* * Get memory for descriptor block, consumer block, and other buffers @@ -908,8 +1068,9 @@ static int __devinit dfx_driver_init(struct net_device *dev, #endif sizeof(PI_CONSUMER_BLOCK) + (PI_ALIGN_K_DESC_BLK - 1); - bp->kmalloced = top_v = pci_alloc_consistent(bp->pci_dev, alloc_size, - &bp->kmalloced_dma); + bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size, + &bp->kmalloced_dma, + GFP_ATOMIC); if (top_v == NULL) { printk("%s: Could not allocate memory for host buffers " "and structures!\n", print_name); @@ -1219,14 +1380,15 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers) static int dfx_open(struct net_device *dev) { + DFX_board_t *bp = netdev_priv(dev); int ret; - DFX_board_t *bp = dev->priv; DBG_printk("In dfx_open...\n"); /* Register IRQ - support shared interrupts by passing device ptr */ - ret = request_irq(dev->irq, dfx_interrupt, IRQF_SHARED, dev->name, dev); + ret = request_irq(dev->irq, dfx_interrupt, IRQF_SHARED, dev->name, + dev); if (ret) { printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq); return ret; @@ -1309,7 +1471,7 @@ static int dfx_open(struct net_device *dev) static int dfx_close(struct net_device *dev) { - DFX_board_t *bp = dev->priv; + DFX_board_t *bp = netdev_priv(dev); DBG_printk("In dfx_close...\n"); @@ -1645,7 +1807,7 @@ static void dfx_int_type_0_process(DFX_board_t *bp) static void dfx_int_common(struct net_device *dev) { - DFX_board_t *bp = dev->priv; + DFX_board_t *bp = netdev_priv(dev); PI_UINT32 port_status; /* Port Status register */ /* Process xmt interrupts - frequent case, so always call this routine */ @@ -1715,18 +1877,16 @@ static void dfx_int_common(struct net_device *dev) static irqreturn_t dfx_interrupt(int irq, void *dev_id) { - struct net_device *dev = dev_id; - DFX_board_t *bp; /* private board structure pointer */ - - /* Get board pointer only if device structure is valid */ - - bp = dev->priv; - - /* See if we're already servicing an interrupt */ + struct net_device *dev = dev_id; + DFX_board_t *bp = netdev_priv(dev); + struct device *bdev = bp->bus_dev; + int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_eisa = DFX_BUS_EISA(bdev); + int dfx_bus_tc = DFX_BUS_TC(bdev); /* Service adapter interrupts */ - if (bp->bus_type == DFX_BUS_TYPE_PCI) { + if (dfx_bus_pci) { u32 status; dfx_port_read_long(bp, PFI_K_REG_STATUS, &status); @@ -1750,10 +1910,12 @@ static irqreturn_t dfx_interrupt(int irq, void *dev_id) PFI_MODE_M_DMA_ENB)); spin_unlock(&bp->lock); - } else { + } + if (dfx_bus_eisa) { + unsigned long base_addr = to_eisa_device(bdev)->base_addr; u8 status; - dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status); + status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0); if (!(status & PI_CONFIG_STAT_0_M_PEND)) return IRQ_NONE; @@ -1761,15 +1923,35 @@ static irqreturn_t dfx_interrupt(int irq, void *dev_id) /* Disable interrupts at the ESIC */ status &= ~PI_CONFIG_STAT_0_M_INT_ENB; - dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status); + outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status); /* Call interrupt service routine for this adapter */ dfx_int_common(dev); /* Reenable interrupts at the ESIC */ - dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status); + status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0); status |= PI_CONFIG_STAT_0_M_INT_ENB; - dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status); + outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status); + + spin_unlock(&bp->lock); + } + if (dfx_bus_tc) { + u32 status; + + dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &status); + if (!(status & (PI_PSTATUS_M_RCV_DATA_PENDING | + PI_PSTATUS_M_XMT_DATA_PENDING | + PI_PSTATUS_M_SMT_HOST_PENDING | + PI_PSTATUS_M_UNSOL_PENDING | + PI_PSTATUS_M_CMD_RSP_PENDING | + PI_PSTATUS_M_CMD_REQ_PENDING | + PI_PSTATUS_M_TYPE_0_PENDING))) + return IRQ_NONE; + + spin_lock(&bp->lock); + + /* Call interrupt service routine for this adapter */ + dfx_int_common(dev); spin_unlock(&bp->lock); } @@ -1823,7 +2005,7 @@ static irqreturn_t dfx_interrupt(int irq, void *dev_id) static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev) { - DFX_board_t *bp = dev->priv; + DFX_board_t *bp = netdev_priv(dev); /* Fill the bp->stats structure with driver-maintained counters */ @@ -2009,8 +2191,8 @@ static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev) */ static void dfx_ctl_set_multicast_list(struct net_device *dev) - { - DFX_board_t *bp = dev->priv; +{ + DFX_board_t *bp = netdev_priv(dev); int i; /* used as index in for loop */ struct dev_mc_list *dmi; /* ptr to multicast addr entry */ @@ -2124,8 +2306,8 @@ static void dfx_ctl_set_multicast_list(struct net_device *dev) static int dfx_ctl_set_mac_address(struct net_device *dev, void *addr) { - DFX_board_t *bp = dev->priv; struct sockaddr *p_sockaddr = (struct sockaddr *)addr; + DFX_board_t *bp = netdev_priv(dev); /* Copy unicast address to driver-maintained structs and update count */ @@ -2764,9 +2946,9 @@ static int dfx_rcv_init(DFX_board_t *bp, int get_buffers) my_skb_align(newskb, 128); bp->descr_block_virt->rcv_data[i + j].long_1 = - (u32)pci_map_single(bp->pci_dev, newskb->data, + (u32)dma_map_single(bp->bus_dev, newskb->data, NEW_SKB_SIZE, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); /* * p_rcv_buff_va is only used inside the * kernel so we put the skb pointer here. @@ -2880,17 +3062,17 @@ static void dfx_rcv_queue_process( my_skb_align(newskb, 128); skb = (struct sk_buff *)bp->p_rcv_buff_va[entry]; - pci_unmap_single(bp->pci_dev, + dma_unmap_single(bp->bus_dev, bp->descr_block_virt->rcv_data[entry].long_1, NEW_SKB_SIZE, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); skb_reserve(skb, RCV_BUFF_K_PADDING); bp->p_rcv_buff_va[entry] = (char *)newskb; bp->descr_block_virt->rcv_data[entry].long_1 = - (u32)pci_map_single(bp->pci_dev, + (u32)dma_map_single(bp->bus_dev, newskb->data, NEW_SKB_SIZE, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); } else skb = NULL; } else @@ -3010,7 +3192,7 @@ static int dfx_xmt_queue_pkt( ) { - DFX_board_t *bp = dev->priv; + DFX_board_t *bp = netdev_priv(dev); u8 prod; /* local transmit producer index */ PI_XMT_DESCR *p_xmt_descr; /* ptr to transmit descriptor block entry */ XMT_DRIVER_DESCR *p_xmt_drv_descr; /* ptr to transmit driver descriptor */ @@ -3116,8 +3298,8 @@ static int dfx_xmt_queue_pkt( */ p_xmt_descr->long_0 = (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len) << PI_XMT_DESCR_V_SEG_LEN)); - p_xmt_descr->long_1 = (u32)pci_map_single(bp->pci_dev, skb->data, - skb->len, PCI_DMA_TODEVICE); + p_xmt_descr->long_1 = (u32)dma_map_single(bp->bus_dev, skb->data, + skb->len, DMA_TO_DEVICE); /* * Verify that descriptor is actually available @@ -3220,10 +3402,10 @@ static int dfx_xmt_done(DFX_board_t *bp) /* Return skb to operating system */ comp = bp->rcv_xmt_reg.index.xmt_comp; - pci_unmap_single(bp->pci_dev, + dma_unmap_single(bp->bus_dev, bp->descr_block_virt->xmt_data[comp].long_1, p_xmt_drv_descr->p_skb->len, - PCI_DMA_TODEVICE); + DMA_TO_DEVICE); dev_kfree_skb_irq(p_xmt_drv_descr->p_skb); /* @@ -3344,10 +3526,10 @@ static void dfx_xmt_flush( DFX_board_t *bp ) /* Return skb to operating system */ comp = bp->rcv_xmt_reg.index.xmt_comp; - pci_unmap_single(bp->pci_dev, + dma_unmap_single(bp->bus_dev, bp->descr_block_virt->xmt_data[comp].long_1, p_xmt_drv_descr->p_skb->len, - PCI_DMA_TODEVICE); + DMA_TO_DEVICE); dev_kfree_skb(p_xmt_drv_descr->p_skb); /* Increment transmit error counter */ @@ -3375,13 +3557,44 @@ static void dfx_xmt_flush( DFX_board_t *bp ) bp->cons_block_virt->xmt_rcv_data = prod_cons; } -static void __devexit dfx_remove_one_pci_or_eisa(struct pci_dev *pdev, struct net_device *dev) +/* + * ================== + * = dfx_unregister = + * ================== + * + * Overview: + * Shuts down an FDDI controller + * + * Returns: + * Condition code + * + * Arguments: + * bdev - pointer to device information + * + * Functional Description: + * + * Return Codes: + * None + * + * Assumptions: + * It compiles so it should work :-( (PCI cards do :-) + * + * Side Effects: + * Device structures for FDDI adapters (fddi0, fddi1, etc) are + * freed. + */ +static void __devexit dfx_unregister(struct device *bdev) { - DFX_board_t *bp = dev->priv; + struct net_device *dev = dev_get_drvdata(bdev); + DFX_board_t *bp = netdev_priv(dev); + int dfx_bus_pci = DFX_BUS_PCI(bdev); + int dfx_bus_tc = DFX_BUS_TC(bdev); + int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; + resource_size_t bar_start = 0; /* pointer to port */ + resource_size_t bar_len = 0; /* resource length */ int alloc_size; /* total buffer size used */ unregister_netdev(dev); - release_region(dev->base_addr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN ); alloc_size = sizeof(PI_DESCR_BLOCK) + PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX + @@ -3391,78 +3604,141 @@ static void __devexit dfx_remove_one_pci_or_eisa(struct pci_dev *pdev, struct ne sizeof(PI_CONSUMER_BLOCK) + (PI_ALIGN_K_DESC_BLK - 1); if (bp->kmalloced) - pci_free_consistent(pdev, alloc_size, bp->kmalloced, - bp->kmalloced_dma); + dma_free_coherent(bdev, alloc_size, + bp->kmalloced, bp->kmalloced_dma); + + dfx_bus_uninit(dev); + + dfx_get_bars(bdev, &bar_start, &bar_len); + if (dfx_use_mmio) { + iounmap(bp->base.mem); + release_mem_region(bar_start, bar_len); + } else + release_region(bar_start, bar_len); + + if (dfx_bus_pci) + pci_disable_device(to_pci_dev(bdev)); + free_netdev(dev); } -static void __devexit dfx_remove_one (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - dfx_remove_one_pci_or_eisa(pdev, dev); - pci_set_drvdata(pdev, NULL); -} +static int __devinit __unused dfx_dev_register(struct device *); +static int __devexit __unused dfx_dev_unregister(struct device *); -static struct pci_device_id dfx_pci_tbl[] = { - { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, } +#ifdef CONFIG_PCI +static int __devinit dfx_pci_register(struct pci_dev *, + const struct pci_device_id *); +static void __devexit dfx_pci_unregister(struct pci_dev *); + +static struct pci_device_id dfx_pci_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) }, + { } }; -MODULE_DEVICE_TABLE(pci, dfx_pci_tbl); +MODULE_DEVICE_TABLE(pci, dfx_pci_table); -static struct pci_driver dfx_driver = { +static struct pci_driver dfx_pci_driver = { .name = "defxx", - .probe = dfx_init_one, - .remove = __devexit_p(dfx_remove_one), - .id_table = dfx_pci_tbl, + .id_table = dfx_pci_table, + .probe = dfx_pci_register, + .remove = __devexit_p(dfx_pci_unregister), }; -static int dfx_have_pci; -static int dfx_have_eisa; - +static __devinit int dfx_pci_register(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + return dfx_register(&pdev->dev); +} -static void __exit dfx_eisa_cleanup(void) +static void __devexit dfx_pci_unregister(struct pci_dev *pdev) { - struct net_device *dev = root_dfx_eisa_dev; + dfx_unregister(&pdev->dev); +} +#endif /* CONFIG_PCI */ + +#ifdef CONFIG_EISA +static struct eisa_device_id dfx_eisa_table[] = { + { "DEC3001", DEFEA_PROD_ID_1 }, + { "DEC3002", DEFEA_PROD_ID_2 }, + { "DEC3003", DEFEA_PROD_ID_3 }, + { "DEC3004", DEFEA_PROD_ID_4 }, + { } +}; +MODULE_DEVICE_TABLE(eisa, dfx_eisa_table); + +static struct eisa_driver dfx_eisa_driver = { + .id_table = dfx_eisa_table, + .driver = { + .name = "defxx", + .bus = &eisa_bus_type, + .probe = dfx_dev_register, + .remove = __devexit_p(dfx_dev_unregister), + }, +}; +#endif /* CONFIG_EISA */ + +#ifdef CONFIG_TC +static struct tc_device_id const dfx_tc_table[] = { + { "DEC ", "PMAF-FA " }, + { "DEC ", "PMAF-FD " }, + { "DEC ", "PMAF-FS " }, + { "DEC ", "PMAF-FU " }, + { } +}; +MODULE_DEVICE_TABLE(tc, dfx_tc_table); + +static struct tc_driver dfx_tc_driver = { + .id_table = dfx_tc_table, + .driver = { + .name = "defxx", + .bus = &tc_bus_type, + .probe = dfx_dev_register, + .remove = __devexit_p(dfx_dev_unregister), + }, +}; +#endif /* CONFIG_TC */ - while (dev) - { - struct net_device *tmp; - DFX_board_t *bp; +static int __devinit __unused dfx_dev_register(struct device *dev) +{ + int status; - bp = (DFX_board_t*)dev->priv; - tmp = bp->next; - dfx_remove_one_pci_or_eisa(NULL, dev); - dev = tmp; - } + status = dfx_register(dev); + if (!status) + get_device(dev); + return status; } -static int __init dfx_init(void) +static int __devexit __unused dfx_dev_unregister(struct device *dev) { - int rc_pci, rc_eisa; - - rc_pci = pci_register_driver(&dfx_driver); - if (rc_pci >= 0) dfx_have_pci = 1; + put_device(dev); + dfx_unregister(dev); + return 0; +} - rc_eisa = dfx_eisa_init(); - if (rc_eisa >= 0) dfx_have_eisa = 1; - return ((rc_eisa < 0) ? 0 : rc_eisa) + ((rc_pci < 0) ? 0 : rc_pci); +static int __devinit dfx_init(void) +{ + int status; + + status = pci_register_driver(&dfx_pci_driver); + if (!status) + status = eisa_driver_register(&dfx_eisa_driver); + if (!status) + status = tc_register_driver(&dfx_tc_driver); + return status; } -static void __exit dfx_cleanup(void) +static void __devexit dfx_cleanup(void) { - if (dfx_have_pci) - pci_unregister_driver(&dfx_driver); - if (dfx_have_eisa) - dfx_eisa_cleanup(); - + tc_unregister_driver(&dfx_tc_driver); + eisa_driver_unregister(&dfx_eisa_driver); + pci_unregister_driver(&dfx_pci_driver); } module_init(dfx_init); module_exit(dfx_cleanup); MODULE_AUTHOR("Lawrence V. Stefani"); -MODULE_DESCRIPTION("DEC FDDIcontroller EISA/PCI (DEFEA/DEFPA) driver " +MODULE_DESCRIPTION("DEC FDDIcontroller TC/EISA/PCI (DEFTA/DEFEA/DEFPA) driver " DRV_VERSION " " DRV_RELDATE); MODULE_LICENSE("GPL"); diff --git a/drivers/net/defxx.h b/drivers/net/defxx.h index 2ce8f97253eb..19a6f64df198 100644 --- a/drivers/net/defxx.h +++ b/drivers/net/defxx.h @@ -26,6 +26,7 @@ * 12-Sep-96 LVS Removed packet request header pointers. * 04 Aug 2003 macro Converted to the DMA API. * 23 Oct 2006 macro Big-endian host support. + * 14 Dec 2006 macro TURBOchannel support. */ #ifndef _DEFXX_H_ @@ -1471,9 +1472,17 @@ typedef union #endif /* __BIG_ENDIAN */ +/* Define TC PDQ CSR offset and length */ + +#define PI_TC_K_CSR_OFFSET 0x100000 +#define PI_TC_K_CSR_LEN 0x40 /* 64 bytes */ + /* Define EISA controller register offsets */ -#define PI_ESIC_K_BURST_HOLDOFF 0x040 +#define PI_ESIC_K_CSR_IO_LEN 0x80 /* 128 bytes */ + +#define PI_DEFEA_K_BURST_HOLDOFF 0x040 + #define PI_ESIC_K_SLOT_ID 0xC80 #define PI_ESIC_K_SLOT_CNTRL 0xC84 #define PI_ESIC_K_MEM_ADD_CMP_0 0xC85 @@ -1488,14 +1497,14 @@ typedef union #define PI_ESIC_K_MEM_ADD_LO_CMP_0 0xC8E #define PI_ESIC_K_MEM_ADD_LO_CMP_1 0xC8F #define PI_ESIC_K_MEM_ADD_LO_CMP_2 0xC90 -#define PI_ESIC_K_IO_CMP_0_0 0xC91 -#define PI_ESIC_K_IO_CMP_0_1 0xC92 -#define PI_ESIC_K_IO_CMP_1_0 0xC93 -#define PI_ESIC_K_IO_CMP_1_1 0xC94 -#define PI_ESIC_K_IO_CMP_2_0 0xC95 -#define PI_ESIC_K_IO_CMP_2_1 0xC96 -#define PI_ESIC_K_IO_CMP_3_0 0xC97 -#define PI_ESIC_K_IO_CMP_3_1 0xC98 +#define PI_ESIC_K_IO_ADD_CMP_0_0 0xC91 +#define PI_ESIC_K_IO_ADD_CMP_0_1 0xC92 +#define PI_ESIC_K_IO_ADD_CMP_1_0 0xC93 +#define PI_ESIC_K_IO_ADD_CMP_1_1 0xC94 +#define PI_ESIC_K_IO_ADD_CMP_2_0 0xC95 +#define PI_ESIC_K_IO_ADD_CMP_2_1 0xC96 +#define PI_ESIC_K_IO_ADD_CMP_3_0 0xC97 +#define PI_ESIC_K_IO_ADD_CMP_3_1 0xC98 #define PI_ESIC_K_IO_ADD_MASK_0_0 0xC99 #define PI_ESIC_K_IO_ADD_MASK_0_1 0xC9A #define PI_ESIC_K_IO_ADD_MASK_1_0 0xC9B @@ -1518,11 +1527,16 @@ typedef union #define PI_ESIC_K_INPUT_PORT 0xCAC #define PI_ESIC_K_OUTPUT_PORT 0xCAD #define PI_ESIC_K_FUNCTION_CNTRL 0xCAE -#define PI_ESIC_K_CSR_IO_LEN PI_ESIC_K_FUNCTION_CNTRL+1 /* always last reg + 1 */ -/* Define the value all drivers must write to the function control register. */ +/* Define the bits in the function control register. */ -#define PI_ESIC_K_FUNCTION_CNTRL_IO_ENB 0x03 +#define PI_FUNCTION_CNTRL_M_IOCS0 0x01 +#define PI_FUNCTION_CNTRL_M_IOCS1 0x02 +#define PI_FUNCTION_CNTRL_M_IOCS2 0x04 +#define PI_FUNCTION_CNTRL_M_IOCS3 0x08 +#define PI_FUNCTION_CNTRL_M_MEMCS0 0x10 +#define PI_FUNCTION_CNTRL_M_MEMCS1 0x20 +#define PI_FUNCTION_CNTRL_M_DMA 0x80 /* Define the bits in the slot control register. */ @@ -1540,6 +1554,10 @@ typedef union #define PI_BURST_HOLDOFF_V_RESERVED 1 #define PI_BURST_HOLDOFF_V_MEM_MAP 0 +/* Define the implicit mask of the Memory Address Mask Register. */ + +#define PI_MEM_ADD_MASK_M 0x3ff + /* * Define the fields in the IO Compare registers. * The driver must initialize the slot field with the slot ID shifted by the @@ -1577,6 +1595,7 @@ typedef union #define DEFEA_PROD_ID_1 0x0130A310 /* DEC product 300, rev 1 */ #define DEFEA_PROD_ID_2 0x0230A310 /* DEC product 300, rev 2 */ #define DEFEA_PROD_ID_3 0x0330A310 /* DEC product 300, rev 3 */ +#define DEFEA_PROD_ID_4 0x0430A310 /* DEC product 300, rev 4 */ /**********************************************/ /* Digital PFI Specification v1.0 Definitions */ @@ -1633,12 +1652,6 @@ typedef union #define PFI_STATUS_V_FIFO_EMPTY 1 #define PFI_STATUS_V_DMA_IN_PROGRESS 0 -#define DFX_MAX_EISA_SLOTS 16 /* maximum number of EISA slots to scan */ -#define DFX_MAX_NUM_BOARDS 8 /* maximum number of adapters supported */ - -#define DFX_BUS_TYPE_PCI 0 /* type code for DEC FDDIcontroller/PCI */ -#define DFX_BUS_TYPE_EISA 1 /* type code for DEC FDDIcontroller/EISA */ - #define DFX_FC_PRH2_PRH1_PRH0 0x54003820 /* Packet Request Header bytes + FC */ #define DFX_PRH0_BYTE 0x20 /* Packet Request Header byte 0 */ #define DFX_PRH1_BYTE 0x38 /* Packet Request Header byte 1 */ @@ -1756,10 +1769,11 @@ typedef struct DFX_board_tag /* Store device, bus-specific, and parameter information for this adapter */ struct net_device *dev; /* pointer to device structure */ - struct net_device *next; - u32 bus_type; /* bus type (0 == PCI, 1 == EISA) */ - u16 base_addr; /* base I/O address (same as dev->base_addr) */ - struct pci_dev * pci_dev; + union { + void __iomem *mem; + int port; + } base; /* base address */ + struct device *bus_dev; u32 full_duplex_enb; /* FDDI Full Duplex enable (1 == on, 2 == off) */ u32 req_ttrt; /* requested TTRT value (in 80ns units) */ u32 burst_size; /* adapter burst size (enumerated) */ -- cgit v1.2.2 From 335dc50cec2891026bd51e46769fc12365b6e475 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 5 Feb 2007 16:28:28 -0800 Subject: [TC] mips: pmag-ba-fb: Convert to the driver model This is a set of changes to convert the driver to the driver model. As a side-effect the driver now supports building as a module. Signed-off-by: Maciej W. Rozycki Cc: James Simmons Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Ralf Baechle --- drivers/video/Kconfig | 4 +- drivers/video/pmag-ba-fb.c | 95 ++++++++++++++++++++++++++-------------------- 2 files changed, 56 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4e83f01e894e..18c22ba6e656 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1444,8 +1444,8 @@ config FB_PMAG_AA used mainly in the MIPS-based DECstation series. config FB_PMAG_BA - bool "PMAG-BA TURBOchannel framebuffer support" - depends on (FB = y) && TC + tristate "PMAG-BA TURBOchannel framebuffer support" + depends on FB && TC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index f5361cd8ccce..264d37243fad 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -15,7 +15,8 @@ * Michael Engel , * Karsten Merker and * Harald Koerfgen. - * Copyright (c) 2005 Maciej W. Rozycki + * Copyright (c) 2005, 2006 Maciej W. Rozycki + * Copyright (c) 2005 James Simmons * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this @@ -28,26 +29,21 @@ #include #include #include +#include #include #include #include -#include - #include