|
@@ -414,7 +414,7 @@ static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
|
|
|
* ================
|
|
|
*
|
|
|
* Overview:
|
|
|
- * Retrieves the address range used to access control and status
|
|
|
+ * Retrieves the address ranges used to access control and status
|
|
|
* registers.
|
|
|
*
|
|
|
* Returns:
|
|
@@ -422,8 +422,8 @@ static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
|
|
|
*
|
|
|
* Arguments:
|
|
|
* bdev - pointer to device information
|
|
|
- * bar_start - pointer to store the start address
|
|
|
- * bar_len - pointer to store the length of the area
|
|
|
+ * bar_start - pointer to store the start addresses
|
|
|
+ * bar_len - pointer to store the lengths of the areas
|
|
|
*
|
|
|
* Assumptions:
|
|
|
* I am sure there are some.
|
|
@@ -442,38 +442,47 @@ static void dfx_get_bars(struct device *bdev,
|
|
|
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);
|
|
|
+ bar_start[0] = pci_resource_start(to_pci_dev(bdev), num);
|
|
|
+ bar_len[0] = pci_resource_len(to_pci_dev(bdev), num);
|
|
|
+ bar_start[2] = bar_start[1] = 0;
|
|
|
+ bar_len[2] = bar_len[1] = 0;
|
|
|
}
|
|
|
if (dfx_bus_eisa) {
|
|
|
unsigned long base_addr = to_eisa_device(bdev)->base_addr;
|
|
|
- resource_size_t bar;
|
|
|
+ resource_size_t bar_lo;
|
|
|
+ resource_size_t bar_hi;
|
|
|
|
|
|
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;
|
|
|
+ bar_lo = inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_2);
|
|
|
+ bar_lo <<= 8;
|
|
|
+ bar_lo |= inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_1);
|
|
|
+ bar_lo <<= 8;
|
|
|
+ bar_lo |= inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_0);
|
|
|
+ bar_lo <<= 8;
|
|
|
+ bar_start[0] = bar_lo;
|
|
|
+ bar_hi = inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_2);
|
|
|
+ bar_hi <<= 8;
|
|
|
+ bar_hi |= inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_1);
|
|
|
+ bar_hi <<= 8;
|
|
|
+ bar_hi |= inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_0);
|
|
|
+ bar_hi <<= 8;
|
|
|
+ bar_len[0] = ((bar_hi - bar_lo) | PI_MEM_ADD_MASK_M) +
|
|
|
+ 1;
|
|
|
} else {
|
|
|
- *bar_start = base_addr;
|
|
|
- *bar_len = PI_ESIC_K_CSR_IO_LEN +
|
|
|
- PI_ESIC_K_BURST_HOLDOFF_LEN;
|
|
|
+ bar_start[0] = base_addr;
|
|
|
+ bar_len[0] = PI_ESIC_K_CSR_IO_LEN;
|
|
|
}
|
|
|
+ bar_start[1] = base_addr + PI_DEFEA_K_BURST_HOLDOFF;
|
|
|
+ bar_len[1] = PI_ESIC_K_BURST_HOLDOFF_LEN;
|
|
|
+ bar_start[2] = base_addr + PI_ESIC_K_ESIC_CSR;
|
|
|
+ bar_len[2] = PI_ESIC_K_ESIC_CSR_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;
|
|
|
+ bar_start[0] = to_tc_dev(bdev)->resource.start +
|
|
|
+ PI_TC_K_CSR_OFFSET;
|
|
|
+ bar_len[0] = PI_TC_K_CSR_LEN;
|
|
|
+ bar_start[2] = bar_start[1] = 0;
|
|
|
+ bar_len[2] = bar_len[1] = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -518,13 +527,14 @@ static int dfx_register(struct device *bdev)
|
|
|
{
|
|
|
static int version_disp;
|
|
|
int dfx_bus_pci = dev_is_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;
|
|
|
const char *print_name = dev_name(bdev);
|
|
|
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 */
|
|
|
+ resource_size_t bar_start[3]; /* pointers to ports */
|
|
|
+ resource_size_t bar_len[3]; /* resource length */
|
|
|
int alloc_size; /* total buffer size used */
|
|
|
struct resource *region;
|
|
|
int err = 0;
|
|
@@ -542,10 +552,13 @@ static int dfx_register(struct device *bdev)
|
|
|
}
|
|
|
|
|
|
/* Enable PCI device. */
|
|
|
- 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;
|
|
|
+ if (dfx_bus_pci) {
|
|
|
+ err = pci_enable_device(to_pci_dev(bdev));
|
|
|
+ if (err) {
|
|
|
+ pr_err("%s: Cannot enable PCI device, aborting\n",
|
|
|
+ print_name);
|
|
|
+ goto err_out;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
SET_NETDEV_DEV(dev, bdev);
|
|
@@ -554,31 +567,62 @@ static int dfx_register(struct device *bdev)
|
|
|
bp->bus_dev = bdev;
|
|
|
dev_set_drvdata(bdev, dev);
|
|
|
|
|
|
- dfx_get_bars(bdev, &bar_start, &bar_len);
|
|
|
+ dfx_get_bars(bdev, bar_start, bar_len);
|
|
|
+ if (dfx_bus_eisa && dfx_use_mmio && bar_start[0] == 0) {
|
|
|
+ pr_err("%s: Cannot use MMIO, no address set, aborting\n",
|
|
|
+ print_name);
|
|
|
+ pr_err("%s: Run ECU and set adapter's MMIO location\n",
|
|
|
+ print_name);
|
|
|
+ pr_err("%s: Or recompile driver with \"CONFIG_DEFXX_MMIO=n\""
|
|
|
+ "\n", print_name);
|
|
|
+ err = -ENXIO;
|
|
|
+ goto err_out;
|
|
|
+ }
|
|
|
|
|
|
if (dfx_use_mmio)
|
|
|
- region = request_mem_region(bar_start, bar_len, print_name);
|
|
|
+ region = request_mem_region(bar_start[0], bar_len[0],
|
|
|
+ print_name);
|
|
|
else
|
|
|
- region = request_region(bar_start, bar_len, print_name);
|
|
|
+ region = request_region(bar_start[0], bar_len[0], print_name);
|
|
|
if (!region) {
|
|
|
- printk(KERN_ERR "%s: Cannot reserve I/O resource "
|
|
|
- "0x%lx @ 0x%lx, aborting\n",
|
|
|
- print_name, (long)bar_len, (long)bar_start);
|
|
|
+ pr_err("%s: Cannot reserve %s resource 0x%lx @ 0x%lx, "
|
|
|
+ "aborting\n", dfx_use_mmio ? "MMIO" : "I/O", print_name,
|
|
|
+ (long)bar_len[0], (long)bar_start[0]);
|
|
|
err = -EBUSY;
|
|
|
goto err_out_disable;
|
|
|
}
|
|
|
+ if (bar_start[1] != 0) {
|
|
|
+ region = request_region(bar_start[1], bar_len[1], print_name);
|
|
|
+ if (!region) {
|
|
|
+ pr_err("%s: Cannot reserve I/O resource "
|
|
|
+ "0x%lx @ 0x%lx, aborting\n", print_name,
|
|
|
+ (long)bar_len[1], (long)bar_start[1]);
|
|
|
+ err = -EBUSY;
|
|
|
+ goto err_out_csr_region;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (bar_start[2] != 0) {
|
|
|
+ region = request_region(bar_start[2], bar_len[2], print_name);
|
|
|
+ if (!region) {
|
|
|
+ pr_err("%s: Cannot reserve I/O resource "
|
|
|
+ "0x%lx @ 0x%lx, aborting\n", print_name,
|
|
|
+ (long)bar_len[2], (long)bar_start[2]);
|
|
|
+ err = -EBUSY;
|
|
|
+ goto err_out_bh_region;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/* Set up I/O base address. */
|
|
|
if (dfx_use_mmio) {
|
|
|
- bp->base.mem = ioremap_nocache(bar_start, bar_len);
|
|
|
+ bp->base.mem = ioremap_nocache(bar_start[0], bar_len[0]);
|
|
|
if (!bp->base.mem) {
|
|
|
printk(KERN_ERR "%s: Cannot map MMIO\n", print_name);
|
|
|
err = -ENOMEM;
|
|
|
- goto err_out_region;
|
|
|
+ goto err_out_esic_region;
|
|
|
}
|
|
|
} else {
|
|
|
- bp->base.port = bar_start;
|
|
|
- dev->base_addr = bar_start;
|
|
|
+ bp->base.port = bar_start[0];
|
|
|
+ dev->base_addr = bar_start[0];
|
|
|
}
|
|
|
|
|
|
/* Initialize new device structure */
|
|
@@ -587,7 +631,7 @@ static int dfx_register(struct device *bdev)
|
|
|
if (dfx_bus_pci)
|
|
|
pci_set_master(to_pci_dev(bdev));
|
|
|
|
|
|
- if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) {
|
|
|
+ if (dfx_driver_init(dev, print_name, bar_start[0]) != DFX_K_SUCCESS) {
|
|
|
err = -ENODEV;
|
|
|
goto err_out_unmap;
|
|
|
}
|
|
@@ -615,11 +659,19 @@ err_out_unmap:
|
|
|
if (dfx_use_mmio)
|
|
|
iounmap(bp->base.mem);
|
|
|
|
|
|
-err_out_region:
|
|
|
+err_out_esic_region:
|
|
|
+ if (bar_start[2] != 0)
|
|
|
+ release_region(bar_start[2], bar_len[2]);
|
|
|
+
|
|
|
+err_out_bh_region:
|
|
|
+ if (bar_start[1] != 0)
|
|
|
+ release_region(bar_start[1], bar_len[1]);
|
|
|
+
|
|
|
+err_out_csr_region:
|
|
|
if (dfx_use_mmio)
|
|
|
- release_mem_region(bar_start, bar_len);
|
|
|
+ release_mem_region(bar_start[0], bar_len[0]);
|
|
|
else
|
|
|
- release_region(bar_start, bar_len);
|
|
|
+ release_region(bar_start[0], bar_len[0]);
|
|
|
|
|
|
err_out_disable:
|
|
|
if (dfx_bus_pci)
|
|
@@ -711,13 +763,14 @@ static void dfx_bus_init(struct net_device *dev)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Enable memory decoding (MEMCS0) and/or port decoding
|
|
|
+ * Enable memory decoding (MEMCS1) and/or port decoding
|
|
|
* (IOCS1/IOCS0) as appropriate in Function Control
|
|
|
- * Register. IOCS0 is used for PDQ registers, taking 16
|
|
|
- * 32-bit words, while IOCS1 is used for the Burst Holdoff
|
|
|
- * register, taking a single 32-bit word only. We use the
|
|
|
- * slot-specific I/O range as per the ESIC spec, that is
|
|
|
- * set bits 15:12 in the mask registers to mask them out.
|
|
|
+ * Register. MEMCS1 or IOCS0 is used for PDQ registers,
|
|
|
+ * taking 16 32-bit words, while IOCS1 is used for the
|
|
|
+ * Burst Holdoff register, taking a single 32-bit word
|
|
|
+ * only. We use the slot-specific I/O range as per the
|
|
|
+ * ESIC spec, that is set bits 15:12 in the mask registers
|
|
|
+ * to mask them out.
|
|
|
*/
|
|
|
|
|
|
/* Set the decode range of the board. */
|
|
@@ -742,9 +795,11 @@ static void dfx_bus_init(struct net_device *dev)
|
|
|
outb(val, base_addr + PI_ESIC_K_IO_ADD_MASK_1_0);
|
|
|
|
|
|
/* Enable the decoders. */
|
|
|
- val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0;
|
|
|
+ val = PI_FUNCTION_CNTRL_M_IOCS1;
|
|
|
if (dfx_use_mmio)
|
|
|
- val |= PI_FUNCTION_CNTRL_M_MEMCS0;
|
|
|
+ val |= PI_FUNCTION_CNTRL_M_MEMCS1;
|
|
|
+ else
|
|
|
+ val |= PI_FUNCTION_CNTRL_M_IOCS0;
|
|
|
outb(val, base_addr + PI_ESIC_K_FUNCTION_CNTRL);
|
|
|
|
|
|
/*
|
|
@@ -838,6 +893,12 @@ static void dfx_bus_uninit(struct net_device *dev)
|
|
|
val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
|
|
|
val &= ~PI_CONFIG_STAT_0_M_INT_ENB;
|
|
|
outb(val, base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
|
|
|
+
|
|
|
+ /* Disable the board. */
|
|
|
+ outb(0, base_addr + PI_ESIC_K_SLOT_CNTRL);
|
|
|
+
|
|
|
+ /* Disable memory and port decoders. */
|
|
|
+ outb(0, base_addr + PI_ESIC_K_FUNCTION_CNTRL);
|
|
|
}
|
|
|
if (dfx_bus_pci) {
|
|
|
/* Disable interrupts at PCI bus interface chip (PFI) */
|
|
@@ -1061,8 +1122,8 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name,
|
|
|
board_name = "DEFEA";
|
|
|
if (dfx_bus_pci)
|
|
|
board_name = "DEFPA";
|
|
|
- pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n",
|
|
|
- print_name, board_name, dfx_use_mmio ? "" : "I/O ",
|
|
|
+ pr_info("%s: %s at %s addr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n",
|
|
|
+ print_name, board_name, dfx_use_mmio ? "MMIO" : "I/O",
|
|
|
(long long)bar_start, dev->irq, dev->dev_addr);
|
|
|
|
|
|
/*
|
|
@@ -3636,8 +3697,8 @@ static void dfx_unregister(struct device *bdev)
|
|
|
int dfx_bus_pci = dev_is_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 */
|
|
|
+ resource_size_t bar_start[3]; /* pointers to ports */
|
|
|
+ resource_size_t bar_len[3]; /* resource lengths */
|
|
|
int alloc_size; /* total buffer size used */
|
|
|
|
|
|
unregister_netdev(dev);
|
|
@@ -3655,12 +3716,16 @@ static void dfx_unregister(struct device *bdev)
|
|
|
|
|
|
dfx_bus_uninit(dev);
|
|
|
|
|
|
- dfx_get_bars(bdev, &bar_start, &bar_len);
|
|
|
+ dfx_get_bars(bdev, bar_start, bar_len);
|
|
|
+ if (bar_start[2] != 0)
|
|
|
+ release_region(bar_start[2], bar_len[2]);
|
|
|
+ if (bar_start[1] != 0)
|
|
|
+ release_region(bar_start[1], bar_len[1]);
|
|
|
if (dfx_use_mmio) {
|
|
|
iounmap(bp->base.mem);
|
|
|
- release_mem_region(bar_start, bar_len);
|
|
|
+ release_mem_region(bar_start[0], bar_len[0]);
|
|
|
} else
|
|
|
- release_region(bar_start, bar_len);
|
|
|
+ release_region(bar_start[0], bar_len[0]);
|
|
|
|
|
|
if (dfx_bus_pci)
|
|
|
pci_disable_device(to_pci_dev(bdev));
|