Commit f77fb2ba authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.5-rmk

into home.transmeta.com:/home/torvalds/v2.5/linux
parents e7778aa6 25a49b8e
...@@ -57,7 +57,7 @@ static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma) ...@@ -57,7 +57,7 @@ static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma)
if (end > PAGE_SIZE) if (end > PAGE_SIZE)
end = PAGE_SIZE; end = PAGE_SIZE;
if (offset + (int) TRANSFER_SIZE > end) if (offset + TRANSFER_SIZE >= end)
flags |= DMA_END_L; flags |= DMA_END_L;
sg->length = end - TRANSFER_SIZE; sg->length = end - TRANSFER_SIZE;
...@@ -95,27 +95,31 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) ...@@ -95,27 +95,31 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
if (!(status & DMA_ST_INT)) if (!(status & DMA_ST_INT))
return IRQ_HANDLED; return IRQ_HANDLED;
if (status & DMA_ST_OFL && !dma->sg) if ((dma->state ^ status) & DMA_ST_AB)
break; iomd_get_next_sg(&dma->cur_sg, dma);
iomd_get_next_sg(&dma->cur_sg, dma);
switch (status & (DMA_ST_OFL | DMA_ST_AB)) { switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
case DMA_ST_OFL: /* OIA */ case DMA_ST_OFL: /* OIA */
case DMA_ST_AB: /* .IB */ case DMA_ST_AB: /* .IB */
iomd_writel(dma->cur_sg.dma_address, base + CURA); iomd_writel(dma->cur_sg.dma_address, base + CURA);
iomd_writel(dma->cur_sg.length, base + ENDA); iomd_writel(dma->cur_sg.length, base + ENDA);
dma->state = DMA_ST_AB;
break; break;
case DMA_ST_OFL | DMA_ST_AB: /* OIB */ case DMA_ST_OFL | DMA_ST_AB: /* OIB */
case 0: /* .IA */ case 0: /* .IA */
iomd_writel(dma->cur_sg.dma_address, base + CURB); iomd_writel(dma->cur_sg.dma_address, base + CURB);
iomd_writel(dma->cur_sg.length, base + ENDB); iomd_writel(dma->cur_sg.length, base + ENDB);
dma->state = 0;
break; break;
} }
if (status & DMA_ST_OFL &&
dma->cur_sg.length == (DMA_END_S|DMA_END_L))
break;
} while (1); } while (1);
iomd_writeb(0, dma->dma_base + CR); dma->state = ~DMA_ST_AB;
disable_irq(irq); disable_irq(irq);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -152,6 +156,7 @@ static void iomd_enable_dma(dmach_t channel, dma_t *dma) ...@@ -152,6 +156,7 @@ static void iomd_enable_dma(dmach_t channel, dma_t *dma)
} }
iomd_writeb(DMA_CR_C, dma_base + CR); iomd_writeb(DMA_CR_C, dma_base + CR);
dma->state = DMA_ST_AB;
} }
if (dma->dma_mode == DMA_MODE_READ) if (dma->dma_mode == DMA_MODE_READ)
...@@ -165,13 +170,11 @@ static void iomd_disable_dma(dmach_t channel, dma_t *dma) ...@@ -165,13 +170,11 @@ static void iomd_disable_dma(dmach_t channel, dma_t *dma)
{ {
unsigned long dma_base = dma->dma_base; unsigned long dma_base = dma->dma_base;
unsigned long flags; unsigned long flags;
unsigned int ctrl;
local_irq_save(flags); local_irq_save(flags);
ctrl = iomd_readb(dma_base + CR); if (dma->state != ~DMA_ST_AB)
if (ctrl & DMA_CR_E)
disable_irq(dma->dma_irq); disable_irq(dma->dma_irq);
iomd_writeb(ctrl & ~DMA_CR_E, dma_base + CR); iomd_writeb(0, dma_base + CR);
local_irq_restore(flags); local_irq_restore(flags);
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include <linux/fs.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -306,7 +307,7 @@ static struct i2c_adapter ioc_ops = { ...@@ -306,7 +307,7 @@ static struct i2c_adapter ioc_ops = {
.id = I2C_HW_B_IOC, .id = I2C_HW_B_IOC,
.algo_data = &ioc_data, .algo_data = &ioc_data,
.client_register = ioc_client_reg, .client_register = ioc_client_reg,
.client_unregister = ioc_client_unreg .client_unregister = ioc_client_unreg,
.dev = { .dev = {
.name = "IOC/IOMD", .name = "IOC/IOMD",
}, },
......
...@@ -34,7 +34,7 @@ static struct i2c_client_address_data addr_data = { ...@@ -34,7 +34,7 @@ static struct i2c_client_address_data addr_data = {
.force = ignore, .force = ignore,
}; };
#define DAT(x) ((unsigned int)(x->data)) #define DAT(x) ((unsigned int)(x->dev.driver_data))
static int static int
pcf8583_attach(struct i2c_adapter *adap, int addr, unsigned short flags, 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, ...@@ -51,13 +51,13 @@ pcf8583_attach(struct i2c_adapter *adap, int addr, unsigned short flags,
if (!c) if (!c)
return -ENOMEM; return -ENOMEM;
strcpy(c->name, "PCF8583"); strcpy(c->dev.name, "PCF8583");
c->id = pcf8583_driver.id; c->id = pcf8583_driver.id;
c->flags = 0; c->flags = 0;
c->addr = addr; c->addr = addr;
c->adapter = adap; c->adapter = adap;
c->driver = &pcf8583_driver; c->driver = &pcf8583_driver;
c->data = NULL; c->dev.driver_data = NULL;
if (i2c_transfer(c->adapter, msgs, 2) == 2) if (i2c_transfer(c->adapter, msgs, 2) == 2)
DAT(c) = buf[0]; DAT(c) = buf[0];
......
...@@ -25,7 +25,7 @@ struct button_callback { ...@@ -25,7 +25,7 @@ struct button_callback {
/* Function prototypes: */ /* Function prototypes: */
static void button_sequence_finished (unsigned long parameters); 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, static int button_read (struct file *filp, char *buffer,
size_t count, loff_t *ppos); size_t count, loff_t *ppos);
int button_init (void); int button_init (void);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/pci.h> #include <linux/dma-mapping.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -27,12 +27,7 @@ ...@@ -27,12 +27,7 @@
#include <asm/ecard.h> #include <asm/ecard.h>
#include <asm/io.h> #include <asm/io.h>
/* #define ICS_IDENT_OFFSET 0x2280
* Maximum number of interfaces per card
*/
#define MAX_IFS 2
#define ICS_IDENT_OFFSET 0x8a0
#define ICS_ARCIN_V5_INTRSTAT 0x000 #define ICS_ARCIN_V5_INTRSTAT 0x000
#define ICS_ARCIN_V5_INTROFFSET 0x001 #define ICS_ARCIN_V5_INTROFFSET 0x001
...@@ -77,14 +72,19 @@ static struct cardinfo icside_cardinfo_v6_2 = { ...@@ -77,14 +72,19 @@ static struct cardinfo icside_cardinfo_v6_2 = {
struct icside_state { struct icside_state {
unsigned int channel; unsigned int channel;
unsigned int enabled; 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 { #define ICS_TYPE_A3IN 0
ics_if_unknown, #define ICS_TYPE_A3USER 1
ics_if_arcin_v5, #define ICS_TYPE_V6 3
ics_if_arcin_v6 #define ICS_TYPE_V5 15
} iftype_t; #define ICS_TYPE_NOTYPE ((unsigned int)-1)
/* ---------------- Version 5 PCB Support Functions --------------------- */ /* ---------------- Version 5 PCB Support Functions --------------------- */
/* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) /* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
...@@ -92,8 +92,10 @@ typedef enum { ...@@ -92,8 +92,10 @@ typedef enum {
*/ */
static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
{ {
unsigned int memc_port = (unsigned int)ec->irq_data; struct icside_state *state = ec->irq_data;
outb(0, memc_port + ICS_ARCIN_V5_INTROFFSET); unsigned int base = state->irq_port;
outb(0, base + ICS_ARCIN_V5_INTROFFSET);
} }
/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) /* 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) ...@@ -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) static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
{ {
unsigned int memc_port = (unsigned int)ec->irq_data; struct icside_state *state = ec->irq_data;
inb(memc_port + ICS_ARCIN_V5_INTROFFSET); unsigned int base = state->irq_port;
inb(base + ICS_ARCIN_V5_INTROFFSET);
} }
static const expansioncard_ops_t icside_ops_arcin_v5 = { static const expansioncard_ops_t icside_ops_arcin_v5 = {
icside_irqenable_arcin_v5, .irqenable = icside_irqenable_arcin_v5,
icside_irqdisable_arcin_v5, .irqdisable = icside_irqdisable_arcin_v5,
NULL,
NULL,
NULL,
NULL
}; };
...@@ -163,65 +163,11 @@ static int icside_irqpending_arcin_v6(struct expansion_card *ec) ...@@ -163,65 +163,11 @@ static int icside_irqpending_arcin_v6(struct expansion_card *ec)
} }
static const expansioncard_ops_t icside_ops_arcin_v6 = { static const expansioncard_ops_t icside_ops_arcin_v6 = {
icside_irqenable_arcin_v6, .irqenable = icside_irqenable_arcin_v6,
icside_irqdisable_arcin_v6, .irqdisable = icside_irqdisable_arcin_v6,
icside_irqpending_arcin_v6, .irqpending = icside_irqpending_arcin_v6,
NULL,
NULL,
NULL
}; };
/* 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 * Handle routing of interrupts. This is called before
* we write the command to the drive. * we write the command to the drive.
...@@ -229,7 +175,7 @@ static iftype_t __init icside_identifyif (struct expansion_card *ec) ...@@ -229,7 +175,7 @@ static iftype_t __init icside_identifyif (struct expansion_card *ec)
static void icside_maskproc(ide_drive_t *drive, int mask) static void icside_maskproc(ide_drive_t *drive, int mask)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct icside_state *state = hwif->hw.priv; struct icside_state *state = hwif->hwif_data;
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
...@@ -271,6 +217,7 @@ static void icside_maskproc(ide_drive_t *drive, int mask) ...@@ -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) static void ide_build_sglist(ide_drive_t *drive, struct request *rq)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
struct icside_state *state = hwif->hwif_data;
struct scatterlist *sg = hwif->sg_table; struct scatterlist *sg = hwif->sg_table;
int nents; int nents;
...@@ -280,9 +227,9 @@ static void ide_build_sglist(ide_drive_t *drive, struct request *rq) ...@@ -280,9 +227,9 @@ static void ide_build_sglist(ide_drive_t *drive, struct request *rq)
ide_task_t *args = rq->special; ide_task_t *args = rq->special;
if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
hwif->sg_dma_direction = PCI_DMA_TODEVICE; hwif->sg_dma_direction = DMA_TO_DEVICE;
else else
hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; hwif->sg_dma_direction = DMA_FROM_DEVICE;
memset(sg, 0, sizeof(*sg)); memset(sg, 0, sizeof(*sg));
sg->page = virt_to_page(rq->buffer); sg->page = virt_to_page(rq->buffer);
...@@ -293,12 +240,12 @@ static void ide_build_sglist(ide_drive_t *drive, struct request *rq) ...@@ -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); nents = blk_rq_map_sg(&drive->queue, rq, sg);
if (rq_data_dir(rq) == READ) if (rq_data_dir(rq) == READ)
hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; hwif->sg_dma_direction = DMA_FROM_DEVICE;
else 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; hwif->sg_nents = nents;
} }
...@@ -484,7 +431,7 @@ static int icside_dma_check(ide_drive_t *drive) ...@@ -484,7 +431,7 @@ static int icside_dma_check(ide_drive_t *drive)
int xfer_mode = XFER_PIO_2; int xfer_mode = XFER_PIO_2;
int on; int on;
if (!id || !(id->capability & 1) || !hwif->autodma) if (!(id->capability & 1) || !hwif->autodma)
goto out; goto out;
/* /*
...@@ -500,13 +447,7 @@ static int icside_dma_check(ide_drive_t *drive) ...@@ -500,13 +447,7 @@ static int icside_dma_check(ide_drive_t *drive)
* Enable DMA on any drive that has multiword DMA * Enable DMA on any drive that has multiword DMA
*/ */
if (id->field_valid & 2) { if (id->field_valid & 2) {
if (id->dma_mword & 4) { xfer_mode = ide_dma_speed(drive, 0);
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;
}
goto out; goto out;
} }
...@@ -531,13 +472,14 @@ static int icside_dma_check(ide_drive_t *drive) ...@@ -531,13 +472,14 @@ static int icside_dma_check(ide_drive_t *drive)
static int icside_dma_end(ide_drive_t *drive) static int icside_dma_end(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct icside_state *state = hwif->hwif_data;
drive->waiting_for_dma = 0; drive->waiting_for_dma = 0;
disable_dma(hwif->hw.dma); disable_dma(hwif->hw.dma);
/* Teardown mappings after DMA has completed. */ /* 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_direction);
hwif->sg_dma_active = 0; hwif->sg_dma_active = 0;
...@@ -713,7 +655,7 @@ int icside_dma_write(ide_drive_t *drive) ...@@ -713,7 +655,7 @@ int icside_dma_write(ide_drive_t *drive)
static int icside_dma_test_irq(ide_drive_t *drive) static int icside_dma_test_irq(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = HWIF(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 + return inb(state->irq_port +
(hwif->channel ? (hwif->channel ?
...@@ -748,7 +690,7 @@ static int icside_dma_lostirq(ide_drive_t *drive) ...@@ -748,7 +690,7 @@ static int icside_dma_lostirq(ide_drive_t *drive)
return 1; return 1;
} }
static int icside_setup_dma(ide_hwif_t *hwif) static int icside_dma_init(ide_hwif_t *hwif)
{ {
int autodma = 0; int autodma = 0;
...@@ -763,6 +705,10 @@ static int icside_setup_dma(ide_hwif_t *hwif) ...@@ -763,6 +705,10 @@ static int icside_setup_dma(ide_hwif_t *hwif)
if (!hwif->sg_table) if (!hwif->sg_table)
goto failed; goto failed;
hwif->atapi_dma = 1;
hwif->mwdma_mask = 7; /* MW0..2 */
hwif->swdma_mask = 7; /* SW0..2 */
hwif->dmatable_cpu = NULL; hwif->dmatable_cpu = NULL;
hwif->dmatable_dma = 0; hwif->dmatable_dma = 0;
hwif->speedproc = icside_set_speed; hwif->speedproc = icside_set_speed;
...@@ -784,10 +730,10 @@ static int icside_setup_dma(ide_hwif_t *hwif) ...@@ -784,10 +730,10 @@ static int icside_setup_dma(ide_hwif_t *hwif)
hwif->ide_dma_timeout = icside_dma_timeout; hwif->ide_dma_timeout = icside_dma_timeout;
hwif->ide_dma_lostirq = icside_dma_lostirq; hwif->ide_dma_lostirq = icside_dma_lostirq;
hwif->drives[0].autodma = autodma; hwif->drives[0].autodma = hwif->autodma;
hwif->drives[1].autodma = autodma; hwif->drives[1].autodma = hwif->autodma;
printk(" capable%s\n", autodma ? ", auto-enable" : ""); printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");
return 1; return 1;
...@@ -796,14 +742,16 @@ static int icside_setup_dma(ide_hwif_t *hwif) ...@@ -796,14 +742,16 @@ static int icside_setup_dma(ide_hwif_t *hwif)
return 0; return 0;
} }
int ide_release_dma(ide_hwif_t *hwif) static void icside_dma_exit(ide_hwif_t *hwif)
{ {
if (hwif->sg_table) { if (hwif->sg_table) {
kfree(hwif->sg_table); kfree(hwif->sg_table);
hwif->sg_table = NULL; hwif->sg_table = NULL;
} }
return 1;
} }
#else
#define icside_dma_init(hwif) (0)
#define icside_dma_exit(hwif) do { } while (0)
#endif #endif
static ide_hwif_t *icside_find_hwif(unsigned long dataport) static ide_hwif_t *icside_find_hwif(unsigned long dataport)
...@@ -829,7 +777,7 @@ static ide_hwif_t *icside_find_hwif(unsigned long dataport) ...@@ -829,7 +777,7 @@ static ide_hwif_t *icside_find_hwif(unsigned long dataport)
} }
static ide_hwif_t * 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; unsigned long port = base + info->dataoffset;
ide_hwif_t *hwif; ide_hwif_t *hwif;
...@@ -847,42 +795,47 @@ icside_setup(unsigned long base, struct cardinfo *info, int irq) ...@@ -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->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
hwif->hw.irq = irq; hwif->hw.irq = ec->irq;
hwif->irq = irq; hwif->irq = ec->irq;
hwif->hw.dma = NO_DMA;
hwif->noprobe = 0; hwif->noprobe = 0;
hwif->chipset = ide_acorn; hwif->chipset = ide_acorn;
hwif->gendev.parent = &ec->dev;
} }
return hwif; 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; unsigned long slot_port;
ide_hwif_t *hwif; ide_hwif_t *hwif;
slot_port = ecard_address(ec, ECARD_MEMC, 0); 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->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT);
ec->irqmask = 1; ec->irqmask = 1;
ec->irq_data = (void *)slot_port; ec->irq_data = state;
ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5; ec->ops = &icside_ops_arcin_v5;
/* /*
* Be on the safe side - disable interrupts * Be on the safe side - disable interrupts
*/ */
inb(slot_port + ICS_ARCIN_V5_INTROFFSET); 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; 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; unsigned long slot_port, port;
struct icside_state *state;
ide_hwif_t *hwif, *mate; ide_hwif_t *hwif, *mate;
unsigned int sel = 0; unsigned int sel = 0;
...@@ -905,89 +858,173 @@ static int __init icside_register_v6(struct expansion_card *ec) ...@@ -905,89 +858,173 @@ static int __init icside_register_v6(struct expansion_card *ec)
/* /*
* Find and register the interfaces. * Find and register the interfaces.
*/ */
hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq); hwif = icside_setup(port, &icside_cardinfo_v6_1, ec);
mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq); mate = icside_setup(port, &icside_cardinfo_v6_2, ec);
if (!hwif || !mate) if (!hwif || !mate)
return -ENODEV; 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->irq_port = port;
state->slot_port = slot_port;
state->hwif[0] = hwif;
state->hwif[1] = mate;
ec->irq_data = state; ec->irq_data = state;
ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; ec->ops = &icside_ops_arcin_v6;
hwif->maskproc = icside_maskproc; hwif->maskproc = icside_maskproc;
hwif->channel = 0; hwif->channel = 0;
hwif->hw.priv = state; hwif->hwif_data = state;
hwif->mate = mate; hwif->mate = mate;
hwif->serialized = 1; hwif->serialized = 1;
hwif->config_data = slot_port; hwif->config_data = slot_port;
hwif->select_data = sel; hwif->select_data = sel;
hwif->hw.dma = ec->dma; hwif->hw.dma = ec->dma;
mate->maskproc = icside_maskproc; mate->maskproc = icside_maskproc;
mate->channel = 1; mate->channel = 1;
mate->hw.priv = state; mate->hwif_data = state;
mate->mate = hwif; mate->mate = hwif;
mate->serialized = 1; mate->serialized = 1;
mate->config_data = slot_port; mate->config_data = slot_port;
mate->select_data = sel | 1; 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)) { if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
icside_setup_dma(hwif); icside_dma_init(hwif);
icside_setup_dma(mate); icside_dma_init(mate);
} }
#endif
return 0; return 0;
} }
static int __devinit static int __devinit
icside_probe(struct expansion_card *ec, const struct ecard_id *id) 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)) { state->type = type;
case ics_if_arcin_v5: }
result = icside_register_v5(ec);
switch (state->type) {
case ICS_TYPE_A3IN:
printk(KERN_WARNING "icside: A3IN unsupported\n");
ret = -ENODEV;
break; break;
case ics_if_arcin_v6: case ICS_TYPE_A3USER:
result = icside_register_v6(ec); 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; break;
default: default:
result = -ENODEV; printk(KERN_WARNING "icside: unknown interface type\n");
ret = -ENODEV;
break; break;
} }
if (result) if (ret == 0) {
ecard_release(ec); ecard_set_drvdata(ec, state);
/*
* this locks the driver in-core - remove this /*
* comment and the two lines below when we can * this locks the driver in-core - remove this
* safely remove interfaces. * comment and the line below when we can
*/ * safely remove interfaces.
else */
MOD_INC_USE_COUNT; 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 static void icside_shutdown(struct expansion_card *ec)
icside_remove(struct expansion_card *ec)
{ {
/* need to do more */ struct icside_state *state = ecard_get_drvdata(ec);
ecard_release(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[] = { static const struct ecard_id icside_ids[] = {
...@@ -999,6 +1036,7 @@ static const struct ecard_id icside_ids[] = { ...@@ -999,6 +1036,7 @@ static const struct ecard_id icside_ids[] = {
static struct ecard_driver icside_driver = { static struct ecard_driver icside_driver = {
.probe = icside_probe, .probe = icside_probe,
.remove = __devexit_p(icside_remove), .remove = __devexit_p(icside_remove),
.shutdown = icside_shutdown,
.id_table = icside_ids, .id_table = icside_ids,
.drv = { .drv = {
.name = "icside", .name = "icside",
......
...@@ -20,8 +20,6 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) ...@@ -20,8 +20,6 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
hw_regs_t hw; hw_regs_t hw;
int i, ret; int i, ret;
ecard_claim(ec);
memset(&hw, 0, sizeof(hw)); memset(&hw, 0, sizeof(hw));
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { 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) ...@@ -49,7 +47,6 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
static void __devexit rapide_remove(struct expansion_card *ec) static void __devexit rapide_remove(struct expansion_card *ec)
{ {
/* need to do more */ /* need to do more */
ecard_release(ec);
} }
static struct ecard_id rapide_ids[] = { static struct ecard_id rapide_ids[] = {
......
...@@ -347,7 +347,6 @@ static struct sa1111_driver ps2_driver = { ...@@ -347,7 +347,6 @@ static struct sa1111_driver ps2_driver = {
.drv = { .drv = {
.name = "sa1111-ps2", .name = "sa1111-ps2",
.bus = &sa1111_bus_type, .bus = &sa1111_bus_type,
.devclass = &input_devclass,
.probe = ps2_probe, .probe = ps2_probe,
.remove = ps2_remove, .remove = ps2_remove,
.suspend = ps2_suspend, .suspend = ps2_suspend,
......
...@@ -221,14 +221,7 @@ config MII ...@@ -221,14 +221,7 @@ config MII
or internal device. It is safe to say Y or M here even if your or internal device. It is safe to say Y or M here even if your
ethernet card lack MII. ethernet card lack MII.
config ARM_AM79C961A source "drivers/net/arm/Kconfig"
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"
config MACE config MACE
tristate "MACE (Power Mac ethernet) support" tristate "MACE (Power Mac ethernet) support"
......
...@@ -77,7 +77,6 @@ obj-$(CONFIG_HP100) += hp100.o ...@@ -77,7 +77,6 @@ obj-$(CONFIG_HP100) += hp100.o
obj-$(CONFIG_SMC9194) += smc9194.o obj-$(CONFIG_SMC9194) += smc9194.o
obj-$(CONFIG_FEC) += fec.o obj-$(CONFIG_FEC) += fec.o
obj-$(CONFIG_68360_ENET) += 68360enet.o obj-$(CONFIG_68360_ENET) += 68360enet.o
obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
obj-$(CONFIG_ARM_ETHERH) += 8390.o obj-$(CONFIG_ARM_ETHERH) += 8390.o
obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_WD80x3) += wd.o 8390.o
obj-$(CONFIG_EL2) += 3c503.o 8390.o obj-$(CONFIG_EL2) += 3c503.o 8390.o
...@@ -179,7 +178,7 @@ obj-$(CONFIG_AMD8111_ETH) += amd8111e.o ...@@ -179,7 +178,7 @@ obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
# non-drivers/net drivers who want mii lib # non-drivers/net drivers who want mii lib
obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o
obj-$(CONFIG_ARCH_ACORN) += ../acorn/net/ obj-$(CONFIG_ARM) += arm/
obj-$(CONFIG_NET_FC) += fc/ obj-$(CONFIG_NET_FC) += fc/
obj-$(CONFIG_DEV_APPLETALK) += appletalk/ obj-$(CONFIG_DEV_APPLETALK) += appletalk/
obj-$(CONFIG_TR) += tokenring/ obj-$(CONFIG_TR) += tokenring/
......
...@@ -2,6 +2,13 @@ ...@@ -2,6 +2,13 @@
# Acorn Network device configuration # Acorn Network device configuration
# These are for Acorn's Expansion card network interfaces # 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 config ARM_ETHER1
tristate "Acorn Ether1 support" tristate "Acorn Ether1 support"
depends on NET_ETHERNET && ARM && ARCH_ACORN depends on NET_ETHERNET && ARM && ARCH_ACORN
...@@ -23,3 +30,16 @@ config ARM_ETHERH ...@@ -23,3 +30,16 @@ config ARM_ETHERH
If you have an Acorn system with one of these network cards, you 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. 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.
# File: drivers/acorn/net/Makefile # File: drivers/net/arm/Makefile
# #
# Makefile for the Acorn ethercard network device drivers # 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_ETHERH) += etherh.o
obj-$(CONFIG_ARM_ETHER3) += ether3.o obj-$(CONFIG_ARM_ETHER3) += ether3.o
obj-$(CONFIG_ARM_ETHER1) += ether1.o obj-$(CONFIG_ARM_ETHER1) += ether1.o
/*
* 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&ETHER_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))&ETHER_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(&ether00_pldhs_ops);
}
module_init(ether00_mod_init);
...@@ -450,6 +450,7 @@ ether1_init_for_open (struct net_device *dev) ...@@ -450,6 +450,7 @@ ether1_init_for_open (struct net_device *dev)
struct ether1_priv *priv = (struct ether1_priv *)dev->priv; struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
int i, status, addr, next, next2; int i, status, addr, next, next2;
int failures = 0; int failures = 0;
unsigned long timeout;
outb (CTRL_RST|CTRL_ACK, REG_CONTROL); outb (CTRL_RST|CTRL_ACK, REG_CONTROL);
...@@ -515,19 +516,19 @@ ether1_init_for_open (struct net_device *dev) ...@@ -515,19 +516,19 @@ ether1_init_for_open (struct net_device *dev)
outb (CTRL_CA, REG_CONTROL); outb (CTRL_CA, REG_CONTROL);
/* 586 should now unset iscp.busy */ /* 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) { 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); printk (KERN_WARNING "%s: can't initialise 82586: iscp is busy\n", dev->name);
return 1; return 1;
} }
} }
/* check status of commands that we issued */ /* 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)) while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) { & STAT_COMPLETE) == 0) {
if (time_after(jiffies, i)) if (time_after(jiffies, timeout))
break; break;
} }
...@@ -541,10 +542,10 @@ ether1_init_for_open (struct net_device *dev) ...@@ -541,10 +542,10 @@ ether1_init_for_open (struct net_device *dev)
failures += 1; failures += 1;
} }
i += HZ/10; timeout += HZ/10;
while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS)) while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) { & STAT_COMPLETE) == 0) {
if (time_after(jiffies, i)) if (time_after(jiffies, timeout))
break; break;
} }
...@@ -558,10 +559,10 @@ ether1_init_for_open (struct net_device *dev) ...@@ -558,10 +559,10 @@ ether1_init_for_open (struct net_device *dev)
failures += 1; failures += 1;
} }
i += HZ/10; timeout += HZ/10;
while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS)) while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) { & STAT_COMPLETE) == 0) {
if (time_after(jiffies, i)) if (time_after(jiffies, timeout))
break; break;
} }
...@@ -575,10 +576,10 @@ ether1_init_for_open (struct net_device *dev) ...@@ -575,10 +576,10 @@ ether1_init_for_open (struct net_device *dev)
failures += 1; failures += 1;
} }
i += HZ; timeout += HZ;
while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS)) while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) { & STAT_COMPLETE) == 0) {
if (time_after(jiffies, i)) if (time_after(jiffies, timeout))
break; break;
} }
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include "../../net/8390.h" #include "../8390.h"
#define NET_DEBUG 0 #define NET_DEBUG 0
#define DEBUG_INIT 2 #define DEBUG_INIT 2
......
...@@ -636,13 +636,14 @@ static void sa1100_irda_fir_irq(struct net_device *dev) ...@@ -636,13 +636,14 @@ static void sa1100_irda_fir_irq(struct net_device *dev)
sa1100_irda_rx_dma_start(si); 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; struct net_device *dev = dev_id;
if (IS_FIR(((struct sa1100_irda *)dev->priv))) if (IS_FIR(((struct sa1100_irda *)dev->priv)))
sa1100_irda_fir_irq(dev); sa1100_irda_fir_irq(dev);
else else
sa1100_irda_hpsir_irq(dev); sa1100_irda_hpsir_irq(dev);
return IRQ_HANDLED;
} }
/* /*
......
...@@ -1602,7 +1602,7 @@ config SCSI_MAC53C94 ...@@ -1602,7 +1602,7 @@ config SCSI_MAC53C94
whenever you want). If you want to compile it as a module, say M whenever you want). If you want to compile it as a module, say M
here and read <file:Documentation/modules.txt>. here and read <file:Documentation/modules.txt>.
source "drivers/acorn/scsi/Kconfig" source "drivers/scsi/arm/Kconfig"
config JAZZ_ESP config JAZZ_ESP
bool "MIPS JAZZ FAS216 SCSI support" bool "MIPS JAZZ FAS216 SCSI support"
......
...@@ -114,7 +114,7 @@ obj-$(CONFIG_SCSI_CPQFCTS) += cpqfc.o ...@@ -114,7 +114,7 @@ obj-$(CONFIG_SCSI_CPQFCTS) += cpqfc.o
obj-$(CONFIG_SCSI_LASI700) += lasi700.o 53c700.o obj-$(CONFIG_SCSI_LASI700) += lasi700.o 53c700.o
obj-$(CONFIG_SCSI_NSP32) += nsp32.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_ST) += st.o
obj-$(CONFIG_CHR_DEV_OSST) += osst.o obj-$(CONFIG_CHR_DEV_OSST) += osst.o
......
# #
# Makefile for drivers/acorn/scsi # Makefile for drivers/scsi/arm
# #
acornscsi_mod-objs := acornscsi.o acornscsi-io.o acornscsi_mod-objs := acornscsi.o acornscsi-io.o
......
...@@ -149,8 +149,8 @@ ...@@ -149,8 +149,8 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/ecard.h> #include <asm/ecard.h>
#include "../../scsi/scsi.h" #include "../scsi.h"
#include "../../scsi/hosts.h" #include "../hosts.h"
#include "acornscsi.h" #include "acornscsi.h"
#include "msgqueue.h" #include "msgqueue.h"
#include "scsi.h" #include "scsi.h"
...@@ -2931,6 +2931,35 @@ int acornscsi_proc_info(char *buffer, char **start, off_t offset, ...@@ -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; pos = p - buffer;
*start = buffer + (offset - begin); *start = buffer + (offset - begin);
......
...@@ -298,7 +298,6 @@ typedef struct acornscsi_hostdata { ...@@ -298,7 +298,6 @@ typedef struct acornscsi_hostdata {
unsigned short last_message; /* last message to be sent */ unsigned short last_message; /* last message to be sent */
unsigned char disconnectable:1; /* this command can be disconnected */ unsigned char disconnectable:1; /* this command can be disconnected */
unsigned char interrupt:1; /* interrupt active */
} scsi; } scsi;
/* statistics information */ /* statistics information */
......
...@@ -29,14 +29,15 @@ ...@@ -29,14 +29,15 @@
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/ecard.h> #include <asm/ecard.h>
#include "../../scsi/scsi.h" #include "../scsi.h"
#include "../../scsi/hosts.h" #include "../hosts.h"
#include "fas216.h" #include "fas216.h"
struct arxescsi_info { struct arxescsi_info {
...@@ -238,10 +239,10 @@ static int ...@@ -238,10 +239,10 @@ static int
arxescsi_proc_info(char *buffer, char **start, off_t offset, int length, arxescsi_proc_info(char *buffer, char **start, off_t offset, int length,
int host_no, int inout) int host_no, int inout)
{ {
int pos, begin;
struct Scsi_Host *host; struct Scsi_Host *host;
struct arxescsi_info *info; struct arxescsi_info *info;
Scsi_Device *scd; char *p = buffer;
int pos;
host = scsi_host_hn_get(host_no); host = scsi_host_hn_get(host_no);
if (!host) if (!host)
...@@ -251,26 +252,13 @@ arxescsi_proc_info(char *buffer, char **start, off_t offset, int length, ...@@ -251,26 +252,13 @@ arxescsi_proc_info(char *buffer, char **start, off_t offset, int length,
if (inout == 1) if (inout == 1)
return -EINVAL; return -EINVAL;
begin = 0; p += sprintf(p, "ARXE 16-bit SCSI driver v%s\n", VERSION);
pos = sprintf(buffer, "ARXE 16-bit SCSI driver v%s\n", VERSION); p += fas216_print_host(&info->info, p);
pos += fas216_print_host(&info->info, buffer + pos); p += fas216_print_stats(&info->info, p);
pos += fas216_print_stats(&info->info, buffer + pos); p += fas216_print_devices(&info->info, p);
pos += sprintf (buffer+pos, "\nAttached devices:\n"); *start = buffer + offset;
pos = p - buffer - offset;
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;
if (pos > length) if (pos > length)
pos = length; pos = length;
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/system.h> #include <asm/system.h>
#include "../../scsi/scsi.h" #include "../scsi.h"
#include "../../scsi/hosts.h" #include "../hosts.h"
#include <scsi/scsicam.h> #include <scsi/scsicam.h>
...@@ -41,7 +41,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, ...@@ -41,7 +41,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset,
#define BOARD_NORMAL 0 #define BOARD_NORMAL 0
#define BOARD_NCR53C400 1 #define BOARD_NCR53C400 1
#include "../../scsi/NCR5380.h" #include "../NCR5380.h"
void cumanascsi_setup(char *str, int *ints) void cumanascsi_setup(char *str, int *ints)
{ {
...@@ -239,7 +239,7 @@ static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value) ...@@ -239,7 +239,7 @@ static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value)
#undef CTRL #undef CTRL
#include "../../scsi/NCR5380.c" #include "../NCR5380.c"
static Scsi_Host_Template cumanascsi_template = { static Scsi_Host_Template cumanascsi_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
......
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include "../../scsi/scsi.h" #include "../scsi.h"
#include "../../scsi/hosts.h" #include "../hosts.h"
#include "fas216.h" #include "fas216.h"
#include "scsi.h" #include "scsi.h"
...@@ -356,10 +356,10 @@ cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length) ...@@ -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 cumanascsi_2_proc_info (char *buffer, char **start, off_t offset,
int length, int host_no, int inout) int length, int host_no, int inout)
{ {
int pos, begin;
struct Scsi_Host *host; struct Scsi_Host *host;
struct cumanascsi2_info *info; struct cumanascsi2_info *info;
Scsi_Device *scd; char *p = buffer;
int pos;
host = scsi_host_hn_get(host_no); host = scsi_host_hn_get(host_no);
if (!host) if (!host)
...@@ -370,18 +370,16 @@ int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, ...@@ -370,18 +370,16 @@ int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset,
info = (struct cumanascsi2_info *)host->hostdata; info = (struct cumanascsi2_info *)host->hostdata;
begin = 0; p += sprintf(p, "Cumana SCSI II driver v%s\n", VERSION);
pos = sprintf(buffer, "Cumana SCSI II driver v%s\n", VERSION); p += fas216_print_host(&info->info, p);
pos += fas216_print_host(&info->info, buffer + pos); p += sprintf(p, "Term : o%s\n",
pos += sprintf(buffer + pos, "Term : o%s\n",
info->terms ? "n" : "ff"); 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;
pos = p - buffer - offset;
*start = buffer + (offset - begin);
pos -= offset - begin;
if (pos > length) if (pos > length)
pos = length; pos = length;
......
...@@ -52,8 +52,8 @@ ...@@ -52,8 +52,8 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include "../../scsi/scsi.h" #include "../scsi.h"
#include "../../scsi/hosts.h" #include "../hosts.h"
#define NCR5380_implementation_fields int port, ctrl #define NCR5380_implementation_fields int port, ctrl
#define NCR5380_local_declare() struct Scsi_Host *_instance #define NCR5380_local_declare() struct Scsi_Host *_instance
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
#define NCR5380_queue_command ecoscsi_queue_command #define NCR5380_queue_command ecoscsi_queue_command
#define NCR5380_proc_info ecoscsi_proc_info #define NCR5380_proc_info ecoscsi_proc_info
#include "../../scsi/NCR5380.h" #include "../NCR5380.h"
#define ECOSCSI_PUBLIC_RELEASE 1 #define ECOSCSI_PUBLIC_RELEASE 1
...@@ -239,7 +239,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, ...@@ -239,7 +239,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset,
#define BOARD_NORMAL 0 #define BOARD_NORMAL 0
#define BOARD_NCR53C400 1 #define BOARD_NCR53C400 1
#include "../../scsi/NCR5380.c" #include "../NCR5380.c"
static Scsi_Host_Template ecoscsi_template = { static Scsi_Host_Template ecoscsi_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
......
...@@ -40,8 +40,8 @@ ...@@ -40,8 +40,8 @@
#include <asm/ecard.h> #include <asm/ecard.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include "../../scsi/scsi.h" #include "../scsi.h"
#include "../../scsi/hosts.h" #include "../hosts.h"
#include "fas216.h" #include "fas216.h"
#include "scsi.h" #include "scsi.h"
...@@ -430,10 +430,10 @@ eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) ...@@ -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 eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
int length, int host_no, int inout) int length, int host_no, int inout)
{ {
int pos, begin;
struct Scsi_Host *host; struct Scsi_Host *host;
struct eesoxscsi_info *info; struct eesoxscsi_info *info;
Scsi_Device *scd; char *p = buffer;
int pos;
host = scsi_host_hn_get(host_no); host = scsi_host_hn_get(host_no);
if (!host) if (!host)
...@@ -444,16 +444,15 @@ int eesoxscsi_proc_info(char *buffer, char **start, off_t offset, ...@@ -444,16 +444,15 @@ int eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
info = (struct eesoxscsi_info *)host->hostdata; info = (struct eesoxscsi_info *)host->hostdata;
begin = 0; p += sprintf(p, "EESOX SCSI driver v%s\n", VERSION);
pos = sprintf(buffer, "EESOX SCSI driver v%s\n", VERSION); p += fas216_print_host(&info->info, p);
pos += fas216_print_host(&info->info, buffer + pos); p += sprintf(p, "Term : o%s\n",
pos += sprintf(buffer + pos, "Term : o%s\n",
info->control & EESOX_TERM_ENABLE ? "n" : "ff"); info->control & EESOX_TERM_ENABLE ? "n" : "ff");
pos += fas216_print_stats(&info->info, buffer + pos); 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) if (pos > length)
pos = length; pos = length;
......
...@@ -44,14 +44,15 @@ ...@@ -44,14 +44,15 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/ecard.h> #include <asm/ecard.h>
#include "../../scsi/scsi.h" #include "../scsi.h"
#include "../../scsi/hosts.h" #include "../hosts.h"
#include "fas216.h" #include "fas216.h"
#include "scsi.h" #include "scsi.h"
...@@ -79,7 +80,6 @@ ...@@ -79,7 +80,6 @@
* I was thinking that this was a good chip until I found this restriction ;( * I was thinking that this was a good chip until I found this restriction ;(
*/ */
#define SCSI2_SYNC #define SCSI2_SYNC
#undef SCSI2_WIDE
#undef SCSI2_TAG #undef SCSI2_TAG
#undef DEBUG_CONNECT #undef DEBUG_CONNECT
...@@ -96,6 +96,8 @@ ...@@ -96,6 +96,8 @@
static int level_mask = LOG_ERROR; static int level_mask = LOG_ERROR;
MODULE_PARM(level_mask, "i");
static int __init fas216_log_setup(char *str) static int __init fas216_log_setup(char *str)
{ {
char *s; char *s;
...@@ -199,10 +201,8 @@ static void fas216_dumpinfo(FAS216_Info *info) ...@@ -199,10 +201,8 @@ static void fas216_dumpinfo(FAS216_Info *info)
info->scsi.io_port, info->scsi.io_shift, info->scsi.irq, 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[0], info->scsi.cfg[1], info->scsi.cfg[2],
info->scsi.cfg[3]); info->scsi.cfg[3]);
printk(" type=%p phase=%X reconnected={ target=%d lun=%d tag=%d }\n", printk(" type=%p phase=%X\n",
info->scsi.type, info->scsi.phase, info->scsi.type, info->scsi.phase);
info->scsi.reconnected.target,
info->scsi.reconnected.lun, info->scsi.reconnected.tag);
print_SCp(&info->scsi.SCp, " SCp={ ", " }\n"); print_SCp(&info->scsi.SCp, " SCp={ ", " }\n");
printk(" msgs async_stp=%X disconnectable=%d aborting=%d }\n", printk(" msgs async_stp=%X disconnectable=%d aborting=%d }\n",
info->scsi.async_stp, info->scsi.async_stp,
...@@ -265,21 +265,24 @@ static const char *fas216_bus_phase(int stat) ...@@ -265,21 +265,24 @@ static const char *fas216_bus_phase(int stat)
static const char *fas216_drv_phase(FAS216_Info *info) static const char *fas216_drv_phase(FAS216_Info *info)
{ {
switch (info->scsi.phase) { static const char *phases[] = {
case PHASE_IDLE: return "idle"; [PHASE_IDLE] = "idle",
case PHASE_SELECTION: return "selection"; [PHASE_SELECTION] = "selection",
case PHASE_COMMAND: return "command"; [PHASE_COMMAND] = "command",
case PHASE_RECONNECTED: return "reconnected"; [PHASE_DATAOUT] = "data out",
case PHASE_DATAOUT: return "data out"; [PHASE_DATAIN] = "data in",
case PHASE_DATAIN: return "data in"; [PHASE_MSGIN] = "message in",
case PHASE_MSGIN: return "message in"; [PHASE_MSGIN_DISCONNECT]= "disconnect",
case PHASE_MSGIN_DISCONNECT: return "disconnect"; [PHASE_MSGOUT_EXPECT] = "expect message out",
case PHASE_MSGOUT_EXPECT: return "expect message out"; [PHASE_MSGOUT] = "message out",
case PHASE_MSGOUT: return "message out"; [PHASE_STATUS] = "status",
case PHASE_STATUS: return "status"; [PHASE_DONE] = "done",
case PHASE_DONE: return "done"; };
default: return "???";
} if (info->scsi.phase < ARRAY_SIZE(phases) &&
phases[info->scsi.phase])
return phases[info->scsi.phase];
return "???";
} }
static char fas216_target(FAS216_Info *info) static char fas216_target(FAS216_Info *info)
...@@ -406,25 +409,6 @@ static void print_debug_list(void) ...@@ -406,25 +409,6 @@ static void print_debug_list(void)
static void fas216_done(FAS216_Info *info, unsigned int result); 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 * fas216_get_last_msg - retrive last message from the list
* @info: interface to search * @info: interface to search
...@@ -640,105 +624,6 @@ static void fas216_handlesync(FAS216_Info *info, char *msg) ...@@ -640,105 +624,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 * fas216_updateptrs - update data pointers after transfer suspended/paused
* @info: interface's local pointer to update * @info: interface's local pointer to update
...@@ -993,6 +878,8 @@ static void fas216_aborttransfer(FAS216_Info *info) ...@@ -993,6 +878,8 @@ static void fas216_aborttransfer(FAS216_Info *info)
fas216_cmd(info, CMD_FLUSHFIFO); fas216_cmd(info, CMD_FLUSHFIFO);
} }
static void fas216_kick(FAS216_Info *info);
/** /**
* fas216_disconnected_intr - handle device disconnection * fas216_disconnected_intr - handle device disconnection
* @info: interface from which device disconnected from * @info: interface from which device disconnected from
...@@ -1001,6 +888,8 @@ static void fas216_aborttransfer(FAS216_Info *info) ...@@ -1001,6 +888,8 @@ static void fas216_aborttransfer(FAS216_Info *info)
*/ */
static void fas216_disconnect_intr(FAS216_Info *info) static void fas216_disconnect_intr(FAS216_Info *info)
{ {
unsigned long flags;
fas216_checkmagic(info); fas216_checkmagic(info);
fas216_log(info, LOG_CONNECT, "disconnect phase=%02x", fas216_log(info, LOG_CONNECT, "disconnect phase=%02x",
...@@ -1008,8 +897,6 @@ static void fas216_disconnect_intr(FAS216_Info *info) ...@@ -1008,8 +897,6 @@ static void fas216_disconnect_intr(FAS216_Info *info)
msgqueue_flush(&info->scsi.msgs); msgqueue_flush(&info->scsi.msgs);
fas216_cmd(info, CMD_ENABLESEL);
switch (info->scsi.phase) { switch (info->scsi.phase) {
case PHASE_SELECTION: /* while selecting - no target */ case PHASE_SELECTION: /* while selecting - no target */
case PHASE_SELSTEPS: case PHASE_SELSTEPS:
...@@ -1018,9 +905,12 @@ static void fas216_disconnect_intr(FAS216_Info *info) ...@@ -1018,9 +905,12 @@ static void fas216_disconnect_intr(FAS216_Info *info)
case PHASE_MSGIN_DISCONNECT: /* message in - disconnecting */ case PHASE_MSGIN_DISCONNECT: /* message in - disconnecting */
info->scsi.disconnectable = 1; info->scsi.disconnectable = 1;
info->scsi.reconnected.tag = 0;
info->scsi.phase = PHASE_IDLE; info->scsi.phase = PHASE_IDLE;
info->stats.disconnects += 1; 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; break;
case PHASE_DONE: /* at end of command - complete */ case PHASE_DONE: /* at end of command - complete */
...@@ -1053,122 +943,61 @@ static void fas216_disconnect_intr(FAS216_Info *info) ...@@ -1053,122 +943,61 @@ static void fas216_disconnect_intr(FAS216_Info *info)
static void static void
fas216_reselected_intr(FAS216_Info *info) 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); fas216_checkmagic(info);
if ((info->scsi.phase == PHASE_SELECTION || WARN_ON(info->scsi.phase == PHASE_SELECTION ||
info->scsi.phase == PHASE_SELSTEPS) && info->SCpnt) { info->scsi.phase == PHASE_SELSTEPS);
Scsi_Cmnd *SCpnt = info->SCpnt;
info->origSCpnt = SCpnt; cfis = fas216_readb(info, REG_CFIS);
info->SCpnt = NULL;
if (info->device[SCpnt->device->id].wide_state == neg_inprogress) fas216_log(info, LOG_CONNECT, "reconnect phase=%02x cfis=%02x",
info->device[SCpnt->device->id].wide_state = neg_wait; info->scsi.phase, cfis);
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", 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", printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n",
info->host->host_no); info->host->host_no);
goto initiator_error; goto bad_message;
}
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;
} }
if (!(identify_msg & 0x80)) { for (i = 0; i < cfis; i++)
printk(KERN_ERR "scsi%d.H: no IDENTIFY message on reselect, got msg %02X\n", msg[i] = fas216_readb(info, REG_FF);
info->host->host_no, identify_msg);
ok = 0;
}
if (!ok) { if (!(msg[0] & (1 << info->host->this_id)) ||
/* !(msg[1] & 0x80))
* Something went wrong - send an initiator error to
* the target.
*/
goto initiator_error; goto initiator_error;
}
target &= ~(1 << info->host->this_id); target = msg[0] & ~(1 << info->host->this_id);
target = ffs(target) - 1; target = ffs(target) - 1;
lun = msg[1] & 7;
tag = 0;
identify_msg &= 7; if (cfis >= 3) {
info->scsi.reconnected.target = target; if (msg[2] != SIMPLE_QUEUE_TAG)
info->scsi.reconnected.lun = identify_msg; goto initiator_error;
info->scsi.reconnected.tag = 0;
/* set up for synchronous transfers */ tag = msg[3];
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;
} }
fas216_cmd(info, CMD_MSGACCEPTED); /* set up for synchronous transfers */
return; fas216_writeb(info, REG_SDID, target);
fas216_set_sync(info, target);
initiator_error:
fas216_cmd(info, CMD_SETATN);
msgqueue_flush(&info->scsi.msgs); 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", fas216_log(info, LOG_CONNECT, "Reconnected: target %1x lun %1x tag %02x",
info->SCpnt->device->id, info->SCpnt->device->lun, info->SCpnt->tag, target, lun, tag);
info->scsi.reconnected.target, info->scsi.reconnected.lun,
info->scsi.reconnected.tag);
if (info->scsi.disconnectable && info->SCpnt) { if (info->scsi.disconnectable && info->SCpnt) {
info->scsi.disconnectable = 0; info->scsi.disconnectable = 0;
if (info->SCpnt->device->id == info->scsi.reconnected.target && if (info->SCpnt->device->id == target &&
info->SCpnt->device->lun == info->scsi.reconnected.lun && info->SCpnt->device->lun == lun &&
info->SCpnt->tag == info->scsi.reconnected.tag) { info->SCpnt->tag == tag) {
fas216_log(info, LOG_CONNECT, "reconnected"); fas216_log(info, LOG_CONNECT, "reconnected previously executing command");
} else { } else {
queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
fas216_log(info, LOG_CONNECT, "had to move command to disconnected queue"); fas216_log(info, LOG_CONNECT, "had to move command to disconnected queue");
...@@ -1177,32 +1006,53 @@ fas216_finish_reconnect(FAS216_Info *info) ...@@ -1177,32 +1006,53 @@ fas216_finish_reconnect(FAS216_Info *info)
} }
if (!info->SCpnt) { if (!info->SCpnt) {
info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected, info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected,
info->scsi.reconnected.target, target, lun, tag);
info->scsi.reconnected.lun,
info->scsi.reconnected.tag);
fas216_log(info, LOG_CONNECT, "had to get command"); 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); fas216_cmd(info, CMD_SETATN);
msgqueue_flush(&info->scsi.msgs);
#if 0 #if 0
if (info->scsi.reconnected.tag) if (tag)
msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, info->scsi.reconnected.tag); msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, tag);
else else
#endif #endif
msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
info->scsi.phase = PHASE_MSGOUT_EXPECT; info->scsi.phase = PHASE_MSGOUT_EXPECT;
info->scsi.aborting = 1; 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) 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 ...@@ -1267,10 +1117,6 @@ static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int
fas216_handlesync(info, message); fas216_handlesync(info, message);
break; break;
case EXTENDED_MESSAGE | EXTENDED_WDTR << 8:
fas216_handlewide(info, message);
break;
default: default:
fas216_log(info, 0, "reject, last message 0x%04x", fas216_log(info, 0, "reject, last message 0x%04x",
fas216_get_last_msg(info, info->scsi.msgin_fifo)); 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 ...@@ -1280,14 +1126,6 @@ static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int
case NOP: case NOP:
break; 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: case EXTENDED_MESSAGE:
if (msglen < 3) if (msglen < 3)
goto unrecognised; goto unrecognised;
...@@ -1297,10 +1135,6 @@ static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int ...@@ -1297,10 +1135,6 @@ static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int
fas216_handlesync(info, message); fas216_handlesync(info, message);
break; break;
case EXTENDED_WDTR: /* Wide transfer negotiation request/reply */
fas216_handlewide(info, message);
break;
default: default:
goto unrecognised; goto unrecognised;
} }
...@@ -1437,13 +1271,6 @@ static void fas216_message(FAS216_Info *info) ...@@ -1437,13 +1271,6 @@ static void fas216_message(FAS216_Info *info)
} }
#endif #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_parse_message(info, message, msglen);
fas216_cmd(info, CMD_MSGACCEPTED); fas216_cmd(info, CMD_MSGACCEPTED);
return; return;
...@@ -1521,26 +1348,26 @@ static void fas216_send_messageout(FAS216_Info *info, int start) ...@@ -1521,26 +1348,26 @@ static void fas216_send_messageout(FAS216_Info *info, int start)
* fas216_busservice_intr - handle bus service interrupt from FAS216 chip * fas216_busservice_intr - handle bus service interrupt from FAS216 chip
* @info: interface which caused bus service interrupt * @info: interface which caused bus service interrupt
* @stat: Status register contents * @stat: Status register contents
* @ssr: SCSI Status register contents * @is: SCSI Status register contents
* *
* Handle a bus service interrupt from FAS216 chip * 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_checkmagic(info);
fas216_log(info, LOG_BUSSERVICE, fas216_log(info, LOG_BUSSERVICE,
"bus service: stat=%02x ssr=%02x phase=%02x", "bus service: stat=%02x is=%02x phase=%02x",
stat, ssr, info->scsi.phase); stat, is, info->scsi.phase);
switch (info->scsi.phase) { switch (info->scsi.phase) {
case PHASE_SELECTION: case PHASE_SELECTION:
if ((ssr & IS_BITS) != IS_MSGBYTESENT) if ((is & IS_BITS) != IS_MSGBYTESENT)
goto bad_is; goto bad_is;
break; break;
case PHASE_SELSTEPS: case PHASE_SELSTEPS:
switch (ssr & IS_BITS) { switch (is & IS_BITS) {
case IS_SELARB: case IS_SELARB:
case IS_MSGBYTESENT: case IS_MSGBYTESENT:
goto bad_is; goto bad_is;
...@@ -1566,9 +1393,6 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne ...@@ -1566,9 +1393,6 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
* as described by the SCSI II spec. * as described by the SCSI II spec.
*/ */
switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) { 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_SELSTEPS):/* Sel w/ steps -> Data In */
case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */ case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */
case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> 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 ...@@ -1583,9 +1407,6 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
fas216_transfer(info); fas216_transfer(info);
return; 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_SELSTEPS):/* Sel w/ steps-> Data Out */
case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */ case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */
case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> 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 ...@@ -1595,10 +1416,6 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
fas216_transfer(info); fas216_transfer(info);
return; 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_DATAOUT): /* Data Out -> Status */
case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */ case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */
fas216_stoptransfer(info); fas216_stoptransfer(info);
...@@ -1606,7 +1423,6 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne ...@@ -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_MSGOUT): /* Message Out -> Status */
case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */ case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */
case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */ case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */
status:
fas216_cmd(info, CMD_INITCMDCOMPLETE); fas216_cmd(info, CMD_INITCMDCOMPLETE);
info->scsi.phase = PHASE_STATUS; info->scsi.phase = PHASE_STATUS;
return; return;
...@@ -1623,16 +1439,11 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne ...@@ -1623,16 +1439,11 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
info->scsi.phase = PHASE_MSGIN; info->scsi.phase = PHASE_MSGIN;
return; return;
/* Reselmsgin -> Message In */
case STATE(STAT_MESGIN, PHASE_RECONNECTED):
case STATE(STAT_MESGIN, PHASE_MSGIN): case STATE(STAT_MESGIN, PHASE_MSGIN):
info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF; info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF;
fas216_cmd(info, CMD_TRANSFERINFO); fas216_cmd(info, CMD_TRANSFERINFO);
return; 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_MSGOUT): /* Message Out -> Command */
case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */ case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */
fas216_send_command(info); fas216_send_command(info);
...@@ -1722,7 +1533,7 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne ...@@ -1722,7 +1533,7 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
return; return;
bad_is: 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); fas216_dumpstate(info);
print_debug_list(); print_debug_list();
...@@ -1733,37 +1544,40 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne ...@@ -1733,37 +1544,40 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
* fas216_funcdone_intr - handle a function done interrupt from FAS216 chip * fas216_funcdone_intr - handle a function done interrupt from FAS216 chip
* @info: interface which caused function done interrupt * @info: interface which caused function done interrupt
* @stat: Status register contents * @stat: Status register contents
* @ssr: SCSI Status register contents * @is: SCSI Status register contents
* *
* Handle a function done interrupt from FAS216 chip * 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 fifo_len = fas216_readb(info, REG_CFIS) & CFIS_CF;
unsigned int status, message;
fas216_checkmagic(info); fas216_checkmagic(info);
fas216_log(info, LOG_FUNCTIONDONE, fas216_log(info, LOG_FUNCTIONDONE,
"function done: stat=%02x ssr=%02x phase=%02x", "function done: stat=%02x is=%02x phase=%02x",
stat, ssr, info->scsi.phase); stat, is, info->scsi.phase);
switch (info->scsi.phase) { switch (info->scsi.phase) {
case PHASE_STATUS: /* status phase - read status and msg */ case PHASE_STATUS: /* status phase - read status and msg */
if (fifo_len != 2) { if (fifo_len != 2) {
fas216_log(info, 0, "odd number of bytes in FIFO: %d", fifo_len); 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); * Read status then message byte.
info->scsi.SCp.Message = message; */
info->scsi.SCp.Status = status; info->scsi.SCp.Status = fas216_readb(info, REG_FF);
info->scsi.SCp.Message = fas216_readb(info, REG_FF);
info->scsi.phase = PHASE_DONE; info->scsi.phase = PHASE_DONE;
fas216_cmd(info, CMD_MSGACCEPTED); fas216_cmd(info, CMD_MSGACCEPTED);
break; break;
case PHASE_IDLE: /* reselected? */ case PHASE_IDLE:
case PHASE_SELECTION:
case PHASE_SELSTEPS:
break;
case PHASE_MSGIN: /* message in phase */ case PHASE_MSGIN: /* message in phase */
case PHASE_RECONNECTED: /* reconnected command */
if ((stat & STAT_BUSMASK) == STAT_MESGIN) { if ((stat & STAT_BUSMASK) == STAT_MESGIN) {
info->scsi.msgin_fifo = fifo_len; info->scsi.msgin_fifo = fifo_len;
fas216_message(info); fas216_message(info);
...@@ -1779,22 +1593,13 @@ static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned ...@@ -1779,22 +1593,13 @@ static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned
static void fas216_bus_reset(FAS216_Info *info) static void fas216_bus_reset(FAS216_Info *info)
{ {
neg_t sync_state, wide_state; neg_t sync_state;
int i; int i;
msgqueue_flush(&info->scsi.msgs); 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; sync_state = neg_invalid;
#ifdef SCSI2_WIDE
if (info->ifcfg.wide_max_size != 0)
wide_state = neg_wait;
#endif
#ifdef SCSI2_SYNC #ifdef SCSI2_SYNC
if (info->ifcfg.capabilities & (FASCAP_DMA|FASCAP_PSEUDODMA)) if (info->ifcfg.capabilities & (FASCAP_DMA|FASCAP_PSEUDODMA))
sync_state = neg_wait; sync_state = neg_wait;
...@@ -1807,7 +1612,6 @@ static void fas216_bus_reset(FAS216_Info *info) ...@@ -1807,7 +1612,6 @@ static void fas216_bus_reset(FAS216_Info *info)
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
info->device[i].disconnect_ok = info->ifcfg.disconnect_ok; info->device[i].disconnect_ok = info->ifcfg.disconnect_ok;
info->device[i].sync_state = sync_state; 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].period = info->ifcfg.asyncperiod / 4;
info->device[i].stp = info->scsi.async_stp; info->device[i].stp = info->scsi.async_stp;
info->device[i].sof = 0; info->device[i].sof = 0;
...@@ -1826,38 +1630,38 @@ static void fas216_bus_reset(FAS216_Info *info) ...@@ -1826,38 +1630,38 @@ static void fas216_bus_reset(FAS216_Info *info)
*/ */
irqreturn_t fas216_intr(FAS216_Info *info) irqreturn_t fas216_intr(FAS216_Info *info)
{ {
unsigned char isr, ssr, stat; unsigned char inst, is, stat;
int handled = IRQ_NONE; int handled = IRQ_NONE;
fas216_checkmagic(info); fas216_checkmagic(info);
stat = fas216_readb(info, REG_STAT); stat = fas216_readb(info, REG_STAT);
ssr = fas216_readb(info, REG_IS); is = fas216_readb(info, REG_IS);
isr = fas216_readb(info, REG_INST); 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 (stat & STAT_INT) {
if (isr & INST_BUSRESET) { if (inst & INST_BUSRESET) {
fas216_log(info, 0, "bus reset detected"); fas216_log(info, 0, "bus reset detected");
fas216_bus_reset(info); fas216_bus_reset(info);
scsi_report_bus_reset(info->host, 0); 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_log(info, LOG_ERROR, "illegal command given\n");
fas216_dumpstate(info); fas216_dumpstate(info);
print_debug_list(); print_debug_list();
} else if (isr & INST_DISCONNECT) } else if (inst & INST_DISCONNECT)
fas216_disconnect_intr(info); fas216_disconnect_intr(info);
else if (isr & INST_RESELECTED) /* reselected */ else if (inst & INST_RESELECTED) /* reselected */
fas216_reselected_intr(info); fas216_reselected_intr(info);
else if (isr & INST_BUSSERVICE) /* bus service request */ else if (inst & INST_BUSSERVICE) /* bus service request */
fas216_busservice_intr(info, stat, ssr); fas216_busservice_intr(info, stat, is);
else if (isr & INST_FUNCDONE) /* function done */ else if (inst & INST_FUNCDONE) /* function done */
fas216_funcdone_intr(info, stat, ssr); fas216_funcdone_intr(info, stat, is);
else else
fas216_log(info, 0, "unknown interrupt received:" fas216_log(info, 0, "unknown interrupt received:"
" phase %s isr %02X ssr %02X stat %02X", " phase %s inst %02X is %02X stat %02X",
fas216_drv_phase(info), isr, ssr, stat); fas216_drv_phase(info), inst, is, stat);
handled = IRQ_HANDLED; handled = IRQ_HANDLED;
} }
return handled; return handled;
...@@ -1948,7 +1752,7 @@ static int parity_test(FAS216_Info *info, int target) ...@@ -1948,7 +1752,7 @@ static int parity_test(FAS216_Info *info, int target)
{ {
#if 0 #if 0
if (target == 3) { if (target == 3) {
info->device[3].parity_check = 0; info->device[target].parity_check = 0;
return 1; return 1;
} }
#endif #endif
...@@ -1991,15 +1795,6 @@ static void fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) ...@@ -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); msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag);
do { 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 #ifdef SCSI2_SYNC
if ((info->device[SCpnt->device->id].sync_state == neg_wait || if ((info->device[SCpnt->device->id].sync_state == neg_wait ||
info->device[SCpnt->device->id].sync_state == neg_complete) && info->device[SCpnt->device->id].sync_state == neg_complete) &&
...@@ -2140,8 +1935,18 @@ static void fas216_kick(FAS216_Info *info) ...@@ -2140,8 +1935,18 @@ static void fas216_kick(FAS216_Info *info)
} }
} while (0); } while (0);
if (!SCpnt) /* no command pending - just exit */ if (!SCpnt) {
/*
* no command pending, so enable reselection.
*/
fas216_cmd(info, CMD_ENABLESEL);
return; return;
}
/*
* We're going to start a command, so disable reselection
*/
fas216_cmd(info, CMD_DISABLESEL);
if (info->scsi.disconnectable && info->SCpnt) { if (info->scsi.disconnectable && info->SCpnt) {
fas216_log(info, LOG_CONNECT, fas216_log(info, LOG_CONNECT,
...@@ -2804,6 +2609,8 @@ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) ...@@ -2804,6 +2609,8 @@ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
clear_bit(SDpnt->id * 8 + i, info->busyluns); clear_bit(SDpnt->id * 8 + i, info->busyluns);
} }
info->scsi.phase = PHASE_IDLE;
/* /*
* Reset the SCSI bus. Device cleanup happens in * Reset the SCSI bus. Device cleanup happens in
* the interrupt handler. * the interrupt handler.
...@@ -2833,7 +2640,8 @@ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) ...@@ -2833,7 +2640,8 @@ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
*/ */
static void fas216_init_chip(FAS216_Info *info) 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_CNTL1, info->scsi.cfg[0]);
fas216_writeb(info, REG_CNTL2, info->scsi.cfg[1]); fas216_writeb(info, REG_CNTL2, info->scsi.cfg[1]);
fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]); fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]);
...@@ -3042,7 +2850,7 @@ int fas216_init(struct Scsi_Host *host) ...@@ -3042,7 +2850,7 @@ int fas216_init(struct Scsi_Host *host)
info->scsi.cfg[0] = host->this_id | CNTL1_PERE; info->scsi.cfg[0] = host->this_id | CNTL1_PERE;
info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE; info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE;
info->scsi.cfg[2] = info->ifcfg.cntl3 | 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->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod);
info->rst_dev_status = -1; info->rst_dev_status = -1;
...@@ -3082,6 +2890,12 @@ int fas216_add(struct Scsi_Host *host, struct device *dev) ...@@ -3082,6 +2890,12 @@ int fas216_add(struct Scsi_Host *host, struct device *dev)
FAS216_Info *info = (FAS216_Info *)host->hostdata; FAS216_Info *info = (FAS216_Info *)host->hostdata;
int type, ret; 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); fas216_reset_state(info);
type = fas216_detect_type(info); type = fas216_detect_type(info);
info->scsi.type = chip_types[type]; info->scsi.type = chip_types[type];
...@@ -3181,32 +2995,32 @@ int fas216_print_stats(FAS216_Info *info, char *buffer) ...@@ -3181,32 +2995,32 @@ int fas216_print_stats(FAS216_Info *info, char *buffer)
return p - 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]; struct fas216_device *dev;
int len = 0; Scsi_Device *scd;
char *p; char *p = buffer;
proc_print_scsidevice(scd, buffer, &len, 0);
p = buffer + len;
p += sprintf(p, " Extensions: ");
if (scd->tagged_supported) p += sprintf(p, "Device/Lun TaggedQ Parity Sync\n");
p += sprintf(p, "TAG %sabled [%d] ",
scd->tagged_queue ? "en" : "dis",
scd->current_tag);
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 ", p += sprintf(p, "%3sabled ", dev->parity_enabled ? "en" : "dis");
8 << dev->wide_xfer);
if (dev->sof) if (dev->sof)
p += sprintf(p, "sync offset %d, %d ns\n", p += sprintf(p, "offset %d, %d ns\n",
dev->sof, dev->period * 4); dev->sof, dev->period * 4);
else else
p += sprintf(p, "async\n"); p += sprintf(p, "async\n");
}
return p - buffer; return p - buffer;
} }
...@@ -3224,7 +3038,7 @@ EXPORT_SYMBOL(fas216_eh_bus_reset); ...@@ -3224,7 +3038,7 @@ EXPORT_SYMBOL(fas216_eh_bus_reset);
EXPORT_SYMBOL(fas216_eh_host_reset); EXPORT_SYMBOL(fas216_eh_host_reset);
EXPORT_SYMBOL(fas216_print_host); EXPORT_SYMBOL(fas216_print_host);
EXPORT_SYMBOL(fas216_print_stats); EXPORT_SYMBOL(fas216_print_stats);
EXPORT_SYMBOL(fas216_print_device); EXPORT_SYMBOL(fas216_print_devices);
MODULE_AUTHOR("Russell King"); MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver core"); MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver core");
......
...@@ -177,7 +177,6 @@ typedef enum { ...@@ -177,7 +177,6 @@ typedef enum {
PHASE_SELSTEPS, /* selection with command steps */ PHASE_SELSTEPS, /* selection with command steps */
PHASE_COMMAND, /* command sent */ PHASE_COMMAND, /* command sent */
PHASE_MESSAGESENT, /* selected, and we're sending cmd */ PHASE_MESSAGESENT, /* selected, and we're sending cmd */
PHASE_RECONNECTED, /* reconnected */
PHASE_DATAOUT, /* data out to device */ PHASE_DATAOUT, /* data out to device */
PHASE_DATAIN, /* data in from device */ PHASE_DATAIN, /* data in from device */
PHASE_MSGIN, /* message in from device */ PHASE_MSGIN, /* message in from device */
...@@ -244,12 +243,6 @@ typedef struct { ...@@ -244,12 +243,6 @@ typedef struct {
const char *type; /* chip type */ const char *type; /* chip type */
unsigned int irq; /* interrupt */ 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 */ Scsi_Pointer SCp; /* current commands data pointer */
MsgQueue_t msgs; /* message queue for connected device */ MsgQueue_t msgs; /* message queue for connected device */
...@@ -368,7 +361,7 @@ extern void fas216_release (struct Scsi_Host *instance); ...@@ -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_host(FAS216_Info *info, char *buffer);
extern int fas216_print_stats(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) /* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt)
* Purpose : abort this command * Purpose : abort this command
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include "../../scsi/scsi.h" #include "../scsi.h"
#include "../../scsi/hosts.h" #include "../hosts.h"
#define AUTOSENSE #define AUTOSENSE
/*#define PSEUDO_DMA*/ /*#define PSEUDO_DMA*/
...@@ -40,7 +40,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset, ...@@ -40,7 +40,7 @@ int NCR5380_proc_info(char *buffer, char **start, off_t offset,
#define BOARD_NORMAL 0 #define BOARD_NORMAL 0
#define BOARD_NCR53C400 1 #define BOARD_NCR53C400 1
#include "../../scsi/NCR5380.h" #include "../NCR5380.h"
#undef START_DMA_INITIATOR_RECEIVE_REG #undef START_DMA_INITIATOR_RECEIVE_REG
#define START_DMA_INITIATOR_RECEIVE_REG (7 + 128) #define START_DMA_INITIATOR_RECEIVE_REG (7 + 128)
...@@ -112,7 +112,7 @@ printk("reading %p len %d\n", addr, len); ...@@ -112,7 +112,7 @@ printk("reading %p len %d\n", addr, len);
#undef STAT #undef STAT
#include "../../scsi/NCR5380.c" #include "../NCR5380.c"
static Scsi_Host_Template oakscsi_template = { static Scsi_Host_Template oakscsi_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
......
...@@ -25,8 +25,8 @@ ...@@ -25,8 +25,8 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include "../../scsi/scsi.h" #include "../scsi.h"
#include "../../scsi/hosts.h" #include "../hosts.h"
#include "fas216.h" #include "fas216.h"
#include "scsi.h" #include "scsi.h"
...@@ -242,10 +242,10 @@ powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) ...@@ -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 powertecscsi_proc_info(char *buffer, char **start, off_t offset,
int length, int host_no, int inout) int length, int host_no, int inout)
{ {
int pos, begin;
struct Scsi_Host *host; struct Scsi_Host *host;
struct powertec_info *info; struct powertec_info *info;
Scsi_Device *scd; char *p = buffer;
int pos;
host = scsi_host_hn_get(host_no); host = scsi_host_hn_get(host_no);
if (!host) if (!host)
...@@ -256,29 +256,16 @@ int powertecscsi_proc_info(char *buffer, char **start, off_t offset, ...@@ -256,29 +256,16 @@ int powertecscsi_proc_info(char *buffer, char **start, off_t offset,
info = (struct powertec_info *)host->hostdata; info = (struct powertec_info *)host->hostdata;
begin = 0; p += sprintf(p, "PowerTec SCSI driver v%s\n", VERSION);
pos = sprintf(buffer, "PowerTec SCSI driver v%s\n", VERSION); p += fas216_print_host(&info->info, p);
pos += fas216_print_host(&info->info, buffer + pos); p += sprintf(p, "Term : o%s\n",
pos += sprintf(buffer + pos, "Term : o%s\n",
info->term_ctl ? "n" : "ff"); 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"); *start = buffer + offset;
pos = p - buffer - offset;
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;
if (pos > length) if (pos > length)
pos = length; pos = length;
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/init.h> #include <linux/init.h>
#include "../../scsi/scsi.h" #include "../scsi.h"
#define DEBUG #define DEBUG
......
...@@ -146,7 +146,7 @@ cyber2000_seqw(unsigned int reg, unsigned int val, struct cfb_info *cfb) ...@@ -146,7 +146,7 @@ cyber2000_seqw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
* Hardware Cyber2000 Acceleration * Hardware Cyber2000 Acceleration
*/ */
static void 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; struct cfb_info *cfb = (struct cfb_info *)info;
unsigned long dst, col; unsigned long dst, col;
...@@ -178,7 +178,7 @@ cyber2000fb_fillrect(struct fb_info *info, struct fb_fillrect *rect) ...@@ -178,7 +178,7 @@ cyber2000fb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
} }
static void 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; struct cfb_info *cfb = (struct cfb_info *)info;
unsigned int cmd = CO_CMD_L_PATTERN_FGCOL; unsigned int cmd = CO_CMD_L_PATTERN_FGCOL;
...@@ -189,24 +189,25 @@ cyber2000fb_copyarea(struct fb_info *info, struct fb_copyarea *region) ...@@ -189,24 +189,25 @@ cyber2000fb_copyarea(struct fb_info *info, struct fb_copyarea *region)
return; 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) { if (region->sx < region->dx) {
region->sx += region->width - 1; src += region->width - 1;
region->dx += region->width - 1; dst += region->width - 1;
cmd |= CO_CMD_L_INC_LEFT; cmd |= CO_CMD_L_INC_LEFT;
} }
if (region->sy < region->dy) { if (region->sy < region->dy) {
region->sy += region->height - 1; src += (region->height - 1) * cfb->fb.var.xres_virtual;
region->dy += region->height - 1; dst += (region->height - 1) * cfb->fb.var.xres_virtual;
cmd |= CO_CMD_L_INC_UP; 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) { if (cfb->fb.var.bits_per_pixel == 24) {
cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb); cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
src *= 3; src *= 3;
...@@ -221,9 +222,9 @@ cyber2000fb_copyarea(struct fb_info *info, struct fb_copyarea *region) ...@@ -221,9 +222,9 @@ cyber2000fb_copyarea(struct fb_info *info, struct fb_copyarea *region)
} }
static void 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)) { // if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT)) {
cfb_imageblit(info, image); cfb_imageblit(info, image);
...@@ -754,7 +755,6 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ...@@ -754,7 +755,6 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->blue.msb_right = 0; var->blue.msb_right = 0;
switch (var->bits_per_pixel) { switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8: /* PSEUDOCOLOUR, 256 */ case 8: /* PSEUDOCOLOUR, 256 */
var->transp.offset = 0; var->transp.offset = 0;
var->transp.length = 0; var->transp.length = 0;
...@@ -765,8 +765,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ...@@ -765,8 +765,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->blue.offset = 0; var->blue.offset = 0;
var->blue.length = 8; var->blue.length = 8;
break; break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:/* DIRECTCOLOUR, 64k or 32k */ case 16:/* DIRECTCOLOUR, 64k or 32k */
switch (var->green.length) { switch (var->green.length) {
case 6: /* RGB565, 64k */ case 6: /* RGB565, 64k */
...@@ -804,8 +803,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ...@@ -804,8 +803,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
break; break;
} }
break; break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:/* TRUECOLOUR, 16m */ case 24:/* TRUECOLOUR, 16m */
var->transp.offset = 0; var->transp.offset = 0;
var->transp.length = 0; var->transp.length = 0;
...@@ -816,8 +814,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ...@@ -816,8 +814,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->blue.offset = 0; var->blue.offset = 0;
var->blue.length = 8; var->blue.length = 8;
break; break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:/* TRUECOLOUR, 16m */ case 32:/* TRUECOLOUR, 16m */
var->transp.offset = 24; var->transp.offset = 24;
var->transp.length = 8; var->transp.length = 8;
...@@ -828,7 +825,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ...@@ -828,7 +825,7 @@ cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->blue.offset = 0; var->blue.offset = 0;
var->blue.length = 8; var->blue.length = 8;
break; break;
#endif
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -1601,15 +1598,17 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -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? * Use MCLK from BIOS. FIXME: what about hotplug?
*/ */
#ifndef __arm__
cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb); cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb);
cfb->mclk_div = cyber2000_grphr(EXT_MCLK_DIV, cfb); cfb->mclk_div = cyber2000_grphr(EXT_MCLK_DIV, cfb);
#else
#ifdef __arm__
/* /*
* MCLK on the NetWinder and the Shark is fixed at 75MHz * MCLK on the NetWinder and the Shark is fixed at 75MHz
*/ */
cfb->mclk_mult = 0xdb; if (machine_is_netwinder()) {
cfb->mclk_div = 0x54; cfb->mclk_mult = 0xdb;
cfb->mclk_div = 0x54;
}
#endif #endif
err = cyberpro_common_probe(cfb); err = cyberpro_common_probe(cfb);
......
...@@ -41,6 +41,7 @@ struct dma_struct { ...@@ -41,6 +41,7 @@ struct dma_struct {
unsigned int dma_base; /* Controller base address */ unsigned int dma_base; /* Controller base address */
int dma_irq; /* Controller IRQ */ int dma_irq; /* Controller IRQ */
struct scatterlist cur_sg; /* Current controller buffer */ struct scatterlist cur_sg; /* Current controller buffer */
unsigned int state;
struct dma_ops *d_ops; struct dma_ops *d_ops;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment