diff options
| -rw-r--r-- | drivers/acorn/char/i2c.c | 3 | ||||
| -rw-r--r-- | drivers/acorn/char/pcf8583.c | 6 | ||||
| -rw-r--r-- | drivers/acorn/net/Kconfig | 25 | ||||
| -rw-r--r-- | drivers/acorn/net/Makefile | 8 | ||||
| -rw-r--r-- | drivers/char/nwbutton.h | 2 | ||||
| -rw-r--r-- | drivers/ide/arm/icside.c | 340 | ||||
| -rw-r--r-- | drivers/ide/arm/rapide.c | 3 | ||||
| -rw-r--r-- | drivers/input/serio/sa1111ps2.c | 1 | ||||
| -rw-r--r-- | drivers/net/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/net/Makefile | 3 | ||||
| -rw-r--r-- | drivers/net/arm/Kconfig | 45 | ||||
| -rw-r--r-- | drivers/net/arm/Makefile | 10 | ||||
| -rw-r--r-- | drivers/net/arm/am79c961a.c (renamed from drivers/net/am79c961a.c) | 0 | ||||
| -rw-r--r-- | drivers/net/arm/am79c961a.h (renamed from drivers/net/am79c961a.h) | 0 | ||||
| -rw-r--r-- | drivers/net/arm/ether00.c | 1025 | ||||
| -rw-r--r-- | drivers/net/arm/ether1.c (renamed from drivers/acorn/net/ether1.c) | 21 | ||||
| -rw-r--r-- | drivers/net/arm/ether1.h (renamed from drivers/acorn/net/ether1.h) | 0 | ||||
| -rw-r--r-- | drivers/net/arm/ether3.c (renamed from drivers/acorn/net/ether3.c) | 0 | ||||
| -rw-r--r-- | drivers/net/arm/ether3.h (renamed from drivers/acorn/net/ether3.h) | 0 | ||||
| -rw-r--r-- | drivers/net/arm/etherh.c (renamed from drivers/acorn/net/etherh.c) | 2 | ||||
| -rw-r--r-- | drivers/net/irda/sa1100_ir.c | 3 | ||||
| -rw-r--r-- | drivers/scsi/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/scsi/Makefile | 2 | ||||
| -rw-r--r-- | drivers/scsi/arm/Kconfig (renamed from drivers/acorn/scsi/Kconfig) | 0 | ||||
| -rw-r--r-- | drivers/scsi/arm/Makefile (renamed from drivers/acorn/scsi/Makefile) | 2 | ||||
| -rw-r--r-- | drivers/scsi/arm/acornscsi-io.S (renamed from drivers/acorn/scsi/acornscsi-io.S) | 0 | ||||
| -rw-r--r-- | drivers/scsi/arm/acornscsi.c (renamed from drivers/acorn/scsi/acornscsi.c) | 33 | ||||
| -rw-r--r-- | drivers/scsi/arm/acornscsi.h (renamed from drivers/acorn/scsi/acornscsi.h) | 1 | ||||
| -rw-r--r-- | drivers/scsi/arm/arxescsi.c (renamed from drivers/acorn/scsi/arxescsi.c) | 34 | ||||
| -rw-r--r-- | drivers/scsi/arm/cumana_1.c (renamed from drivers/acorn/scsi/cumana_1.c) | 8 | ||||
| -rw-r--r-- | drivers/scsi/arm/cumana_2.c (renamed from drivers/acorn/scsi/cumana_2.c) | 24 | ||||
| -rw-r--r-- | drivers/scsi/arm/ecoscsi.c (renamed from drivers/acorn/scsi/ecoscsi.c) | 8 | ||||
| -rw-r--r-- | drivers/scsi/arm/eesox.c (renamed from drivers/acorn/scsi/eesox.c) | 19 | ||||
| -rw-r--r-- | drivers/scsi/arm/fas216.c (renamed from drivers/acorn/scsi/fas216.c) | 548 | ||||
| -rw-r--r-- | drivers/scsi/arm/fas216.h (renamed from drivers/acorn/scsi/fas216.h) | 9 | ||||
| -rw-r--r-- | drivers/scsi/arm/msgqueue.c (renamed from drivers/acorn/scsi/msgqueue.c) | 0 | ||||
| -rw-r--r-- | drivers/scsi/arm/msgqueue.h (renamed from drivers/acorn/scsi/msgqueue.h) | 0 | ||||
| -rw-r--r-- | drivers/scsi/arm/oak.c (renamed from drivers/acorn/scsi/oak.c) | 8 | ||||
| -rw-r--r-- | drivers/scsi/arm/powertec.c (renamed from drivers/acorn/scsi/powertec.c) | 35 | ||||
| -rw-r--r-- | drivers/scsi/arm/queue.c (renamed from drivers/acorn/scsi/queue.c) | 2 | ||||
| -rw-r--r-- | drivers/scsi/arm/queue.h (renamed from drivers/acorn/scsi/queue.h) | 0 | ||||
| -rw-r--r-- | drivers/scsi/arm/scsi.h (renamed from drivers/acorn/scsi/scsi.h) | 0 | ||||
| -rw-r--r-- | drivers/video/cyber2000fb.c | 51 |
43 files changed, 1587 insertions, 705 deletions
diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c index dc946403ac33..2328f7602295 100644 --- a/drivers/acorn/char/i2c.c +++ b/drivers/acorn/char/i2c.c @@ -19,6 +19,7 @@ #include <linux/rtc.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> +#include <linux/fs.h> #include <asm/hardware.h> #include <asm/io.h> @@ -306,7 +307,7 @@ static struct i2c_adapter ioc_ops = { .id = I2C_HW_B_IOC, .algo_data = &ioc_data, .client_register = ioc_client_reg, - .client_unregister = ioc_client_unreg + .client_unregister = ioc_client_unreg, .dev = { .name = "IOC/IOMD", }, diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c index 216d290606a9..6cf9e9259cef 100644 --- a/drivers/acorn/char/pcf8583.c +++ b/drivers/acorn/char/pcf8583.c @@ -34,7 +34,7 @@ static struct i2c_client_address_data addr_data = { .force = ignore, }; -#define DAT(x) ((unsigned int)(x->data)) +#define DAT(x) ((unsigned int)(x->dev.driver_data)) static int pcf8583_attach(struct i2c_adapter *adap, int addr, unsigned short flags, @@ -51,13 +51,13 @@ pcf8583_attach(struct i2c_adapter *adap, int addr, unsigned short flags, if (!c) return -ENOMEM; - strcpy(c->name, "PCF8583"); + strcpy(c->dev.name, "PCF8583"); c->id = pcf8583_driver.id; c->flags = 0; c->addr = addr; c->adapter = adap; c->driver = &pcf8583_driver; - c->data = NULL; + c->dev.driver_data = NULL; if (i2c_transfer(c->adapter, msgs, 2) == 2) DAT(c) = buf[0]; diff --git a/drivers/acorn/net/Kconfig b/drivers/acorn/net/Kconfig deleted file mode 100644 index d895d7541351..000000000000 --- a/drivers/acorn/net/Kconfig +++ /dev/null @@ -1,25 +0,0 @@ -# -# Acorn Network device configuration -# These are for Acorn's Expansion card network interfaces -# -config ARM_ETHER1 - tristate "Acorn Ether1 support" - depends on NET_ETHERNET && ARM && ARCH_ACORN - help - If you have an Acorn system with one of these (AKA25) network cards, - you should say Y to this option if you wish to use it with Linux. - -config ARM_ETHER3 - tristate "Acorn/ANT Ether3 support" - depends on NET_ETHERNET && ARM && ARCH_ACORN - help - If you have an Acorn system with one of these network cards, you - should say Y to this option if you wish to use it with Linux. - -config ARM_ETHERH - tristate "I-cubed EtherH/ANT EtherM support" - depends on NET_ETHERNET && ARM && ARCH_ACORN - help - If you have an Acorn system with one of these network cards, you - should say Y to this option if you wish to use it with Linux. - diff --git a/drivers/acorn/net/Makefile b/drivers/acorn/net/Makefile deleted file mode 100644 index a567f4cdd75b..000000000000 --- a/drivers/acorn/net/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# File: drivers/acorn/net/Makefile -# -# Makefile for the Acorn ethercard network device drivers -# - -obj-$(CONFIG_ARM_ETHERH) += etherh.o -obj-$(CONFIG_ARM_ETHER3) += ether3.o -obj-$(CONFIG_ARM_ETHER1) += ether1.o diff --git a/drivers/char/nwbutton.h b/drivers/char/nwbutton.h index 5f5c8ddd041f..a59a045af441 100644 --- a/drivers/char/nwbutton.h +++ b/drivers/char/nwbutton.h @@ -25,7 +25,7 @@ struct button_callback { /* Function prototypes: */ static void button_sequence_finished (unsigned long parameters); -static void button_handler (int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t button_handler (int irq, void *dev_id, struct pt_regs *regs); static int button_read (struct file *filp, char *buffer, size_t count, loff_t *ppos); int button_init (void); diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index 9f3bb7919dd4..653de7cd0523 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -19,7 +19,7 @@ #include <linux/errno.h> #include <linux/hdreg.h> #include <linux/ide.h> -#include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/device.h> #include <linux/init.h> @@ -27,12 +27,7 @@ #include <asm/ecard.h> #include <asm/io.h> -/* - * Maximum number of interfaces per card - */ -#define MAX_IFS 2 - -#define ICS_IDENT_OFFSET 0x8a0 +#define ICS_IDENT_OFFSET 0x2280 #define ICS_ARCIN_V5_INTRSTAT 0x000 #define ICS_ARCIN_V5_INTROFFSET 0x001 @@ -77,14 +72,19 @@ static struct cardinfo icside_cardinfo_v6_2 = { struct icside_state { unsigned int channel; unsigned int enabled; - unsigned int irq_port; + unsigned long irq_port; + unsigned long slot_port; + unsigned int type; + /* parent device... until the IDE core gets one of its own */ + struct device *dev; + ide_hwif_t *hwif[2]; }; -typedef enum { - ics_if_unknown, - ics_if_arcin_v5, - ics_if_arcin_v6 -} iftype_t; +#define ICS_TYPE_A3IN 0 +#define ICS_TYPE_A3USER 1 +#define ICS_TYPE_V6 3 +#define ICS_TYPE_V5 15 +#define ICS_TYPE_NOTYPE ((unsigned int)-1) /* ---------------- Version 5 PCB Support Functions --------------------- */ /* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) @@ -92,8 +92,10 @@ typedef enum { */ static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) { - unsigned int memc_port = (unsigned int)ec->irq_data; - outb(0, memc_port + ICS_ARCIN_V5_INTROFFSET); + struct icside_state *state = ec->irq_data; + unsigned int base = state->irq_port; + + outb(0, base + ICS_ARCIN_V5_INTROFFSET); } /* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) @@ -101,17 +103,15 @@ static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) */ static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) { - unsigned int memc_port = (unsigned int)ec->irq_data; - inb(memc_port + ICS_ARCIN_V5_INTROFFSET); + struct icside_state *state = ec->irq_data; + unsigned int base = state->irq_port; + + inb(base + ICS_ARCIN_V5_INTROFFSET); } static const expansioncard_ops_t icside_ops_arcin_v5 = { - icside_irqenable_arcin_v5, - icside_irqdisable_arcin_v5, - NULL, - NULL, - NULL, - NULL + .irqenable = icside_irqenable_arcin_v5, + .irqdisable = icside_irqdisable_arcin_v5, }; @@ -163,65 +163,11 @@ static int icside_irqpending_arcin_v6(struct expansion_card *ec) } static const expansioncard_ops_t icside_ops_arcin_v6 = { - icside_irqenable_arcin_v6, - icside_irqdisable_arcin_v6, - icside_irqpending_arcin_v6, - NULL, - NULL, - NULL + .irqenable = icside_irqenable_arcin_v6, + .irqdisable = icside_irqdisable_arcin_v6, + .irqpending = icside_irqpending_arcin_v6, }; -/* Prototype: icside_identifyif (struct expansion_card *ec) - * Purpose : identify IDE interface type - * Notes : checks the description string - */ -static iftype_t __init icside_identifyif (struct expansion_card *ec) -{ - unsigned int addr; - iftype_t iftype; - int id = 0; - - iftype = ics_if_unknown; - - addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET; - - id = inb(addr) & 1; - id |= (inb(addr + 1) & 1) << 1; - id |= (inb(addr + 2) & 1) << 2; - id |= (inb(addr + 3) & 1) << 3; - - switch (id) { - case 0: /* A3IN */ - printk("icside: A3IN unsupported\n"); - break; - - case 1: /* A3USER */ - printk("icside: A3USER unsupported\n"); - break; - - case 3: /* ARCIN V6 */ - printk(KERN_DEBUG "icside: detected ARCIN V6 in slot %d\n", ec->slot_no); - iftype = ics_if_arcin_v6; - break; - - case 15:/* ARCIN V5 (no id) */ - printk(KERN_DEBUG "icside: detected ARCIN V5 in slot %d\n", ec->slot_no); - iftype = ics_if_arcin_v5; - break; - - default:/* we don't know - complain very loudly */ - printk("icside: ***********************************\n"); - printk("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id); - printk("icside: ***********************************\n"); - printk("icside: please report this to linux@arm.linux.org.uk\n"); - printk("icside: defaulting to ARCIN V5\n"); - iftype = ics_if_arcin_v5; - break; - } - - return iftype; -} - /* * Handle routing of interrupts. This is called before * we write the command to the drive. @@ -229,7 +175,7 @@ static iftype_t __init icside_identifyif (struct expansion_card *ec) static void icside_maskproc(ide_drive_t *drive, int mask) { ide_hwif_t *hwif = HWIF(drive); - struct icside_state *state = hwif->hw.priv; + struct icside_state *state = hwif->hwif_data; unsigned long flags; local_irq_save(flags); @@ -271,6 +217,7 @@ static void icside_maskproc(ide_drive_t *drive, int mask) static void ide_build_sglist(ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = drive->hwif; + struct icside_state *state = hwif->hwif_data; struct scatterlist *sg = hwif->sg_table; int nents; @@ -280,9 +227,9 @@ static void ide_build_sglist(ide_drive_t *drive, struct request *rq) ide_task_t *args = rq->special; if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) - hwif->sg_dma_direction = PCI_DMA_TODEVICE; + hwif->sg_dma_direction = DMA_TO_DEVICE; else - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; + hwif->sg_dma_direction = DMA_FROM_DEVICE; memset(sg, 0, sizeof(*sg)); sg->page = virt_to_page(rq->buffer); @@ -293,12 +240,12 @@ static void ide_build_sglist(ide_drive_t *drive, struct request *rq) nents = blk_rq_map_sg(&drive->queue, rq, sg); if (rq_data_dir(rq) == READ) - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; + hwif->sg_dma_direction = DMA_FROM_DEVICE; else - hwif->sg_dma_direction = PCI_DMA_TODEVICE; + hwif->sg_dma_direction = DMA_TO_DEVICE; } - nents = pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction); + nents = dma_map_sg(state->dev, sg, nents, hwif->sg_dma_direction); hwif->sg_nents = nents; } @@ -484,7 +431,7 @@ static int icside_dma_check(ide_drive_t *drive) int xfer_mode = XFER_PIO_2; int on; - if (!id || !(id->capability & 1) || !hwif->autodma) + if (!(id->capability & 1) || !hwif->autodma) goto out; /* @@ -500,13 +447,7 @@ static int icside_dma_check(ide_drive_t *drive) * Enable DMA on any drive that has multiword DMA */ if (id->field_valid & 2) { - if (id->dma_mword & 4) { - xfer_mode = XFER_MW_DMA_2; - } else if (id->dma_mword & 2) { - xfer_mode = XFER_MW_DMA_1; - } else if (id->dma_mword & 1) { - xfer_mode = XFER_MW_DMA_0; - } + xfer_mode = ide_dma_speed(drive, 0); goto out; } @@ -531,13 +472,14 @@ out: static int icside_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + struct icside_state *state = hwif->hwif_data; drive->waiting_for_dma = 0; disable_dma(hwif->hw.dma); /* Teardown mappings after DMA has completed. */ - pci_unmap_sg(NULL, hwif->sg_table, hwif->sg_nents, + dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents, hwif->sg_dma_direction); hwif->sg_dma_active = 0; @@ -713,7 +655,7 @@ int icside_dma_write(ide_drive_t *drive) static int icside_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct icside_state *state = hwif->hw.priv; + struct icside_state *state = hwif->hwif_data; return inb(state->irq_port + (hwif->channel ? @@ -748,7 +690,7 @@ static int icside_dma_lostirq(ide_drive_t *drive) return 1; } -static int icside_setup_dma(ide_hwif_t *hwif) +static int icside_dma_init(ide_hwif_t *hwif) { int autodma = 0; @@ -763,6 +705,10 @@ static int icside_setup_dma(ide_hwif_t *hwif) if (!hwif->sg_table) goto failed; + hwif->atapi_dma = 1; + hwif->mwdma_mask = 7; /* MW0..2 */ + hwif->swdma_mask = 7; /* SW0..2 */ + hwif->dmatable_cpu = NULL; hwif->dmatable_dma = 0; hwif->speedproc = icside_set_speed; @@ -784,10 +730,10 @@ static int icside_setup_dma(ide_hwif_t *hwif) hwif->ide_dma_timeout = icside_dma_timeout; hwif->ide_dma_lostirq = icside_dma_lostirq; - hwif->drives[0].autodma = autodma; - hwif->drives[1].autodma = autodma; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; - printk(" capable%s\n", autodma ? ", auto-enable" : ""); + printk(" capable%s\n", hwif->autodma ? ", auto-enable" : ""); return 1; @@ -796,14 +742,16 @@ failed: return 0; } -int ide_release_dma(ide_hwif_t *hwif) +static void icside_dma_exit(ide_hwif_t *hwif) { if (hwif->sg_table) { kfree(hwif->sg_table); hwif->sg_table = NULL; } - return 1; } +#else +#define icside_dma_init(hwif) (0) +#define icside_dma_exit(hwif) do { } while (0) #endif static ide_hwif_t *icside_find_hwif(unsigned long dataport) @@ -829,7 +777,7 @@ found: } static ide_hwif_t * -icside_setup(unsigned long base, struct cardinfo *info, int irq) +icside_setup(unsigned long base, struct cardinfo *info, struct expansion_card *ec) { unsigned long port = base + info->dataoffset; ide_hwif_t *hwif; @@ -847,42 +795,47 @@ icside_setup(unsigned long base, struct cardinfo *info, int irq) } hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; - hwif->hw.irq = irq; - hwif->irq = irq; - hwif->hw.dma = NO_DMA; + hwif->hw.irq = ec->irq; + hwif->irq = ec->irq; hwif->noprobe = 0; hwif->chipset = ide_acorn; + hwif->gendev.parent = &ec->dev; } return hwif; } -static int __init icside_register_v5(struct expansion_card *ec) +static int __init +icside_register_v5(struct icside_state *state, struct expansion_card *ec) { unsigned long slot_port; ide_hwif_t *hwif; slot_port = ecard_address(ec, ECARD_MEMC, 0); + state->irq_port = slot_port; + ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT); ec->irqmask = 1; - ec->irq_data = (void *)slot_port; - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5; + ec->irq_data = state; + ec->ops = &icside_ops_arcin_v5; /* * Be on the safe side - disable interrupts */ inb(slot_port + ICS_ARCIN_V5_INTROFFSET); - hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq); + hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec); + + state->hwif[0] = hwif; return hwif ? 0 : -ENODEV; } -static int __init icside_register_v6(struct expansion_card *ec) +static int __init +icside_register_v6(struct icside_state *state, struct expansion_card *ec) { unsigned long slot_port, port; - struct icside_state *state; ide_hwif_t *hwif, *mate; unsigned int sel = 0; @@ -905,89 +858,173 @@ static int __init icside_register_v6(struct expansion_card *ec) /* * Find and register the interfaces. */ - hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq); - mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq); + hwif = icside_setup(port, &icside_cardinfo_v6_1, ec); + mate = icside_setup(port, &icside_cardinfo_v6_2, ec); if (!hwif || !mate) return -ENODEV; - state = kmalloc(sizeof(struct icside_state), GFP_KERNEL); - if (!state) - return -ENOMEM; - - state->channel = 0; - state->enabled = 0; state->irq_port = port; + state->slot_port = slot_port; + state->hwif[0] = hwif; + state->hwif[1] = mate; - ec->irq_data = state; - ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; + ec->irq_data = state; + ec->ops = &icside_ops_arcin_v6; hwif->maskproc = icside_maskproc; hwif->channel = 0; - hwif->hw.priv = state; + hwif->hwif_data = state; hwif->mate = mate; hwif->serialized = 1; hwif->config_data = slot_port; hwif->select_data = sel; - hwif->hw.dma = ec->dma; + hwif->hw.dma = ec->dma; mate->maskproc = icside_maskproc; mate->channel = 1; - mate->hw.priv = state; + mate->hwif_data = state; mate->mate = hwif; mate->serialized = 1; mate->config_data = slot_port; mate->select_data = sel | 1; - mate->hw.dma = ec->dma; + mate->hw.dma = ec->dma; -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) { - icside_setup_dma(hwif); - icside_setup_dma(mate); + icside_dma_init(hwif); + icside_dma_init(mate); } -#endif + return 0; } static int __devinit icside_probe(struct expansion_card *ec, const struct ecard_id *id) { - int result; + struct icside_state *state; + void *idmem; + int ret; - ecard_claim(ec); + state = kmalloc(sizeof(struct icside_state), GFP_KERNEL); + if (!state) { + ret = -ENOMEM; + goto out; + } + + memset(state, 0, sizeof(state)); + state->type = ICS_TYPE_NOTYPE; + state->dev = &ec->dev; + + idmem = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST), + ecard_resource_len(ec, ECARD_RES_IOCFAST)); + if (idmem) { + unsigned int type; + + type = readb(idmem + ICS_IDENT_OFFSET) & 1; + type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1; + type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2; + type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3; + iounmap(idmem); - switch (icside_identifyif(ec)) { - case ics_if_arcin_v5: - result = icside_register_v5(ec); + state->type = type; + } + + switch (state->type) { + case ICS_TYPE_A3IN: + printk(KERN_WARNING "icside: A3IN unsupported\n"); + ret = -ENODEV; break; - case ics_if_arcin_v6: - result = icside_register_v6(ec); + case ICS_TYPE_A3USER: + printk(KERN_WARNING "icside: A3USER unsupported\n"); + ret = -ENODEV; + break; + + case ICS_TYPE_V5: + ret = icside_register_v5(state, ec); + break; + + case ICS_TYPE_V6: + ret = icside_register_v6(state, ec); break; default: - result = -ENODEV; + printk(KERN_WARNING "icside: unknown interface type\n"); + ret = -ENODEV; break; } - if (result) - ecard_release(ec); - /* - * this locks the driver in-core - remove this - * comment and the two lines below when we can - * safely remove interfaces. - */ - else + if (ret == 0) { + ecard_set_drvdata(ec, state); + + /* + * this locks the driver in-core - remove this + * comment and the line below when we can + * safely remove interfaces. + */ MOD_INC_USE_COUNT; + } else { + kfree(state); + } + out: + return ret; +} + +static void __devexit icside_remove(struct expansion_card *ec) +{ + struct icside_state *state = ecard_get_drvdata(ec); - return result; + switch (state->type) { + case ICS_TYPE_V5: + /* FIXME: tell IDE to stop using the interface */ + + /* Disable interrupts */ + inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET); + break; + + case ICS_TYPE_V6: + /* FIXME: tell IDE to stop using the interface */ + icside_dma_exit(state->hwif[1]); + icside_dma_exit(state->hwif[0]); + + if (ec->dma != NO_DMA) + free_dma(ec->dma); + + /* Disable interrupts */ + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + + /* Reset the ROM pointer/EASI selection */ + outb(0, state->slot_port); + break; + } + + ecard_set_drvdata(ec, NULL); + ec->ops = NULL; + ec->irq_data = NULL; + + kfree(state); } -static void __devexit -icside_remove(struct expansion_card *ec) +static void icside_shutdown(struct expansion_card *ec) { - /* need to do more */ - ecard_release(ec); + struct icside_state *state = ecard_get_drvdata(ec); + + switch (state->type) { + case ICS_TYPE_V5: + /* Disable interrupts */ + inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET); + break; + + case ICS_TYPE_V6: + /* Disable interrupts */ + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + + /* Reset the ROM pointer/EASI selection */ + outb(0, state->slot_port); + break; + } } static const struct ecard_id icside_ids[] = { @@ -999,6 +1036,7 @@ static const struct ecard_id icside_ids[] = { static struct ecard_driver icside_driver = { .probe = icside_probe, .remove = __devexit_p(icside_remove), + .shutdown = icside_shutdown, .id_table = icside_ids, .drv = { .name = "icside", diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c index 9291933174ae..f8af375acf24 100644 --- a/drivers/ide/arm/rapide.c +++ b/drivers/ide/arm/rapide.c @@ -20,8 +20,6 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) hw_regs_t hw; int i, ret; - ecard_claim(ec); - memset(&hw, 0, sizeof(hw)); for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { @@ -49,7 +47,6 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) static void __devexit rapide_remove(struct expansion_card *ec) { /* need to do more */ - ecard_release(ec); } static struct ecard_id rapide_ids[] = { diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index bf9adc378a4d..390c4d7e5b9d 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -347,7 +347,6 @@ static struct sa1111_driver ps2_driver = { .drv = { .name = "sa1111-ps2", .bus = &sa1111_bus_type, - .devclass = &input_devclass, .probe = ps2_probe, .remove = ps2_remove, .suspend = ps2_suspend, diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 50536836231f..5dbd74649763 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -221,14 +221,7 @@ config MII or internal device. It is safe to say Y or M here even if your ethernet card lack MII. -config ARM_AM79C961A - bool "ARM EBSA110 AM79C961A support" - depends on NET_ETHERNET && ARM && ARCH_EBSA110 - help - If you wish to compile a kernel for the EBSA-110, then you should - always answer Y to this. - -source "drivers/acorn/net/Kconfig" +source "drivers/net/arm/Kconfig" config MACE tristate "MACE (Power Mac ethernet) support" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index a60b936743c4..1c47eb79f00b 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -77,7 +77,6 @@ obj-$(CONFIG_HP100) += hp100.o obj-$(CONFIG_SMC9194) += smc9194.o obj-$(CONFIG_FEC) += fec.o obj-$(CONFIG_68360_ENET) += 68360enet.o -obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o obj-$(CONFIG_ARM_ETHERH) += 8390.o obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_EL2) += 3c503.o 8390.o @@ -179,7 +178,7 @@ obj-$(CONFIG_AMD8111_ETH) += amd8111e.o # non-drivers/net drivers who want mii lib obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o -obj-$(CONFIG_ARCH_ACORN) += ../acorn/net/ +obj-$(CONFIG_ARM) += arm/ obj-$(CONFIG_NET_FC) += fc/ obj-$(CONFIG_DEV_APPLETALK) += appletalk/ obj-$(CONFIG_TR) += tokenring/ diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig new file mode 100644 index 000000000000..de3cfdcf61a3 --- /dev/null +++ b/drivers/net/arm/Kconfig @@ -0,0 +1,45 @@ +# +# Acorn Network device configuration +# These are for Acorn's Expansion card network interfaces +# +config ARM_AM79C961A + bool "ARM EBSA110 AM79C961A support" + depends on NET_ETHERNET && ARM && ARCH_EBSA110 + help + If you wish to compile a kernel for the EBSA-110, then you should + always answer Y to this. + +config ARM_ETHER1 + tristate "Acorn Ether1 support" + depends on NET_ETHERNET && ARM && ARCH_ACORN + help + If you have an Acorn system with one of these (AKA25) network cards, + you should say Y to this option if you wish to use it with Linux. + +config ARM_ETHER3 + tristate "Acorn/ANT Ether3 support" + depends on NET_ETHERNET && ARM && ARCH_ACORN + help + If you have an Acorn system with one of these network cards, you + should say Y to this option if you wish to use it with Linux. + +config ARM_ETHERH + tristate "I-cubed EtherH/ANT EtherM support" + depends on NET_ETHERNET && ARM && ARCH_ACORN + help + If you have an Acorn system with one of these network cards, you + should say Y to this option if you wish to use it with Linux. + +config ARM_ETHER00 + tristate "Altera Ether00 support" + depends on NET_ETHERNET && ARM && ARCH_CAMELOT + help + This is the driver for Altera's ether00 ethernet mac IP core. Say + Y here if you want to build support for this into the kernel. It + is also available as a module (say M here) that can be inserted/ + removed from the kernel at the same time as the PLD is configured. + If this driver is running on an epxa10 development board then it + will generate a suitable hw address based on the board serial + number (MTD support is required for this). Otherwise you will + need to set a suitable hw address using ifconfig. + diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile new file mode 100644 index 000000000000..b0d706834d89 --- /dev/null +++ b/drivers/net/arm/Makefile @@ -0,0 +1,10 @@ +# File: drivers/net/arm/Makefile +# +# Makefile for the ARM network device drivers +# + +obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o +obj-$(CONFIG_ARM_ETHER00) += ether00.o +obj-$(CONFIG_ARM_ETHERH) += etherh.o +obj-$(CONFIG_ARM_ETHER3) += ether3.o +obj-$(CONFIG_ARM_ETHER1) += ether1.o diff --git a/drivers/net/am79c961a.c b/drivers/net/arm/am79c961a.c index 68527d691d85..68527d691d85 100644 --- a/drivers/net/am79c961a.c +++ b/drivers/net/arm/am79c961a.c diff --git a/drivers/net/am79c961a.h b/drivers/net/arm/am79c961a.h index 453b728ab744..453b728ab744 100644 --- a/drivers/net/am79c961a.h +++ b/drivers/net/arm/am79c961a.h diff --git a/drivers/net/arm/ether00.c b/drivers/net/arm/ether00.c new file mode 100644 index 000000000000..d5a05d1d1cd3 --- /dev/null +++ b/drivers/net/arm/ether00.c @@ -0,0 +1,1025 @@ +/* + * drivers/net/ether00.c + * + * Copyright (C) 2001 Altera Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* includes */ + +#include <linux/pci.h> +#include <linux/netdevice.h> +#include <linux/sched.h> +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <linux/etherdevice.h> +#include <linux/module.h> +#include <linux/tqueue.h> +#include <linux/mtd/mtd.h> +#include <linux/pld/pld_hotswap.h> +#include <asm/arch/excalibur.h> +#include <asm/arch/hardware.h> +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/sizes.h> + +#include <asm/arch/ether00.h> +#include <asm/arch/tdkphy.h> + + +MODULE_AUTHOR("Clive Davies"); +MODULE_DESCRIPTION("Altera Ether00 IP core driver"); +MODULE_LICENSE("GPL"); + +#define PKT_BUF_SZ 1540 /* Size of each rx buffer */ +#define ETH_NR 4 /* Number of MACs this driver supports */ + +#define DEBUG(x) + +#define __dma_va(x) (unsigned int)((unsigned int)priv->dma_data+(((unsigned int)(x))&(EXC_SPSRAM_BLOCK0_SIZE-1))) +#define __dma_pa(x) (unsigned int)(EXC_SPSRAM_BLOCK0_BASE+(((unsigned int)(x))-(unsigned int)priv->dma_data)) + +#define ETHER00_BASE 0 +#define ETHER00_TYPE +#define ETHER00_NAME "ether00" +#define MAC_REG_SIZE 0x400 /* size of MAC register area */ + + + +/* typedefs */ + +/* The definition of the driver control structure */ + +#define RX_NUM_BUFF 10 +#define RX_NUM_FDESC 10 +#define TX_NUM_FDESC 10 + +struct tx_fda_ent{ + FDA_DESC fd; + BUF_DESC bd; + BUF_DESC pad; +}; +struct rx_fda_ent{ + FDA_DESC fd; + BUF_DESC bd; + BUF_DESC pad; +}; +struct rx_blist_ent{ + FDA_DESC fd; + BUF_DESC bd; + BUF_DESC pad; +}; +struct net_priv +{ + struct net_device_stats stats; + struct sk_buff* skb; + void* dma_data; + struct rx_blist_ent* rx_blist_vp; + struct rx_fda_ent* rx_fda_ptr; + struct tx_fda_ent* tx_fdalist_vp; + struct tq_struct tq_memupdate; + unsigned char memupdate_scheduled; + unsigned char rx_disabled; + unsigned char queue_stopped; + spinlock_t rx_lock; +}; + +static const char vendor_id[2]={0x07,0xed}; + +#ifdef ETHER00_DEBUG + +/* Dump (most) registers for debugging puposes */ + +static void dump_regs(struct net_device *dev){ + struct net_priv* priv=dev->priv; + unsigned int* i; + + printk("\n RX free descriptor area:\n"); + + for(i=(unsigned int*)priv->rx_fda_ptr; + i<((unsigned int*)(priv->rx_fda_ptr+RX_NUM_FDESC));){ + printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3)); + i+=4; + } + + printk("\n RX buffer list:\n"); + + for(i=(unsigned int*)priv->rx_blist_vp; + i<((unsigned int*)(priv->rx_blist_vp+RX_NUM_BUFF));){ + printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3)); + i+=4; + } + + printk("\n TX frame descriptor list:\n"); + + for(i=(unsigned int*)priv->tx_fdalist_vp; + i<((unsigned int*)(priv->tx_fdalist_vp+TX_NUM_FDESC));){ + printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3)); + i+=4; + } + + printk("\ndma ctl=%#x\n",readw(ETHER_DMA_CTL(dev->base_addr))); + printk("txfrmptr=%#x\n",readw(ETHER_TXFRMPTR(dev->base_addr))); + printk("txthrsh=%#x\n",readw(ETHER_TXTHRSH(dev->base_addr))); + printk("txpollctr=%#x\n",readw(ETHER_TXPOLLCTR(dev->base_addr))); + printk("blfrmptr=%#x\n",readw(ETHER_BLFRMPTR(dev->base_addr))); + printk("rxfragsize=%#x\n",readw(ETHER_RXFRAGSIZE(dev->base_addr))); + printk("tx_int_en=%#x\n",readw(ETHER_INT_EN(dev->base_addr))); + printk("fda_bas=%#x\n",readw(ETHER_FDA_BAS(dev->base_addr))); + printk("fda_lim=%#x\n",readw(ETHER_FDA_LIM(dev->base_addr))); + printk("int_src=%#x\n",readw(ETHER_INT_SRC(dev->base_addr))); + printk("pausecnt=%#x\n",readw(ETHER_PAUSECNT(dev->base_addr))); + printk("rempaucnt=%#x\n",readw(ETHER_REMPAUCNT(dev->base_addr))); + printk("txconfrmstat=%#x\n",readw(ETHER_TXCONFRMSTAT(dev->base_addr))); + printk("mac_ctl=%#x\n",readw(ETHER_MAC_CTL(dev->base_addr))); + printk("arc_ctl=%#x\n",readw(ETHER_ARC_CTL(dev->base_addr))); + printk("tx_ctl=%#x\n",readw(ETHER_TX_CTL(dev->base_addr))); +} +#endif /* ETHER00_DEBUG */ + + +static int ether00_write_phy(struct net_device *dev, short address, short value) +{ + volatile int count = 1024; + writew(value,ETHER_MD_DATA(dev->base_addr)); + writew( ETHER_MD_CA_BUSY_MSK | + ETHER_MD_CA_WR_MSK | + (address & ETHER_MD_CA_ADDR_MSK), + ETHER_MD_CA(dev->base_addr)); + + /* Wait for the command to complete */ + while((readw(ETHER_MD_CA(dev->base_addr)) & ETHER_MD_CA_BUSY_MSK)&&count){ + count--; + } + if (!count){ + printk("Write to phy failed, addr=%#x, data=%#x\n",address, value); + return -EIO; + } + return 0; +} + +static int ether00_read_phy(struct net_device *dev, short address) +{ + volatile int count = 1024; + writew( ETHER_MD_CA_BUSY_MSK | + (address & ETHER_MD_CA_ADDR_MSK), + ETHER_MD_CA(dev->base_addr)); + + /* Wait for the command to complete */ + while((readw(ETHER_MD_CA(dev->base_addr)) & ETHER_MD_CA_BUSY_MSK)&&count){ + count--; + } + if (!count){ + printk(KERN_WARNING "Read from phy timed out\n"); + return -EIO; + } + return readw(ETHER_MD_DATA(dev->base_addr)); +} + +static void ether00_phy_int(int irq_num, void* dev_id, struct pt_regs* regs) +{ + struct net_device* dev=dev_id; + int irq_status; + + irq_status=ether00_read_phy(dev, PHY_IRQ_CONTROL); + + if(irq_status & PHY_IRQ_CONTROL_ANEG_COMP_INT_MSK){ + /* + * Autonegotiation complete on epxa10db. The mac doesn't + * twig if we're in full duplex so we need to check the + * phy status register and configure the mac accordingly + */ + if(ether00_read_phy(dev, PHY_STATUS)&(PHY_STATUS_10T_F_MSK|PHY_STATUS_100_X_F_MSK)){ + int tmp; + tmp=readl(ETHER_MAC_CTL(dev->base_addr)); + writel(tmp|ETHER_MAC_CTL_FULLDUP_MSK,ETHER_MAC_CTL(dev->base_addr)); + } + } + + if(irq_status&PHY_IRQ_CONTROL_LS_CHG_INT_MSK){ + + if(ether00_read_phy(dev, PHY_STATUS)& PHY_STATUS_LINK_MSK){ + /* Link is up */ + netif_carrier_on(dev); + //printk("Carrier on\n"); + }else{ + netif_carrier_off(dev); + //printk("Carrier off\n"); + + } + } + +} + +static void setup_blist_entry(struct sk_buff* skb,struct rx_blist_ent* blist_ent_ptr){ + /* Make the buffer consistent with the cache as the mac is going to write + * directly into it*/ + blist_ent_ptr->fd.FDSystem=(unsigned int)skb; + blist_ent_ptr->bd.BuffData=(char*)__pa(skb->data); + consistent_sync(skb->data,PKT_BUF_SZ,PCI_DMA_FROMDEVICE); + /* align IP on 16 Byte (DMA_CTL set to skip 2 bytes) */ + skb_reserve(skb,2); + blist_ent_ptr->bd.BuffLength=PKT_BUF_SZ-2; + blist_ent_ptr->fd.FDLength=1; + blist_ent_ptr->fd.FDCtl=FDCTL_COWNSFD_MSK; + blist_ent_ptr->bd.BDCtl=BDCTL_COWNSBD_MSK; +} + + +static int ether00_mem_init(struct net_device* dev) +{ + struct net_priv* priv=dev->priv; + struct tx_fda_ent *tx_fd_ptr,*tx_end_ptr; + struct rx_blist_ent* blist_ent_ptr; + int i; + + /* + * Grab a block of on chip SRAM to contain the control stuctures for + * the ethernet MAC. This uncached becuase it needs to be accesses by both + * bus masters (cpu + mac). However, it shouldn't matter too much in terms + * of speed as its on chip memory + */ + priv->dma_data=ioremap_nocache(EXC_SPSRAM_BLOCK0_BASE,EXC_SPSRAM_BLOCK0_SIZE ); + if (!priv->dma_data) + return -ENOMEM; + + priv->rx_fda_ptr=(struct rx_fda_ent*)priv->dma_data; + /* + * Now share it out amongst the Frame descriptors and the buffer list + */ + priv->rx_blist_vp=(struct rx_blist_ent*)((unsigned int)priv->dma_data+RX_NUM_FDESC*sizeof(struct rx_fda_ent)); + + /* + *Initalise the FDA list + */ + /* set ownership to the controller */ + memset(priv->rx_fda_ptr,0x80,RX_NUM_FDESC*sizeof(struct rx_fda_ent)); + + /* + *Initialise the buffer list + */ + blist_ent_ptr=priv->rx_blist_vp; + i=0; + while(blist_ent_ptr<(priv->rx_blist_vp+RX_NUM_BUFF)){ + struct sk_buff *skb; + blist_ent_ptr->fd.FDLength=1; + skb=dev_alloc_skb(PKT_BUF_SZ); + if(skb){ + setup_blist_entry(skb,blist_ent_ptr); + blist_ent_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(blist_ent_ptr+1); + blist_ent_ptr->bd.BDStat=i++; + blist_ent_ptr++; + } + else + { + printk("Failed to initalise buffer list\n"); + } + + } + blist_ent_ptr--; + blist_ent_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(priv->rx_blist_vp); + + priv->tx_fdalist_vp=(struct tx_fda_ent*)(priv->rx_blist_vp+RX_NUM_BUFF); + + /* Initialise the buffers to be a circular list. The mac will then go poll + * the list until it finds a frame ready to transmit */ + tx_end_ptr=priv->tx_fdalist_vp+TX_NUM_FDESC; + for(tx_fd_ptr=priv->tx_fdalist_vp;tx_fd_ptr<tx_end_ptr;tx_fd_ptr++){ + tx_fd_ptr->fd.FDNext=(FDA_DESC*)__dma_pa((tx_fd_ptr+1)); + tx_fd_ptr->fd.FDCtl=1; + tx_fd_ptr->fd.FDStat=0; + tx_fd_ptr->fd.FDLength=1; + + } + /* Change the last FDNext pointer to make a circular list */ + tx_fd_ptr--; + tx_fd_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(priv->tx_fdalist_vp); + + /* Point the device at the chain of Rx and Tx Buffers */ + writel((unsigned int)__dma_pa(priv->rx_fda_ptr),ETHER_FDA_BAS(dev->base_addr)); + writel((RX_NUM_FDESC-1)*sizeof(struct rx_fda_ent),ETHER_FDA_LIM(dev->base_addr)); + writel((unsigned int)__dma_pa(priv->rx_blist_vp),ETHER_BLFRMPTR(dev->base_addr)); + + writel((unsigned int)__dma_pa(priv->tx_fdalist_vp),ETHER_TXFRMPTR(dev->base_addr)); + + return 0; +} + + +void ether00_mem_update(void* dev_id) +{ + struct net_device* dev=dev_id; + struct net_priv* priv=dev->priv; + struct sk_buff* skb; + struct tx_fda_ent *fda_ptr=priv->tx_fdalist_vp; + struct rx_blist_ent* blist_ent_ptr; + unsigned long flags; + + priv->tq_memupdate.sync=0; + //priv->tq_memupdate.list= + priv->memupdate_scheduled=0; + + /* Transmit interrupt */ + while(fda_ptr<(priv->tx_fdalist_vp+TX_NUM_FDESC)){ + if(!(FDCTL_COWNSFD_MSK&fda_ptr->fd.FDCtl) && (ETHER_TX_STAT_COMP_MSK&fda_ptr->fd.FDStat)){ + priv->stats.tx_packets++; + priv->stats.tx_bytes+=fda_ptr->bd.BuffLength; + skb=(struct sk_buff*)fda_ptr->fd.FDSystem; + //printk("%d:txcln:fda=%#x skb=%#x\n",jiffies,fda_ptr,skb); + dev_kfree_skb(skb); + fda_ptr->fd.FDSystem=0; + fda_ptr->fd.FDStat=0; + fda_ptr->fd.FDCtl=0; + } + fda_ptr++; + } + /* Fill in any missing buffers from the received queue */ + spin_lock_irqsave(&priv->rx_lock,flags); + blist_ent_ptr=priv->rx_blist_vp; + while(blist_ent_ptr<(priv->rx_blist_vp+RX_NUM_BUFF)){ + /* fd.FDSystem of 0 indicates we failed to allocate the buffer in the ISR */ + if(!blist_ent_ptr->fd.FDSystem){ + struct sk_buff *skb; + skb=dev_alloc_skb(PKT_BUF_SZ); + blist_ent_ptr->fd.FDSystem=(unsigned int)skb; + if(skb){ + setup_blist_entry(skb,blist_ent_ptr); + } + else + { + break; + } + } + blist_ent_ptr++; + } + spin_unlock_irqrestore(&priv->rx_lock,flags); + if(priv->queue_stopped){ + //printk("%d:cln:start q\n",jiffies); + netif_start_queue(dev); + } + if(priv->rx_disabled){ + //printk("%d:enable_irq\n",jiffies); + priv->rx_disabled=0; + writel(ETHER_RX_CTL_RXEN_MSK,ETHER_RX_CTL(dev->base_addr)); + + } +} + + +static void ether00_int( int irq_num, void* dev_id, struct pt_regs* regs) +{ + struct net_device* dev=dev_id; + struct net_priv* priv=dev->priv; + + unsigned int interruptValue; + + interruptValue=readl(ETHER_INT_SRC(dev->base_addr)); + + //printk("INT_SRC=%x\n",interruptValue); + + if(!(readl(ETHER_INT_SRC(dev->base_addr)) & ETHER_INT_SRC_IRQ_MSK)) + { + return; /* Interrupt wasn't caused by us!! */ + } + + if(readl(ETHER_INT_SRC(dev->base_addr))& + (ETHER_INT_SRC_INTMACRX_MSK | + ETHER_INT_SRC_FDAEX_MSK | + ETHER_INT_SRC_BLEX_MSK)) { + struct rx_blist_ent* blist_ent_ptr; + struct rx_fda_ent* fda_ent_ptr; + struct sk_buff* skb; + + fda_ent_ptr=priv->rx_fda_ptr; + spin_lock(&priv->rx_lock); + while(fda_ent_ptr<(priv->rx_fda_ptr+RX_NUM_FDESC)){ + int result; + + if(!(fda_ent_ptr->fd.FDCtl&FDCTL_COWNSFD_MSK)) + { + /* This frame is ready for processing */ + /*find the corresponding buffer in the bufferlist */ + blist_ent_ptr=priv->rx_blist_vp+fda_ent_ptr->bd.BDStat; + skb=(struct sk_buff*)blist_ent_ptr->fd.FDSystem; + + /* Pass this skb up the stack */ + skb->dev=dev; + skb_put(skb,fda_ent_ptr->fd.FDLength); + skb->protocol=eth_type_trans(skb,dev); + skb->ip_summed=CHECKSUM_UNNECESSARY; + result=netif_rx(skb); + /* Update statistics */ + priv->stats.rx_packets++; + priv->stats.rx_bytes+=fda_ent_ptr->fd.FDLength; + + /* Free the FDA entry */ + fda_ent_ptr->bd.BDStat=0xff; + fda_ent_ptr->fd.FDCtl=FDCTL_COWNSFD_MSK; + + /* Allocate a new skb and point the bd entry to it */ + blist_ent_ptr->fd.FDSystem=0; + skb=dev_alloc_skb(PKT_BUF_SZ); + //printk("allocskb=%#x\n",skb); + if(skb){ + setup_blist_entry(skb,blist_ent_ptr); + + } + else if(!priv->memupdate_scheduled){ + int tmp; + /* There are no buffers at the moment, so schedule */ + /* the background task to sort this out */ + schedule_task(&priv->tq_memupdate); + priv->memupdate_scheduled=1; + printk(KERN_DEBUG "%s:No buffers",dev->name); + /* If this interrupt was due to a lack of buffers then + * we'd better stop the receiver too */ + if(interruptValueÐER_INT_SRC_BLEX_MSK){ + priv->rx_disabled=1; + tmp=readl(ETHER_INT_SRC(dev->base_addr)); + writel(tmp&~ETHER_RX_CTL_RXEN_MSK,ETHER_RX_CTL(dev->base_addr)); + printk(KERN_DEBUG "%s:Halting rx",dev->name); + } + + } + + } + fda_ent_ptr++; + } + spin_unlock(&priv->rx_lock); + + /* Clear the interrupts */ + writel(ETHER_INT_SRC_INTMACRX_MSK | ETHER_INT_SRC_FDAEX_MSK + | ETHER_INT_SRC_BLEX_MSK,ETHER_INT_SRC(dev->base_addr)); + + } + + if(readl(ETHER_INT_SRC(dev->base_addr))ÐER_INT_SRC_INTMACTX_MSK){ + + if(!priv->memupdate_scheduled){ + schedule_task(&priv->tq_memupdate); + priv->memupdate_scheduled=1; + } + /* Clear the interrupt */ + writel(ETHER_INT_SRC_INTMACTX_MSK,ETHER_INT_SRC(dev->base_addr)); + } + + if (readl(ETHER_INT_SRC(dev->base_addr)) & (ETHER_INT_SRC_SWINT_MSK| + ETHER_INT_SRC_INTEARNOT_MSK| + ETHER_INT_SRC_INTLINK_MSK| + ETHER_INT_SRC_INTEXBD_MSK| + ETHER_INT_SRC_INTTXCTLCMP_MSK)) + { + /* + * Not using any of these so they shouldn't happen + * + * In the cased of INTEXBD - if you allocate more + * than 28 decsriptors you may need to think about this + */ + printk("Not using this interrupt\n"); + } + + if (readl(ETHER_INT_SRC(dev->base_addr)) & + (ETHER_INT_SRC_INTSBUS_MSK | + ETHER_INT_SRC_INTNRABT_MSK + |ETHER_INT_SRC_DMPARERR_MSK)) + { + /* + * Hardware errors, we can either ignore them and hope they go away + *or reset the device, I'll try the first for now to see if they happen + */ + printk("Hardware error\n"); + } +} + +static void ether00_setup_ethernet_address(struct net_device* dev) +{ + int tmp; + + dev->addr_len=6; + writew(0,ETHER_ARC_ADR(dev->base_addr)); + writel((dev->dev_addr[0]<<24) | + (dev->dev_addr[1]<<16) | + (dev->dev_addr[2]<<8) | + dev->dev_addr[3], + ETHER_ARC_DATA(dev->base_addr)); + + writew(4,ETHER_ARC_ADR(dev->base_addr)); + tmp=readl(ETHER_ARC_DATA(dev->base_addr)); + tmp&=0xffff; + tmp|=(dev->dev_addr[4]<<24) | (dev->dev_addr[5]<<16); + writel(tmp, ETHER_ARC_DATA(dev->base_addr)); + /* Enable this entry in the ARC */ + + writel(1,ETHER_ARC_ENA(dev->base_addr)); + + return; +} + + +static void ether00_reset(struct net_device *dev) +{ + /* reset the controller */ + writew(ETHER_MAC_CTL_RESET_MSK,ETHER_MAC_CTL(dev->base_addr)); + + /* + * Make sure we're not going to send anything + */ + + writew(ETHER_TX_CTL_TXHALT_MSK,ETHER_TX_CTL(dev->base_addr)); + + /* + * Make sure we're not going to receive anything + */ + writew(ETHER_RX_CTL_RXHALT_MSK,ETHER_RX_CTL(dev->base_addr)); + + /* + * Disable Interrupts for now, and set the burst size to 8 bytes + */ + + writel(ETHER_DMA_CTL_INTMASK_MSK | + ((8 << ETHER_DMA_CTL_DMBURST_OFST) & ETHER_DMA_CTL_DMBURST_MSK) + |(2<<ETHER_DMA_CTL_RXALIGN_OFST), + ETHER_DMA_CTL(dev->base_addr)); + + + /* + * Set TxThrsh - start transmitting a packet after 1514 + * bytes or when a packet is complete, whichever comes first + */ + writew(1514,ETHER_TXTHRSH(dev->base_addr)); + + /* + * Set TxPollCtr. Each cycle is + * 61.44 microseconds with a 33 MHz bus + */ + writew(1,ETHER_TXPOLLCTR(dev->base_addr)); + + /* + * Set Rx_Ctl - Turn off reception and let RxData turn it + * on later + */ + writew(ETHER_RX_CTL_RXHALT_MSK,ETHER_RX_CTL(dev->base_addr)); + +} + + +static void ether00_set_multicast(struct net_device* dev) +{ + int count=dev->mc_count; + + /* Set promiscuous mode if it's asked for. */ + + if (dev->flags&IFF_PROMISC){ + + writew( ETHER_ARC_CTL_COMPEN_MSK | + ETHER_ARC_CTL_BROADACC_MSK | + ETHER_ARC_CTL_GROUPACC_MSK | + ETHER_ARC_CTL_STATIONACC_MSK, + ETHER_ARC_CTL(dev->base_addr)); + return; + } + + /* + * Get all multicast packets if required, or if there are too + * many addresses to fit in hardware + */ + if (dev->flags & IFF_ALLMULTI){ + writew( ETHER_ARC_CTL_COMPEN_MSK | + ETHER_ARC_CTL_GROUPACC_MSK | + ETHER_ARC_CTL_BROADACC_MSK, + ETHER_ARC_CTL(dev->base_addr)); + return; + } + if (dev->mc_count > (ETHER_ARC_SIZE - 1)){ + + printk(KERN_WARNING "Too many multicast addresses for hardware to filter - receiving all multicast packets\n"); + writew( ETHER_ARC_CTL_COMPEN_MSK | + ETHER_ARC_CTL_GROUPACC_MSK | + ETHER_ARC_CTL_BROADACC_MSK, + ETHER_ARC_CTL(dev->base_addr)); + return; + } + + if(dev->mc_count){ + struct dev_mc_list *mc_list_ent=dev->mc_list; + unsigned int temp,i; + DEBUG(printk("mc_count=%d mc_list=%#x\n",dev-> mc_count, dev->mc_list)); + DEBUG(printk("mc addr=%02#x%02x%02x%02x%02x%02x\n", + mc_list_ent->dmi_addr[5], + mc_list_ent->dmi_addr[4], + mc_list_ent->dmi_addr[3], + mc_list_ent->dmi_addr[2], + mc_list_ent->dmi_addr[1], + mc_list_ent->dmi_addr[0]);) + + /* + * The first 6 bytes are the MAC address, so + * don't change them! + */ + writew(4,ETHER_ARC_ADR(dev->base_addr)); + temp=readl(ETHER_ARC_DATA(dev->base_addr)); + temp&=0xffff0000; + + /* Disable the current multicast stuff */ + writel(1,ETHER_ARC_ENA(dev->base_addr)); + + for(;;){ + temp|=mc_list_ent->dmi_addr[1] | + mc_list_ent->dmi_addr[0]<<8; + writel(temp,ETHER_ARC_DATA(dev->base_addr)); + + i=readl(ETHER_ARC_ADR(dev->base_addr)); + writew(i+4,ETHER_ARC_ADR(dev->base_addr)); + + temp=mc_list_ent->dmi_addr[5]| + mc_list_ent->dmi_addr[4]<<8 | + mc_list_ent->dmi_addr[3]<<16 | + mc_list_ent->dmi_addr[2]<<24; + writel(temp,ETHER_ARC_DATA(dev->base_addr)); + + count--; + if(!mc_list_ent->next || !count){ + break; + } + DEBUG(printk("mc_list_next=%#x\n",mc_list_ent->next);) + mc_list_ent=mc_list_ent->next; + + + i=readl(ETHER_ARC_ADR(dev->base_addr)); + writel(i+4,ETHER_ARC_ADR(dev->base_addr)); + + temp=mc_list_ent->dmi_addr[3]| + mc_list_ent->dmi_addr[2]<<8 | + mc_list_ent->dmi_addr[1]<<16 | + mc_list_ent->dmi_addr[0]<<24; + writel(temp,ETHER_ARC_DATA(dev->base_addr)); + + i=readl(ETHER_ARC_ADR(dev->base_addr)); + writel(i+4,ETHER_ARC_ADR(dev->base_addr)); + + temp=mc_list_ent->dmi_addr[4]<<16 | + mc_list_ent->dmi_addr[5]<<24; + + writel(temp,ETHER_ARC_DATA(dev->base_addr)); + + count--; + if(!mc_list_ent->next || !count){ + break; + } + mc_list_ent=mc_list_ent->next; + } + + + if(count) + printk(KERN_WARNING "Multicast list size error\n"); + + + writew( ETHER_ARC_CTL_BROADACC_MSK| + ETHER_ARC_CTL_COMPEN_MSK, + ETHER_ARC_CTL(dev->base_addr)); + + } + + /* enable the active ARC enties */ + writew((1<<(count+2))-1,ETHER_ARC_ENA(dev->base_addr)); +} + + +static int ether00_open(struct net_device* dev) +{ + int result,tmp; + struct net_priv* priv; + + if (!is_valid_ether_addr(dev->dev_addr)) + return -EINVAL; + + /* Allocate private memory */ + dev->priv=kmalloc(sizeof(struct net_priv),GFP_KERNEL); + if(!dev->priv) + return -ENOMEM; + memset(dev->priv,0,sizeof(struct net_priv)); + priv=(struct net_priv*)dev->priv; + priv->tq_memupdate.routine=ether00_mem_update; + priv->tq_memupdate.data=(void*) dev; + spin_lock_init(&priv->rx_lock); + + /* Install interrupt handlers */ + result=request_irq(dev->irq,ether00_int,0,"ether00",dev); + if(result) + goto open_err1; + + result=request_irq(2,ether00_phy_int,0,"ether00_phy",dev); + if(result) + goto open_err2; + + ether00_reset(dev); + result=ether00_mem_init(dev); + if(result) + goto open_err3; + + + ether00_setup_ethernet_address(dev); + + ether00_set_multicast(dev); + + result=ether00_write_phy(dev,PHY_CONTROL, PHY_CONTROL_ANEGEN_MSK | PHY_CONTROL_RANEG_MSK); + if(result) + goto open_err4; + result=ether00_write_phy(dev,PHY_IRQ_CONTROL, PHY_IRQ_CONTROL_LS_CHG_IE_MSK | + PHY_IRQ_CONTROL_ANEG_COMP_IE_MSK); + if(result) + goto open_err4; + + /* Start the device enable interrupts */ + writew(ETHER_RX_CTL_RXEN_MSK +// | ETHER_RX_CTL_STRIPCRC_MSK + | ETHER_RX_CTL_ENGOOD_MSK + | ETHER_RX_CTL_ENRXPAR_MSK| ETHER_RX_CTL_ENLONGERR_MSK + | ETHER_RX_CTL_ENOVER_MSK| ETHER_RX_CTL_ENCRCERR_MSK, + ETHER_RX_CTL(dev->base_addr)); + + writew(ETHER_TX_CTL_TXEN_MSK| + ETHER_TX_CTL_ENEXDEFER_MSK| + ETHER_TX_CTL_ENLCARR_MSK| + ETHER_TX_CTL_ENEXCOLL_MSK| + ETHER_TX_CTL_ENLATECOLL_MSK| + ETHER_TX_CTL_ENTXPAR_MSK| + ETHER_TX_CTL_ENCOMP_MSK, + ETHER_TX_CTL(dev->base_addr)); + + tmp=readl(ETHER_DMA_CTL(dev->base_addr)); + writel(tmp&~ETHER_DMA_CTL_INTMASK_MSK,ETHER_DMA_CTL(dev->base_addr)); + + return 0; + + open_err4: + ether00_reset(dev); + open_err3: + free_irq(2,dev); + open_err2: + free_irq(dev->irq,dev); + open_err1: + kfree(dev->priv); + return result; + +} + + +static int ether00_tx(struct sk_buff* skb, struct net_device* dev) +{ + struct net_priv *priv=dev->priv; + struct tx_fda_ent *fda_ptr; + int i; + + + /* + * Find an empty slot in which to stick the frame + */ + fda_ptr=(struct tx_fda_ent*)__dma_va(readl(ETHER_TXFRMPTR(dev->base_addr))); + i=0; + while(i<TX_NUM_FDESC){ + if (fda_ptr->fd.FDStat||(fda_ptr->fd.FDCtl & FDCTL_COWNSFD_MSK)){ + fda_ptr =(struct tx_fda_ent*) __dma_va((struct tx_fda_ent*)fda_ptr->fd.FDNext); + } + else { + break; + } + i++; + } + + /* Write the skb data from the cache*/ + consistent_sync(skb->data,skb->len,PCI_DMA_TODEVICE); + fda_ptr->bd.BuffData=(char*)__pa(skb->data); + fda_ptr->bd.BuffLength=(unsigned short)skb->len; + /* Save the pointer to the skb for freeing later */ + fda_ptr->fd.FDSystem=(unsigned int)skb; + fda_ptr->fd.FDStat=0; + /* Pass ownership of the buffers to the controller */ + fda_ptr->fd.FDCtl=1; + fda_ptr->fd.FDCtl|=FDCTL_COWNSFD_MSK; + + /* If the next buffer in the list is full, stop the queue */ + fda_ptr=(struct tx_fda_ent*)__dma_va(fda_ptr->fd.FDNext); + if ((fda_ptr->fd.FDStat)||(fda_ptr->fd.FDCtl & FDCTL_COWNSFD_MSK)){ + netif_stop_queue(dev); + priv->queue_stopped=1; + } + + return 0; +} + +static struct net_device_stats *ether00_stats(struct net_device* dev) +{ + struct net_priv *priv=dev->priv; + return &priv->stats; +} + + +static int ether00_stop(struct net_device* dev) +{ + struct net_priv *priv=dev->priv; + int tmp; + + /* Stop/disable the device. */ + tmp=readw(ETHER_RX_CTL(dev->base_addr)); + tmp&=~(ETHER_RX_CTL_RXEN_MSK | ETHER_RX_CTL_ENGOOD_MSK); + tmp|=ETHER_RX_CTL_RXHALT_MSK; + writew(tmp,ETHER_RX_CTL(dev->base_addr)); + + tmp=readl(ETHER_TX_CTL(dev->base_addr)); + tmp&=~ETHER_TX_CTL_TXEN_MSK; + tmp|=ETHER_TX_CTL_TXHALT_MSK; + writel(tmp,ETHER_TX_CTL(dev->base_addr)); + + /* Free up system resources */ + free_irq(dev->irq,dev); + free_irq(2,dev); + iounmap(priv->dma_data); + kfree(priv); + + return 0; +} + + +static void ether00_get_ethernet_address(struct net_device* dev) +{ + struct mtd_info *mymtd=NULL; + int i; + size_t retlen; + + /* + * For the Epxa10 dev board (camelot), the ethernet MAC + * address is of the form 00:aa:aa:00:xx:xx where + * 00:aa:aa is the Altera vendor ID and xx:xx is the + * last 2 bytes of the board serial number, as programmed + * into the OTP area of the flash device on EBI1. If this + * isn't an expa10 dev board, or there's no mtd support to + * read the serial number from flash then we'll force the + * use to set their own mac address using ifconfig. + */ + +#ifdef CONFIG_ARCH_CAMELOT +#ifdef CONFIG_MTD + /* get the mtd_info structure for the first mtd device*/ + for(i=0;i<MAX_MTD_DEVICES;i++){ + mymtd=get_mtd_device(NULL,i); + if(!mymtd||!strcmp(mymtd->name,"EPXA10DB flash")) + break; + } + + if(!mymtd || !mymtd->read_user_prot_reg){ + printk(KERN_WARNING "%s: Failed to read MAC address from flash\n",dev->name); + }else{ + mymtd->read_user_prot_reg(mymtd,2,1,&retlen,&dev->dev_addr[5]); + mymtd->read_user_prot_reg(mymtd,3,1,&retlen,&dev->dev_addr[4]); + dev->dev_addr[3]=0; + dev->dev_addr[2]=vendor_id[1]; + dev->dev_addr[1]=vendor_id[0]; + dev->dev_addr[0]=0; + } +#else + printk(KERN_WARNING "%s: MTD support required to read MAC address from EPXA10 dev board\n", dev->name); +#endif +#endif + + if (!is_valid_ether_addr(dev->dev_addr)) + printk("%s: Invalid ethernet MAC address. Please set using " + "ifconfig\n", dev->name); + +} + +static int ether00_init(struct net_device* dev) +{ + + ether_setup(dev); + + dev->open=ether00_open; + dev->stop=ether00_stop; + dev->set_multicast_list=ether00_set_multicast; + dev->hard_start_xmit=ether00_tx; + dev->get_stats=ether00_stats; + + ether00_get_ethernet_address(dev); + + SET_MODULE_OWNER(dev); + return 0; +} + +/* + * Keep a mapping of dev_info addresses -> port lines to use when + * removing ports dev==NULL indicates unused entry + */ + + +static struct net_device* dev_list[ETH_NR]; + +static int ether00_add_device(struct pldhs_dev_info* dev_info,void* dev_ps_data) +{ + struct net_device *dev; + void *map_addr; + int result; + int i; + + + i=0; + while(dev_list[i]) + i++; + + if(i==ETH_NR){ + printk(KERN_WARNING "ether00: Maximum number of ports reached\n"); + return 0; + } + + + dev=kmalloc(sizeof(struct net_device),GFP_KERNEL); + if(!dev){ + return -ENOMEM; + } + memset(dev,0,sizeof(struct net_device)); + map_addr=ioremap_nocache(dev_info->base_addr,SZ_4K); + if(!map_addr){ + return -ENOMEM; + } + + dev->init=ether00_init; + strcpy(dev->name,"eth%d"); + dev->base_addr=(unsigned int)map_addr; + dev->irq=dev_info->irq; + dev->features=NETIF_F_DYNALLOC | NETIF_F_HW_CSUM; + + if(check_mem_region((unsigned int)map_addr, MAC_REG_SIZE)){ + return -EBUSY; + } + request_mem_region((unsigned int)map_addr, MAC_REG_SIZE, "ether00"); + + result=register_netdev(dev); + if(result){ + printk("Ether00: Error %i registering driver\n",result); + return result; + } + printk("registered ether00 device at %#x\n",dev_info->base_addr); + + dev_list[i]=dev; + + return result; +} + + +static int ether00_remove_devices(void) +{ + int i; + + for(i=0;i<ETH_NR;i++){ + if(dev_list[i]){ + netif_device_detach(dev_list[i]); + unregister_netdev(dev_list[i]); + iounmap((void*)dev_list[i]->base_addr); + release_mem_region(dev_list[i]->base_addr, MAC_REG_SIZE); + kfree(dev_list[i]); + dev_list[i]=0; + } + } + return 0; +} + +static struct pld_hotswap_ops ether00_pldhs_ops={ + name: ETHER00_NAME, + add_device: ether00_add_device, + remove_devices: ether00_remove_devices, +}; + + +static void __exit ether00_cleanup_module(void) +{ + int result; + result=ether00_remove_devices(); + if(result) + printk(KERN_WARNING "ether00: failed to remove all devices\n"); + + pldhs_unregister_driver(ETHER00_NAME); +} +module_exit(ether00_cleanup_module); + + +static int __init ether00_mod_init(void) +{ + printk("mod init\n"); + return pldhs_register_driver(ðer00_pldhs_ops); + +} + +module_init(ether00_mod_init); + diff --git a/drivers/acorn/net/ether1.c b/drivers/net/arm/ether1.c index 758ff8bb8231..1ceee2381085 100644 --- a/drivers/acorn/net/ether1.c +++ b/drivers/net/arm/ether1.c @@ -450,6 +450,7 @@ ether1_init_for_open (struct net_device *dev) struct ether1_priv *priv = (struct ether1_priv *)dev->priv; int i, status, addr, next, next2; int failures = 0; + unsigned long timeout; outb (CTRL_RST|CTRL_ACK, REG_CONTROL); @@ -515,19 +516,19 @@ ether1_init_for_open (struct net_device *dev) outb (CTRL_CA, REG_CONTROL); /* 586 should now unset iscp.busy */ - i = jiffies + HZ/2; + timeout = jiffies + HZ/2; while (ether1_inw (dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) { - if (time_after(jiffies, i)) { + if (time_after(jiffies, timeout)) { printk (KERN_WARNING "%s: can't initialise 82586: iscp is busy\n", dev->name); return 1; } } /* check status of commands that we issued */ - i += HZ/10; + timeout += HZ/10; while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS)) & STAT_COMPLETE) == 0) { - if (time_after(jiffies, i)) + if (time_after(jiffies, timeout)) break; } @@ -541,10 +542,10 @@ ether1_init_for_open (struct net_device *dev) failures += 1; } - i += HZ/10; + timeout += HZ/10; while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS)) & STAT_COMPLETE) == 0) { - if (time_after(jiffies, i)) + if (time_after(jiffies, timeout)) break; } @@ -558,10 +559,10 @@ ether1_init_for_open (struct net_device *dev) failures += 1; } - i += HZ/10; + timeout += HZ/10; while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS)) & STAT_COMPLETE) == 0) { - if (time_after(jiffies, i)) + if (time_after(jiffies, timeout)) break; } @@ -575,10 +576,10 @@ ether1_init_for_open (struct net_device *dev) failures += 1; } - i += HZ; + timeout += HZ; while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS)) & STAT_COMPLETE) == 0) { - if (time_after(jiffies, i)) + if (time_after(jiffies, timeout)) break; } diff --git a/drivers/acorn/net/ether1.h b/drivers/net/arm/ether1.h index 790bb97cac29..790bb97cac29 100644 --- a/drivers/acorn/net/ether1.h +++ b/drivers/net/arm/ether1.h diff --git a/drivers/acorn/net/ether3.c b/drivers/net/arm/ether3.c index 2a2e8f6cc948..2a2e8f6cc948 100644 --- a/drivers/acorn/net/ether3.c +++ b/drivers/net/arm/ether3.c diff --git a/drivers/acorn/net/ether3.h b/drivers/net/arm/ether3.h index fd0c2edf57fe..fd0c2edf57fe 100644 --- a/drivers/acorn/net/ether3.h +++ b/drivers/net/arm/ether3.h diff --git a/drivers/acorn/net/etherh.c b/drivers/net/arm/etherh.c index 039c74d71dd4..72e6726230a4 100644 --- a/drivers/acorn/net/etherh.c +++ b/drivers/net/arm/etherh.c @@ -51,7 +51,7 @@ #include <asm/io.h> #include <asm/irq.h> -#include "../../net/8390.h" +#include "../8390.h" #define NET_DEBUG 0 #define DEBUG_INIT 2 diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index c95c70dd1f93..ce059524a7a2 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -636,13 +636,14 @@ static void sa1100_irda_fir_irq(struct net_device *dev) sa1100_irda_rx_dma_start(si); } -static void sa1100_irda_irq(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sa1100_irda_irq(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; if (IS_FIR(((struct sa1100_irda *)dev->priv))) sa1100_irda_fir_irq(dev); else sa1100_irda_hpsir_irq(dev); + return IRQ_HANDLED; } /* diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 7c79bb82cc20..ed511c0a45e5 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1602,7 +1602,7 @@ config SCSI_MAC53C94 whenever you want). If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. -source "drivers/acorn/scsi/Kconfig" +source "drivers/scsi/arm/Kconfig" config JAZZ_ESP bool "MIPS JAZZ FAS216 SCSI support" diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 8c9591fe0817..fd556972ba4e 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -114,7 +114,7 @@ obj-$(CONFIG_SCSI_CPQFCTS) += cpqfc.o obj-$(CONFIG_SCSI_LASI700) += lasi700.o 53c700.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o -obj-$(CONFIG_ARCH_ACORN) += ../acorn/scsi/ +obj-$(CONFIG_ARM) += arm/ obj-$(CONFIG_CHR_DEV_ST) += st.o obj-$(CONFIG_CHR_DEV_OSST) += osst.o diff --git a/drivers/acorn/scsi/Kconfig b/drivers/scsi/arm/Kconfig index 54b32868aaf7..54b32868aaf7 100644 --- a/drivers/acorn/scsi/Kconfig +++ b/drivers/scsi/arm/Kconfig diff --git a/drivers/acorn/scsi/Makefile b/drivers/scsi/arm/Makefile index aa143604372e..e8db17924c1d 100644 --- a/drivers/acorn/scsi/Makefile +++ b/drivers/scsi/arm/Makefile @@ -1,5 +1,5 @@ # -# Makefile for drivers/acorn/scsi +# Makefile for drivers/scsi/arm # acornscsi_mod-objs := acornscsi.o acornscsi-io.o diff --git a/drivers/acorn/scsi/acornscsi-io.S b/drivers/scsi/arm/acornscsi-io.S index 93467e6ac923..93467e6ac923 100644 --- a/drivers/acorn/scsi/acornscsi-io.S +++ b/drivers/scsi/arm/acornscsi-io.S diff --git a/drivers/acorn/scsi/acornscsi.c b/drivers/scsi/arm/acornscsi.c index 89ccd50afde2..c891ca6018dc 100644 --- a/drivers/acorn/scsi/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -149,8 +149,8 @@ #include <asm/irq.h> #include <asm/ecard.h> -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" +#include "../scsi.h" +#include "../hosts.h" #include "acornscsi.h" #include "msgqueue.h" #include "scsi.h" @@ -2931,6 +2931,35 @@ int acornscsi_proc_info(char *buffer, char **start, off_t offset, } } + p += sprintf(p, "\nAttached devices:\n"); + + list_for_each_entry(scd, &instance->my_devices, siblings) { + p += sprintf(p, "Device/Lun TaggedQ Sync\n"); + p += sprintf(p, " %d/%d ", scd->id, scd->lun); + if (scd->tagged_supported) + p += sprintf(p, "%3sabled(%3d) ", + scd->tagged_queue ? "en" : "dis", + scd->current_tag); + else + p += sprintf(p, "unsupported "); + + if (host->device[scd->id].sync_xfer & 15) + p += sprintf(p, "offset %d, %d ns\n", + host->device[scd->id].sync_xfer & 15, + acornscsi_getperiod(host->device[scd->id].sync_xfer)); + else + p += sprintf(p, "async\n"); + + pos = p - buffer; + if (pos + begin < offset) { + begin += pos; + p = buffer; + } + pos = p - buffer; + if (pos + begin > offset + length) + break; + } + pos = p - buffer; *start = buffer + (offset - begin); diff --git a/drivers/acorn/scsi/acornscsi.h b/drivers/scsi/arm/acornscsi.h index 457929b24925..8e4d88d0aba3 100644 --- a/drivers/acorn/scsi/acornscsi.h +++ b/drivers/scsi/arm/acornscsi.h @@ -298,7 +298,6 @@ typedef struct acornscsi_hostdata { unsigned short last_message; /* last message to be sent */ unsigned char disconnectable:1; /* this command can be disconnected */ - unsigned char interrupt:1; /* interrupt active */ } scsi; /* statistics information */ diff --git a/drivers/acorn/scsi/arxescsi.c b/drivers/scsi/arm/arxescsi.c index 26beb3960608..8e0b75f52140 100644 --- a/drivers/acorn/scsi/arxescsi.c +++ b/drivers/scsi/arm/arxescsi.c @@ -29,14 +29,15 @@ #include <linux/stat.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <asm/dma.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/ecard.h> -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" +#include "../scsi.h" +#include "../hosts.h" #include "fas216.h" struct arxescsi_info { @@ -238,10 +239,10 @@ static int arxescsi_proc_info(char *buffer, char **start, off_t offset, int length, int host_no, int inout) { - int pos, begin; struct Scsi_Host *host; struct arxescsi_info *info; - Scsi_Device *scd; + char *p = buffer; + int pos; host = scsi_host_hn_get(host_no); if (!host) @@ -251,26 +252,13 @@ arxescsi_proc_info(char *buffer, char **start, off_t offset, int length, if (inout == 1) return -EINVAL; - begin = 0; - pos = sprintf(buffer, "ARXE 16-bit SCSI driver v%s\n", VERSION); - pos += fas216_print_host(&info->info, buffer + pos); - pos += fas216_print_stats(&info->info, buffer + pos); + p += sprintf(p, "ARXE 16-bit SCSI driver v%s\n", VERSION); + p += fas216_print_host(&info->info, p); + p += fas216_print_stats(&info->info, p); + p += fas216_print_devices(&info->info, p); - pos += sprintf (buffer+pos, "\nAttached devices:\n"); - - list_for_each_entry(scd, &host->my_devices, siblings) { - pos += fas216_print_device(&info->info, scd, buffer + pos); - - if (pos + begin < offset) { - begin += pos; - pos = 0; - } - if (pos + begin > offset + length) - break; - } - - *start = buffer + (offset - begin); - pos -= offset - begin; + *start = buffer + offset; + pos = p - buffer - offset; if (pos > length) pos = length; diff --git a/drivers/acorn/scsi/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 222c8fc88b56..8a953eff5756 100644 --- a/drivers/acorn/scsi/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -16,8 +16,8 @@ #include <asm/irq.h> #include <asm/system.h> -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" +#include "../scsi.h" +#include "../hosts.h" #include <scsi/scsicam.h> @@ -41,7 +41,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, #define BOARD_NORMAL 0 #define BOARD_NCR53C400 1 -#include "../../scsi/NCR5380.h" +#include "../NCR5380.h" void cumanascsi_setup(char *str, int *ints) { @@ -239,7 +239,7 @@ static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value) #undef CTRL -#include "../../scsi/NCR5380.c" +#include "../NCR5380.c" static Scsi_Host_Template cumanascsi_template = { .module = THIS_MODULE, diff --git a/drivers/acorn/scsi/cumana_2.c b/drivers/scsi/arm/cumana_2.c index 72fbeba6e59b..3cd4a6389398 100644 --- a/drivers/acorn/scsi/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -34,8 +34,8 @@ #include <asm/irq.h> #include <asm/pgtable.h> -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" +#include "../scsi.h" +#include "../hosts.h" #include "fas216.h" #include "scsi.h" @@ -356,10 +356,10 @@ cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length) int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, int length, int host_no, int inout) { - int pos, begin; struct Scsi_Host *host; struct cumanascsi2_info *info; - Scsi_Device *scd; + char *p = buffer; + int pos; host = scsi_host_hn_get(host_no); if (!host) @@ -370,18 +370,16 @@ int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, info = (struct cumanascsi2_info *)host->hostdata; - begin = 0; - pos = sprintf(buffer, "Cumana SCSI II driver v%s\n", VERSION); - pos += fas216_print_host(&info->info, buffer + pos); - pos += sprintf(buffer + pos, "Term : o%s\n", + p += sprintf(p, "Cumana SCSI II driver v%s\n", VERSION); + p += fas216_print_host(&info->info, p); + p += sprintf(p, "Term : o%s\n", info->terms ? "n" : "ff"); - pos += fas216_print_stats(&info->info, buffer + pos); + p += fas216_print_stats(&info->info, p); + p += fas216_print_devices(&info->info, p); - pos += sprintf(buffer+pos, "\nAttached devices:\n"); - - *start = buffer + (offset - begin); - pos -= offset - begin; + *start = buffer + offset; + pos = p - buffer - offset; if (pos > length) pos = length; diff --git a/drivers/acorn/scsi/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c index e7c6282cb654..5c3fcc6030d0 100644 --- a/drivers/acorn/scsi/ecoscsi.c +++ b/drivers/scsi/arm/ecoscsi.c @@ -52,8 +52,8 @@ #include <asm/io.h> #include <asm/system.h> -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" +#include "../scsi.h" +#include "../hosts.h" #define NCR5380_implementation_fields int port, ctrl #define NCR5380_local_declare() struct Scsi_Host *_instance @@ -66,7 +66,7 @@ #define NCR5380_queue_command ecoscsi_queue_command #define NCR5380_proc_info ecoscsi_proc_info -#include "../../scsi/NCR5380.h" +#include "../NCR5380.h" #define ECOSCSI_PUBLIC_RELEASE 1 @@ -239,7 +239,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, #define BOARD_NORMAL 0 #define BOARD_NCR53C400 1 -#include "../../scsi/NCR5380.c" +#include "../NCR5380.c" static Scsi_Host_Template ecoscsi_template = { .module = THIS_MODULE, diff --git a/drivers/acorn/scsi/eesox.c b/drivers/scsi/arm/eesox.c index 8cf24304c5e9..cb4cd0f87e37 100644 --- a/drivers/acorn/scsi/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -40,8 +40,8 @@ #include <asm/ecard.h> #include <asm/pgtable.h> -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" +#include "../scsi.h" +#include "../hosts.h" #include "fas216.h" #include "scsi.h" @@ -430,10 +430,10 @@ eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) int eesoxscsi_proc_info(char *buffer, char **start, off_t offset, int length, int host_no, int inout) { - int pos, begin; struct Scsi_Host *host; struct eesoxscsi_info *info; - Scsi_Device *scd; + char *p = buffer; + int pos; host = scsi_host_hn_get(host_no); if (!host) @@ -444,16 +444,15 @@ int eesoxscsi_proc_info(char *buffer, char **start, off_t offset, info = (struct eesoxscsi_info *)host->hostdata; - begin = 0; - pos = sprintf(buffer, "EESOX SCSI driver v%s\n", VERSION); - pos += fas216_print_host(&info->info, buffer + pos); - pos += sprintf(buffer + pos, "Term : o%s\n", + p += sprintf(p, "EESOX SCSI driver v%s\n", VERSION); + p += fas216_print_host(&info->info, p); + p += sprintf(p, "Term : o%s\n", info->control & EESOX_TERM_ENABLE ? "n" : "ff"); pos += fas216_print_stats(&info->info, buffer + pos); + p += fas216_print_stats(&info->info, p); + p += fas216_print_devices(&info->info, p); - *start = buffer + (offset - begin); - pos -= offset - begin; if (pos > length) pos = length; diff --git a/drivers/acorn/scsi/fas216.c b/drivers/scsi/arm/fas216.c index c1b2f360b142..5b5d93ace30f 100644 --- a/drivers/acorn/scsi/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -44,14 +44,15 @@ #include <linux/delay.h> #include <linux/bitops.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <asm/dma.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/ecard.h> -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" +#include "../scsi.h" +#include "../hosts.h" #include "fas216.h" #include "scsi.h" @@ -79,7 +80,6 @@ * I was thinking that this was a good chip until I found this restriction ;( */ #define SCSI2_SYNC -#undef SCSI2_WIDE #undef SCSI2_TAG #undef DEBUG_CONNECT @@ -96,6 +96,8 @@ static int level_mask = LOG_ERROR; +MODULE_PARM(level_mask, "i"); + static int __init fas216_log_setup(char *str) { char *s; @@ -199,10 +201,8 @@ static void fas216_dumpinfo(FAS216_Info *info) info->scsi.io_port, info->scsi.io_shift, info->scsi.irq, info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2], info->scsi.cfg[3]); - printk(" type=%p phase=%X reconnected={ target=%d lun=%d tag=%d }\n", - info->scsi.type, info->scsi.phase, - info->scsi.reconnected.target, - info->scsi.reconnected.lun, info->scsi.reconnected.tag); + printk(" type=%p phase=%X\n", + info->scsi.type, info->scsi.phase); print_SCp(&info->scsi.SCp, " SCp={ ", " }\n"); printk(" msgs async_stp=%X disconnectable=%d aborting=%d }\n", info->scsi.async_stp, @@ -265,21 +265,24 @@ static const char *fas216_bus_phase(int stat) static const char *fas216_drv_phase(FAS216_Info *info) { - switch (info->scsi.phase) { - case PHASE_IDLE: return "idle"; - case PHASE_SELECTION: return "selection"; - case PHASE_COMMAND: return "command"; - case PHASE_RECONNECTED: return "reconnected"; - case PHASE_DATAOUT: return "data out"; - case PHASE_DATAIN: return "data in"; - case PHASE_MSGIN: return "message in"; - case PHASE_MSGIN_DISCONNECT: return "disconnect"; - case PHASE_MSGOUT_EXPECT: return "expect message out"; - case PHASE_MSGOUT: return "message out"; - case PHASE_STATUS: return "status"; - case PHASE_DONE: return "done"; - default: return "???"; - } + static const char *phases[] = { + [PHASE_IDLE] = "idle", + [PHASE_SELECTION] = "selection", + [PHASE_COMMAND] = "command", + [PHASE_DATAOUT] = "data out", + [PHASE_DATAIN] = "data in", + [PHASE_MSGIN] = "message in", + [PHASE_MSGIN_DISCONNECT]= "disconnect", + [PHASE_MSGOUT_EXPECT] = "expect message out", + [PHASE_MSGOUT] = "message out", + [PHASE_STATUS] = "status", + [PHASE_DONE] = "done", + }; + + if (info->scsi.phase < ARRAY_SIZE(phases) && + phases[info->scsi.phase]) + return phases[info->scsi.phase]; + return "???"; } static char fas216_target(FAS216_Info *info) @@ -407,25 +410,6 @@ static void print_debug_list(void) static void fas216_done(FAS216_Info *info, unsigned int result); /** - * fas216_clockrate - calculate clock conversion factor - * @clock: clock speed in MHz - * - * Calculate correct value to be written into clock conversion factor - * register. Returns CLKF_ value. - */ -static int fas216_clockrate(int clock) -{ - if (clock <= 10 || clock > 40) { - printk(KERN_CRIT - "fas216: invalid clock rate: check your driver!\n"); - clock = -1; - } else - clock = ((clock - 1) / 5 + 1) & 7; - - return clock; -} - -/** * fas216_get_last_msg - retrive last message from the list * @info: interface to search * @pos: current fifo position @@ -641,105 +625,6 @@ static void fas216_handlesync(FAS216_Info *info, char *msg) } /** - * fas216_handlewide - Handle a wide transfer message - * @info: state structure for interface - * @msg: message from target - * - * Handle a wide transfer message from the target - */ -static void fas216_handlewide(FAS216_Info *info, char *msg) -{ - struct fas216_device *dev = &info->device[info->SCpnt->device->id]; - enum { wide, bit8, none, reject } res = none; - -#ifdef SCSI2_WIDE - switch (msg[0]) { - case MESSAGE_REJECT: - /* Wide transfer request failed. - * Note: SCSI II r10: - * - * SCSI devices that are capable of wide - * data transfers shall not respond to a - * WDTR message with a MESSAGE REJECT message. - * - * Hence, if we get this condition, we never - * reattempt negotiation for this device. - */ - if (dev->wide_state == neg_inprogress) { - dev->wide_state = neg_invalid; - res = bit8; - } - break; - - case EXTENDED_MESSAGE: - switch (dev->wide_state) { - /* We don't accept wide data transfer requests. - * Respond with a MESSAGE REJECT to prevent a - * wide data transfer agreement from being reached. - */ - case neg_invalid: - res = reject; - break; - - /* We were not negotiating a wide data transfer, - * but the device sent is a negotiation request. - * Honour the request by sending back a WDTR - * message containing our capability, limited by - * the targets capability. - */ - default: - fas216_cmd(info, CMD_SETATN); - if (msg[3] > info->ifcfg.wide_max_size) - msg[3] = info->ifcfg.wide_max_size; - - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 4, - EXTENDED_MESSAGE, 2, EXTENDED_WDTR, - msg[3]); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - res = wide; - break; - - /* We initiated the wide data transfer negotiation, - * and have successfully received a response from the - * target. The synchronous transfer agreement has been - * reached. Note: if the values returned are out of our - * bounds, we must reject the message. - */ - case neg_inprogress: - res = reject; - if (msg[3] <= info->ifcfg.wide_max_size) { - dev->wide_state = neg_complete; - res = wide; - } - break; - } - } -#else - res = reject; -#endif - - switch (res) { - case wide: - dev->wide_xfer = msg[3]; - break; - - case reject: - fas216_cmd(info, CMD_SETATN); - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - - case bit8: - dev->wide_xfer = 0; - break; - - case none: - break; - } -} - -/** * fas216_updateptrs - update data pointers after transfer suspended/paused * @info: interface's local pointer to update * @bytes_transferred: number of bytes transferred @@ -993,6 +878,8 @@ static void fas216_aborttransfer(FAS216_Info *info) fas216_cmd(info, CMD_FLUSHFIFO); } +static void fas216_kick(FAS216_Info *info); + /** * fas216_disconnected_intr - handle device disconnection * @info: interface from which device disconnected from @@ -1001,6 +888,8 @@ static void fas216_aborttransfer(FAS216_Info *info) */ static void fas216_disconnect_intr(FAS216_Info *info) { + unsigned long flags; + fas216_checkmagic(info); fas216_log(info, LOG_CONNECT, "disconnect phase=%02x", @@ -1008,8 +897,6 @@ static void fas216_disconnect_intr(FAS216_Info *info) msgqueue_flush(&info->scsi.msgs); - fas216_cmd(info, CMD_ENABLESEL); - switch (info->scsi.phase) { case PHASE_SELECTION: /* while selecting - no target */ case PHASE_SELSTEPS: @@ -1018,9 +905,12 @@ static void fas216_disconnect_intr(FAS216_Info *info) case PHASE_MSGIN_DISCONNECT: /* message in - disconnecting */ info->scsi.disconnectable = 1; - info->scsi.reconnected.tag = 0; info->scsi.phase = PHASE_IDLE; info->stats.disconnects += 1; + spin_lock_irqsave(&info->host_lock, flags); + if (info->scsi.phase == PHASE_IDLE) + fas216_kick(info); + spin_unlock_irqrestore(&info->host_lock, flags); break; case PHASE_DONE: /* at end of command - complete */ @@ -1053,122 +943,61 @@ static void fas216_disconnect_intr(FAS216_Info *info) static void fas216_reselected_intr(FAS216_Info *info) { - unsigned char target, identify_msg, ok; + unsigned int cfis, i; + unsigned char msg[4]; + unsigned char target, lun, tag; fas216_checkmagic(info); - if ((info->scsi.phase == PHASE_SELECTION || - info->scsi.phase == PHASE_SELSTEPS) && info->SCpnt) { - Scsi_Cmnd *SCpnt = info->SCpnt; + WARN_ON(info->scsi.phase == PHASE_SELECTION || + info->scsi.phase == PHASE_SELSTEPS); - info->origSCpnt = SCpnt; - info->SCpnt = NULL; + cfis = fas216_readb(info, REG_CFIS); - if (info->device[SCpnt->device->id].wide_state == neg_inprogress) - info->device[SCpnt->device->id].wide_state = neg_wait; - if (info->device[SCpnt->device->id].sync_state == neg_inprogress) - info->device[SCpnt->device->id].sync_state = neg_wait; - } + fas216_log(info, LOG_CONNECT, "reconnect phase=%02x cfis=%02x", + info->scsi.phase, cfis); - fas216_log(info, LOG_CONNECT, "reconnect phase=%02X", info->scsi.phase); + cfis &= CFIS_CF; - if ((fas216_readb(info, REG_CFIS) & CFIS_CF) != 2) { + if (cfis < 2 || cfis > 4) { printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n", info->host->host_no); - goto initiator_error; - } - - target = fas216_readb(info, REG_FF); - identify_msg = fas216_readb(info, REG_FF); - - ok = 1; - if (!(target & (1 << info->host->this_id))) { - printk(KERN_ERR "scsi%d.H: invalid host id on reselect\n", info->host->host_no); - ok = 0; + goto bad_message; } - if (!(identify_msg & 0x80)) { - printk(KERN_ERR "scsi%d.H: no IDENTIFY message on reselect, got msg %02X\n", - info->host->host_no, identify_msg); - ok = 0; - } + for (i = 0; i < cfis; i++) + msg[i] = fas216_readb(info, REG_FF); - if (!ok) { - /* - * Something went wrong - send an initiator error to - * the target. - */ + if (!(msg[0] & (1 << info->host->this_id)) || + !(msg[1] & 0x80)) goto initiator_error; - } - target &= ~(1 << info->host->this_id); + target = msg[0] & ~(1 << info->host->this_id); target = ffs(target) - 1; + lun = msg[1] & 7; + tag = 0; - identify_msg &= 7; - info->scsi.reconnected.target = target; - info->scsi.reconnected.lun = identify_msg; - info->scsi.reconnected.tag = 0; + if (cfis >= 3) { + if (msg[2] != SIMPLE_QUEUE_TAG) + goto initiator_error; - /* set up for synchronous transfers */ - fas216_set_sync(info, target); - - ok = 0; - if (info->scsi.disconnectable && info->SCpnt && - info->SCpnt->device->id == target && info->SCpnt->device->lun == identify_msg) - ok = 1; - - if (!ok && queue_probetgtlun(&info->queues.disconnected, target, identify_msg)) - ok = 1; - - msgqueue_flush(&info->scsi.msgs); - if (ok) { - info->scsi.phase = PHASE_RECONNECTED; - fas216_writeb(info, REG_SDID, target); - } else { - /* - * Our command structure not found - abort the - * command on the target. Since we have no - * record of this command, we can't send - * an INITIATOR DETECTED ERROR message. - */ - fas216_cmd(info, CMD_SETATN); - msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT_EXPECT; + tag = msg[3]; } - fas216_cmd(info, CMD_MSGACCEPTED); - return; - - initiator_error: - fas216_cmd(info, CMD_SETATN); + /* set up for synchronous transfers */ + fas216_writeb(info, REG_SDID, target); + fas216_set_sync(info, target); msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - fas216_cmd(info, CMD_MSGACCEPTED); -} - -/** - * fas216_finish_reconnect - finish reconnection sequence for device - * @info: interface which caused function done interrupt - * - * Finish reconnection sequence for device - */ -static void -fas216_finish_reconnect(FAS216_Info *info) -{ - fas216_checkmagic(info); - fas216_log(info, LOG_CONNECT, "Connected: %1x %1x %02x, reconnected: %1x %1x %02x", - info->SCpnt->device->id, info->SCpnt->device->lun, info->SCpnt->tag, - info->scsi.reconnected.target, info->scsi.reconnected.lun, - info->scsi.reconnected.tag); + fas216_log(info, LOG_CONNECT, "Reconnected: target %1x lun %1x tag %02x", + target, lun, tag); if (info->scsi.disconnectable && info->SCpnt) { info->scsi.disconnectable = 0; - if (info->SCpnt->device->id == info->scsi.reconnected.target && - info->SCpnt->device->lun == info->scsi.reconnected.lun && - info->SCpnt->tag == info->scsi.reconnected.tag) { - fas216_log(info, LOG_CONNECT, "reconnected"); + if (info->SCpnt->device->id == target && + info->SCpnt->device->lun == lun && + info->SCpnt->tag == tag) { + fas216_log(info, LOG_CONNECT, "reconnected previously executing command"); } else { queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); fas216_log(info, LOG_CONNECT, "had to move command to disconnected queue"); @@ -1177,32 +1006,53 @@ fas216_finish_reconnect(FAS216_Info *info) } if (!info->SCpnt) { info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected, - info->scsi.reconnected.target, - info->scsi.reconnected.lun, - info->scsi.reconnected.tag); + target, lun, tag); fas216_log(info, LOG_CONNECT, "had to get command"); } - if (!info->SCpnt) { + + if (info->SCpnt) { + /* + * Restore data pointer from SAVED data pointer + */ + info->scsi.SCp = info->SCpnt->SCp; + + fas216_log(info, LOG_CONNECT, "data pointers: [%p, %X]", + info->scsi.SCp.ptr, info->scsi.SCp.this_residual); + info->scsi.phase = PHASE_MSGIN; + } else { + /* + * Our command structure not found - abort the + * command on the target. Since we have no + * record of this command, we can't send + * an INITIATOR DETECTED ERROR message. + */ fas216_cmd(info, CMD_SETATN); - msgqueue_flush(&info->scsi.msgs); #if 0 - if (info->scsi.reconnected.tag) - msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, info->scsi.reconnected.tag); + if (tag) + msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, tag); else #endif msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT_EXPECT; info->scsi.aborting = 1; - } else { - /* - * Restore data pointer from SAVED data pointer - */ - info->scsi.SCp = info->SCpnt->SCp; - fas216_log(info, LOG_CONNECT, "data pointers: [%p, %X]", - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); } + + fas216_cmd(info, CMD_MSGACCEPTED); + return; + + initiator_error: + printk(KERN_ERR "scsi%d.H: error during reselection: bytes", + info->host->host_no); + for (i = 0; i < cfis; i++) + printk(" %02x", msg[i]); + printk("\n"); + bad_message: + fas216_cmd(info, CMD_SETATN); + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + fas216_cmd(info, CMD_MSGACCEPTED); } static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int msglen) @@ -1267,10 +1117,6 @@ static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int fas216_handlesync(info, message); break; - case EXTENDED_MESSAGE | EXTENDED_WDTR << 8: - fas216_handlewide(info, message); - break; - default: fas216_log(info, 0, "reject, last message 0x%04x", fas216_get_last_msg(info, info->scsi.msgin_fifo)); @@ -1280,14 +1126,6 @@ static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int case NOP: break; - case SIMPLE_QUEUE_TAG: - if (msglen < 2) - goto unrecognised; - - /* handled above - print a warning since this is untested */ - fas216_log(info, 0, "reconnect queue tag 0x%02x", message[1]); - break; - case EXTENDED_MESSAGE: if (msglen < 3) goto unrecognised; @@ -1297,10 +1135,6 @@ static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int fas216_handlesync(info, message); break; - case EXTENDED_WDTR: /* Wide transfer negotiation request/reply */ - fas216_handlewide(info, message); - break; - default: goto unrecognised; } @@ -1437,13 +1271,6 @@ static void fas216_message(FAS216_Info *info) } #endif - if (info->scsi.phase == PHASE_RECONNECTED) { - if (message[0] == SIMPLE_QUEUE_TAG) - info->scsi.reconnected.tag = message[1]; - fas216_finish_reconnect(info); - info->scsi.phase = PHASE_MSGIN; - } - fas216_parse_message(info, message, msglen); fas216_cmd(info, CMD_MSGACCEPTED); return; @@ -1521,26 +1348,26 @@ static void fas216_send_messageout(FAS216_Info *info, int start) * fas216_busservice_intr - handle bus service interrupt from FAS216 chip * @info: interface which caused bus service interrupt * @stat: Status register contents - * @ssr: SCSI Status register contents + * @is: SCSI Status register contents * * Handle a bus service interrupt from FAS216 chip */ -static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) +static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int is) { fas216_checkmagic(info); fas216_log(info, LOG_BUSSERVICE, - "bus service: stat=%02x ssr=%02x phase=%02x", - stat, ssr, info->scsi.phase); + "bus service: stat=%02x is=%02x phase=%02x", + stat, is, info->scsi.phase); switch (info->scsi.phase) { case PHASE_SELECTION: - if ((ssr & IS_BITS) != IS_MSGBYTESENT) + if ((is & IS_BITS) != IS_MSGBYTESENT) goto bad_is; break; case PHASE_SELSTEPS: - switch (ssr & IS_BITS) { + switch (is & IS_BITS) { case IS_SELARB: case IS_MSGBYTESENT: goto bad_is; @@ -1566,9 +1393,6 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne * as described by the SCSI II spec. */ switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) { - /* Reselmsgin -> Data In */ - case STATE(STAT_DATAIN, PHASE_RECONNECTED): - fas216_finish_reconnect(info); case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In */ case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */ case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> Data In */ @@ -1583,9 +1407,6 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne fas216_transfer(info); return; - /* Reselmsgin -> Data Out */ - case STATE(STAT_DATAOUT, PHASE_RECONNECTED): - fas216_finish_reconnect(info); case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out */ case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */ case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> Data Out */ @@ -1595,10 +1416,6 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne fas216_transfer(info); return; - /* Reselmsgin -> Status */ - case STATE(STAT_STATUS, PHASE_RECONNECTED): - fas216_finish_reconnect(info); - goto status; case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */ case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */ fas216_stoptransfer(info); @@ -1606,7 +1423,6 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */ case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */ case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */ - status: fas216_cmd(info, CMD_INITCMDCOMPLETE); info->scsi.phase = PHASE_STATUS; return; @@ -1623,16 +1439,11 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne info->scsi.phase = PHASE_MSGIN; return; - /* Reselmsgin -> Message In */ - case STATE(STAT_MESGIN, PHASE_RECONNECTED): case STATE(STAT_MESGIN, PHASE_MSGIN): info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF; fas216_cmd(info, CMD_TRANSFERINFO); return; - /* Reselmsgin -> Command */ - case STATE(STAT_COMMAND, PHASE_RECONNECTED): - fas216_finish_reconnect(info); case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out -> Command */ case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */ fas216_send_command(info); @@ -1722,7 +1533,7 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne return; bad_is: - fas216_log(info, 0, "bus service at step %d?", ssr & IS_BITS); + fas216_log(info, 0, "bus service at step %d?", is & IS_BITS); fas216_dumpstate(info); print_debug_list(); @@ -1733,37 +1544,40 @@ bad_is: * fas216_funcdone_intr - handle a function done interrupt from FAS216 chip * @info: interface which caused function done interrupt * @stat: Status register contents - * @ssr: SCSI Status register contents + * @is: SCSI Status register contents * * Handle a function done interrupt from FAS216 chip */ -static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) +static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int is) { unsigned int fifo_len = fas216_readb(info, REG_CFIS) & CFIS_CF; - unsigned int status, message; fas216_checkmagic(info); fas216_log(info, LOG_FUNCTIONDONE, - "function done: stat=%02x ssr=%02x phase=%02x", - stat, ssr, info->scsi.phase); + "function done: stat=%02x is=%02x phase=%02x", + stat, is, info->scsi.phase); switch (info->scsi.phase) { case PHASE_STATUS: /* status phase - read status and msg */ if (fifo_len != 2) { fas216_log(info, 0, "odd number of bytes in FIFO: %d", fifo_len); } - status = fas216_readb(info, REG_FF); - message = fas216_readb(info, REG_FF); - info->scsi.SCp.Message = message; - info->scsi.SCp.Status = status; + /* + * Read status then message byte. + */ + info->scsi.SCp.Status = fas216_readb(info, REG_FF); + info->scsi.SCp.Message = fas216_readb(info, REG_FF); info->scsi.phase = PHASE_DONE; fas216_cmd(info, CMD_MSGACCEPTED); break; - case PHASE_IDLE: /* reselected? */ + case PHASE_IDLE: + case PHASE_SELECTION: + case PHASE_SELSTEPS: + break; + case PHASE_MSGIN: /* message in phase */ - case PHASE_RECONNECTED: /* reconnected command */ if ((stat & STAT_BUSMASK) == STAT_MESGIN) { info->scsi.msgin_fifo = fifo_len; fas216_message(info); @@ -1779,22 +1593,13 @@ static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned static void fas216_bus_reset(FAS216_Info *info) { - neg_t sync_state, wide_state; + neg_t sync_state; int i; msgqueue_flush(&info->scsi.msgs); - info->scsi.reconnected.target = 0; - info->scsi.reconnected.lun = 0; - info->scsi.reconnected.tag = 0; - - wide_state = neg_invalid; sync_state = neg_invalid; -#ifdef SCSI2_WIDE - if (info->ifcfg.wide_max_size != 0) - wide_state = neg_wait; -#endif #ifdef SCSI2_SYNC if (info->ifcfg.capabilities & (FASCAP_DMA|FASCAP_PSEUDODMA)) sync_state = neg_wait; @@ -1807,7 +1612,6 @@ static void fas216_bus_reset(FAS216_Info *info) for (i = 0; i < 8; i++) { info->device[i].disconnect_ok = info->ifcfg.disconnect_ok; info->device[i].sync_state = sync_state; - info->device[i].wide_state = wide_state; info->device[i].period = info->ifcfg.asyncperiod / 4; info->device[i].stp = info->scsi.async_stp; info->device[i].sof = 0; @@ -1826,38 +1630,38 @@ static void fas216_bus_reset(FAS216_Info *info) */ irqreturn_t fas216_intr(FAS216_Info *info) { - unsigned char isr, ssr, stat; + unsigned char inst, is, stat; int handled = IRQ_NONE; fas216_checkmagic(info); stat = fas216_readb(info, REG_STAT); - ssr = fas216_readb(info, REG_IS); - isr = fas216_readb(info, REG_INST); + is = fas216_readb(info, REG_IS); + inst = fas216_readb(info, REG_INST); - add_debug_list(stat, ssr, isr, info->scsi.phase); + add_debug_list(stat, is, inst, info->scsi.phase); if (stat & STAT_INT) { - if (isr & INST_BUSRESET) { + if (inst & INST_BUSRESET) { fas216_log(info, 0, "bus reset detected"); fas216_bus_reset(info); scsi_report_bus_reset(info->host, 0); - } else if (isr & INST_ILLEGALCMD) { + } else if (inst & INST_ILLEGALCMD) { fas216_log(info, LOG_ERROR, "illegal command given\n"); fas216_dumpstate(info); print_debug_list(); - } else if (isr & INST_DISCONNECT) + } else if (inst & INST_DISCONNECT) fas216_disconnect_intr(info); - else if (isr & INST_RESELECTED) /* reselected */ + else if (inst & INST_RESELECTED) /* reselected */ fas216_reselected_intr(info); - else if (isr & INST_BUSSERVICE) /* bus service request */ - fas216_busservice_intr(info, stat, ssr); - else if (isr & INST_FUNCDONE) /* function done */ - fas216_funcdone_intr(info, stat, ssr); + else if (inst & INST_BUSSERVICE) /* bus service request */ + fas216_busservice_intr(info, stat, is); + else if (inst & INST_FUNCDONE) /* function done */ + fas216_funcdone_intr(info, stat, is); else fas216_log(info, 0, "unknown interrupt received:" - " phase %s isr %02X ssr %02X stat %02X", - fas216_drv_phase(info), isr, ssr, stat); + " phase %s inst %02X is %02X stat %02X", + fas216_drv_phase(info), inst, is, stat); handled = IRQ_HANDLED; } return handled; @@ -1948,7 +1752,7 @@ static int parity_test(FAS216_Info *info, int target) { #if 0 if (target == 3) { - info->device[3].parity_check = 0; + info->device[target].parity_check = 0; return 1; } #endif @@ -1991,15 +1795,6 @@ static void fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag); do { -#ifdef SCSI2_WIDE - if (info->device[SCpnt->device->id].wide_state == neg_wait) { - info->device[SCpnt->device->id].wide_state = neg_inprogress; - msgqueue_addmsg(&info->scsi.msgs, 4, - EXTENDED_MESSAGE, 2, EXTENDED_WDTR, - info->ifcfg.wide_max_size); - break; - } -#endif #ifdef SCSI2_SYNC if ((info->device[SCpnt->device->id].sync_state == neg_wait || info->device[SCpnt->device->id].sync_state == neg_complete) && @@ -2140,8 +1935,18 @@ static void fas216_kick(FAS216_Info *info) } } while (0); - if (!SCpnt) /* no command pending - just exit */ + if (!SCpnt) { + /* + * no command pending, so enable reselection. + */ + fas216_cmd(info, CMD_ENABLESEL); return; + } + + /* + * We're going to start a command, so disable reselection + */ + fas216_cmd(info, CMD_DISABLESEL); if (info->scsi.disconnectable && info->SCpnt) { fas216_log(info, LOG_CONNECT, @@ -2804,6 +2609,8 @@ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) clear_bit(SDpnt->id * 8 + i, info->busyluns); } + info->scsi.phase = PHASE_IDLE; + /* * Reset the SCSI bus. Device cleanup happens in * the interrupt handler. @@ -2833,7 +2640,8 @@ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) */ static void fas216_init_chip(FAS216_Info *info) { - fas216_writeb(info, REG_CLKF, fas216_clockrate(info->ifcfg.clockrate)); + unsigned int clock = ((info->ifcfg.clockrate - 1) / 5 + 1) & 7; + fas216_writeb(info, REG_CLKF, clock); fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); fas216_writeb(info, REG_CNTL2, info->scsi.cfg[1]); fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]); @@ -3042,7 +2850,7 @@ int fas216_init(struct Scsi_Host *host) info->scsi.cfg[0] = host->this_id | CNTL1_PERE; info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE; info->scsi.cfg[2] = info->ifcfg.cntl3 | - CNTL3_ADIDCHK | CNTL3_G2CB | CNTL3_LBTM; + CNTL3_ADIDCHK | CNTL3_QTAG | CNTL3_G2CB | CNTL3_LBTM; info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod); info->rst_dev_status = -1; @@ -3082,6 +2890,12 @@ int fas216_add(struct Scsi_Host *host, struct device *dev) FAS216_Info *info = (FAS216_Info *)host->hostdata; int type, ret; + if (info->ifcfg.clockrate <= 10 || info->ifcfg.clockrate > 40) { + printk(KERN_CRIT "fas216: invalid clock rate %u MHz\n", + info->ifcfg.clockrate); + return -EINVAL; + } + fas216_reset_state(info); type = fas216_detect_type(info); info->scsi.type = chip_types[type]; @@ -3181,32 +2995,32 @@ int fas216_print_stats(FAS216_Info *info, char *buffer) return p - buffer; } -int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer) +int fas216_print_devices(FAS216_Info *info, char *buffer) { - struct fas216_device *dev = &info->device[scd->id]; - int len = 0; - char *p; - - proc_print_scsidevice(scd, buffer, &len, 0); - p = buffer + len; - - p += sprintf(p, " Extensions: "); + struct fas216_device *dev; + Scsi_Device *scd; + char *p = buffer; - if (scd->tagged_supported) - p += sprintf(p, "TAG %sabled [%d] ", - scd->tagged_queue ? "en" : "dis", - scd->current_tag); + p += sprintf(p, "Device/Lun TaggedQ Parity Sync\n"); - p += sprintf(p, "%s\n", dev->parity_enabled ? "parity" : ""); + list_for_each_entry(scd, &info->host->my_devices, siblings) { + dev = &info->device[scd->id]; + p += sprintf(p, " %d/%d ", scd->id, scd->lun); + if (scd->tagged_supported) + p += sprintf(p, "%3sabled(%3d) ", + scd->tagged_queue ? "en" : "dis", + scd->current_tag); + else + p += sprintf(p, "unsupported "); - p += sprintf(p, " Transfers : %d-bit ", - 8 << dev->wide_xfer); + p += sprintf(p, "%3sabled ", dev->parity_enabled ? "en" : "dis"); - if (dev->sof) - p += sprintf(p, "sync offset %d, %d ns\n", - dev->sof, dev->period * 4); - else - p += sprintf(p, "async\n"); + if (dev->sof) + p += sprintf(p, "offset %d, %d ns\n", + dev->sof, dev->period * 4); + else + p += sprintf(p, "async\n"); + } return p - buffer; } @@ -3224,7 +3038,7 @@ EXPORT_SYMBOL(fas216_eh_bus_reset); EXPORT_SYMBOL(fas216_eh_host_reset); EXPORT_SYMBOL(fas216_print_host); EXPORT_SYMBOL(fas216_print_stats); -EXPORT_SYMBOL(fas216_print_device); +EXPORT_SYMBOL(fas216_print_devices); MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver core"); diff --git a/drivers/acorn/scsi/fas216.h b/drivers/scsi/arm/fas216.h index e1ba80b30281..d6b6322f9d53 100644 --- a/drivers/acorn/scsi/fas216.h +++ b/drivers/scsi/arm/fas216.h @@ -177,7 +177,6 @@ typedef enum { PHASE_SELSTEPS, /* selection with command steps */ PHASE_COMMAND, /* command sent */ PHASE_MESSAGESENT, /* selected, and we're sending cmd */ - PHASE_RECONNECTED, /* reconnected */ PHASE_DATAOUT, /* data out to device */ PHASE_DATAIN, /* data in from device */ PHASE_MSGIN, /* message in from device */ @@ -244,12 +243,6 @@ typedef struct { const char *type; /* chip type */ unsigned int irq; /* interrupt */ - struct { - unsigned char target; /* reconnected target */ - unsigned char lun; /* reconnected lun */ - unsigned char tag; /* reconnected tag */ - } reconnected; - Scsi_Pointer SCp; /* current commands data pointer */ MsgQueue_t msgs; /* message queue for connected device */ @@ -368,7 +361,7 @@ extern void fas216_release (struct Scsi_Host *instance); extern int fas216_print_host(FAS216_Info *info, char *buffer); extern int fas216_print_stats(FAS216_Info *info, char *buffer); -extern int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer); +extern int fas216_print_devices(FAS216_Info *info, char *buffer); /* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt) * Purpose : abort this command diff --git a/drivers/acorn/scsi/msgqueue.c b/drivers/scsi/arm/msgqueue.c index 7c95c7582b29..7c95c7582b29 100644 --- a/drivers/acorn/scsi/msgqueue.c +++ b/drivers/scsi/arm/msgqueue.c diff --git a/drivers/acorn/scsi/msgqueue.h b/drivers/scsi/arm/msgqueue.h index 41c7333df3e3..41c7333df3e3 100644 --- a/drivers/acorn/scsi/msgqueue.h +++ b/drivers/scsi/arm/msgqueue.h diff --git a/drivers/acorn/scsi/oak.c b/drivers/scsi/arm/oak.c index 6afc155ea856..f99eab756b74 100644 --- a/drivers/acorn/scsi/oak.c +++ b/drivers/scsi/arm/oak.c @@ -16,8 +16,8 @@ #include <asm/io.h> #include <asm/system.h> -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" +#include "../scsi.h" +#include "../hosts.h" #define AUTOSENSE /*#define PSEUDO_DMA*/ @@ -40,7 +40,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, #define BOARD_NORMAL 0 #define BOARD_NCR53C400 1 -#include "../../scsi/NCR5380.h" +#include "../NCR5380.h" #undef START_DMA_INITIATOR_RECEIVE_REG #define START_DMA_INITIATOR_RECEIVE_REG (7 + 128) @@ -112,7 +112,7 @@ printk("reading %p len %d\n", addr, len); #undef STAT -#include "../../scsi/NCR5380.c" +#include "../NCR5380.c" static Scsi_Host_Template oakscsi_template = { .module = THIS_MODULE, diff --git a/drivers/acorn/scsi/powertec.c b/drivers/scsi/arm/powertec.c index c591d3460642..79fca5999b01 100644 --- a/drivers/acorn/scsi/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -25,8 +25,8 @@ #include <asm/irq.h> #include <asm/pgtable.h> -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" +#include "../scsi.h" +#include "../hosts.h" #include "fas216.h" #include "scsi.h" @@ -242,10 +242,10 @@ powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) int powertecscsi_proc_info(char *buffer, char **start, off_t offset, int length, int host_no, int inout) { - int pos, begin; struct Scsi_Host *host; struct powertec_info *info; - Scsi_Device *scd; + char *p = buffer; + int pos; host = scsi_host_hn_get(host_no); if (!host) @@ -256,29 +256,16 @@ int powertecscsi_proc_info(char *buffer, char **start, off_t offset, info = (struct powertec_info *)host->hostdata; - begin = 0; - pos = sprintf(buffer, "PowerTec SCSI driver v%s\n", VERSION); - pos += fas216_print_host(&info->info, buffer + pos); - pos += sprintf(buffer + pos, "Term : o%s\n", + p += sprintf(p, "PowerTec SCSI driver v%s\n", VERSION); + p += fas216_print_host(&info->info, p); + p += sprintf(p, "Term : o%s\n", info->term_ctl ? "n" : "ff"); - pos += fas216_print_stats(&info->info, buffer + pos); + p += fas216_print_stats(&info->info, p); + p += fas216_print_devices(&info->info, p); - pos += sprintf(buffer+pos, "\nAttached devices:\n"); - - list_for_each_entry(scd, &host->my_devices, siblings) { - pos += fas216_print_device(&info->info, scd, buffer + pos); - - if (pos + begin < offset) { - begin += pos; - pos = 0; - } - if (pos + begin > offset + length) - break; - } - - *start = buffer + (offset - begin); - pos -= offset - begin; + *start = buffer + offset; + pos = p - buffer - offset; if (pos > length) pos = length; diff --git a/drivers/acorn/scsi/queue.c b/drivers/scsi/arm/queue.c index eae5a8d180df..fec52a7ae746 100644 --- a/drivers/acorn/scsi/queue.c +++ b/drivers/scsi/arm/queue.c @@ -23,7 +23,7 @@ #include <linux/list.h> #include <linux/init.h> -#include "../../scsi/scsi.h" +#include "../scsi.h" #define DEBUG diff --git a/drivers/acorn/scsi/queue.h b/drivers/scsi/arm/queue.h index 0c9dec4c1716..0c9dec4c1716 100644 --- a/drivers/acorn/scsi/queue.h +++ b/drivers/scsi/arm/queue.h diff --git a/drivers/acorn/scsi/scsi.h b/drivers/scsi/arm/scsi.h index 3b82817d88f4..3b82817d88f4 100644 --- a/drivers/acorn/scsi/scsi.h +++ b/drivers/scsi/arm/scsi.h diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 993a69d81ad5..827a1977ef91 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -146,7 +146,7 @@ cyber2000_seqw(unsigned int reg, unsigned int val, struct cfb_info *cfb) * Hardware Cyber2000 Acceleration */ static void -cyber2000fb_fillrect(struct fb_info *info, struct fb_fillrect *rect) +cyber2000fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct cfb_info *cfb = (struct cfb_info *)info; unsigned long dst, col; @@ -178,7 +178,7 @@ cyber2000fb_fillrect(struct fb_info *info, struct fb_fillrect *rect) } static void -cyber2000fb_copyarea(struct fb_info *info, struct fb_copyarea *region) +cyber2000fb_copyarea(struct fb_info *info, const struct fb_copyarea *region) { struct cfb_info *cfb = (struct cfb_info *)info; unsigned int cmd = CO_CMD_L_PATTERN_FGCOL; @@ -189,24 +189,25 @@ cyber2000fb_copyarea(struct fb_info *info, struct fb_copyarea *region) return; } + cyber2000fb_writeb(0, CO_REG_CONTROL, cfb); + cyber2000fb_writew(region->width - 1, CO_REG_PIXWIDTH, cfb); + cyber2000fb_writew(region->height - 1, CO_REG_PIXHEIGHT, cfb); + + src = region->sx + region->sy * cfb->fb.var.xres_virtual; + dst = region->dx + region->dy * cfb->fb.var.xres_virtual; + if (region->sx < region->dx) { - region->sx += region->width - 1; - region->dx += region->width - 1; + src += region->width - 1; + dst += region->width - 1; cmd |= CO_CMD_L_INC_LEFT; } if (region->sy < region->dy) { - region->sy += region->height - 1; - region->dy += region->height - 1; + src += (region->height - 1) * cfb->fb.var.xres_virtual; + dst += (region->height - 1) * cfb->fb.var.xres_virtual; cmd |= CO_CMD_L_INC_UP; } - cyber2000fb_writeb(0, CO_REG_CONTROL, cfb); - cyber2000fb_writew(region->width - 1, CO_REG_PIXWIDTH, cfb); - cyber2000fb_writew(region->height - 1, CO_REG_PIXHEIGHT, cfb); - - src = region->sx + region->sy * cfb->fb.var.xres_virtual; - dst = region->dx + region->dy * cfb->fb.var.xres_virtual; if (cfb->fb.var.bits_per_pixel == 24) { cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb); src *= 3; @@ -221,9 +222,9 @@ cyber2000fb_copyarea(struct fb_info *info, struct fb_copyarea *region) } static void -cyber2000fb_imageblit(struct fb_info *info, struct fb_image *image) +cyber2000fb_imageblit(struct fb_info *info, const struct fb_image *image) { - struct cfb_info *cfb = (struct cfb_info *)info; +// struct cfb_info *cfb = (struct cfb_info *)info; // if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT)) { cfb_imageblit(info, image); @@ -754,7 +755,6 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) var->blue.msb_right = 0; switch (var->bits_per_pixel) { -#ifdef FBCON_HAS_CFB8 case 8: /* PSEUDOCOLOUR, 256 */ var->transp.offset = 0; var->transp.length = 0; @@ -765,8 +765,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) var->blue.offset = 0; var->blue.length = 8; break; -#endif -#ifdef FBCON_HAS_CFB16 + case 16:/* DIRECTCOLOUR, 64k or 32k */ switch (var->green.length) { case 6: /* RGB565, 64k */ @@ -804,8 +803,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) break; } break; -#endif -#ifdef FBCON_HAS_CFB24 + case 24:/* TRUECOLOUR, 16m */ var->transp.offset = 0; var->transp.length = 0; @@ -816,8 +814,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) var->blue.offset = 0; var->blue.length = 8; break; -#endif -#ifdef FBCON_HAS_CFB32 + case 32:/* TRUECOLOUR, 16m */ var->transp.offset = 24; var->transp.length = 8; @@ -828,7 +825,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) var->blue.offset = 0; var->blue.length = 8; break; -#endif + default: return -EINVAL; } @@ -1601,15 +1598,17 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) /* * Use MCLK from BIOS. FIXME: what about hotplug? */ -#ifndef __arm__ cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb); cfb->mclk_div = cyber2000_grphr(EXT_MCLK_DIV, cfb); -#else + +#ifdef __arm__ /* * MCLK on the NetWinder and the Shark is fixed at 75MHz */ - cfb->mclk_mult = 0xdb; - cfb->mclk_div = 0x54; + if (machine_is_netwinder()) { + cfb->mclk_mult = 0xdb; + cfb->mclk_div = 0x54; + } #endif err = cyberpro_common_probe(cfb); |
