/*
* linux/drivers/acorn/scsi/cumana_2.c
*
- * Copyright (C) 1997-2002 Russell King
+ * Copyright (C) 1997-2005 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
struct cumanascsi2_info {
FAS216_Info info;
struct expansion_card *ec;
-
- void *status; /* card status register */
- void *alatch; /* Control register */
+ void __iomem *base;
unsigned int terms; /* Terminator state */
- void *dmaarea; /* Pseudo DMA area */
struct scatterlist sg[NR_SG]; /* Scatter DMA list */
};
static void
cumanascsi_2_irqenable(struct expansion_card *ec, int irqnr)
{
- writeb(ALATCH_ENA_INT, ec->irq_data);
+ struct cumanascsi2_info *info = ec->irq_data;
+ writeb(ALATCH_ENA_INT, info->base + CUMANASCSI2_ALATCH);
}
/* Prototype: void cumanascsi_2_irqdisable(ec, irqnr)
static void
cumanascsi_2_irqdisable(struct expansion_card *ec, int irqnr)
{
- writeb(ALATCH_DIS_INT, ec->irq_data);
+ struct cumanascsi2_info *info = ec->irq_data;
+ writeb(ALATCH_DIS_INT, info->base + CUMANASCSI2_ALATCH);
}
static const expansioncard_ops_t cumanascsi_2_ops = {
if (on_off) {
info->terms = 1;
- writeb(ALATCH_ENA_TERM, info->alatch);
+ writeb(ALATCH_ENA_TERM, info->base + CUMANASCSI2_ALATCH);
} else {
info->terms = 0;
- writeb(ALATCH_DIS_TERM, info->alatch);
+ writeb(ALATCH_DIS_TERM, info->base + CUMANASCSI2_ALATCH);
}
}
{
struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
struct device *dev = scsi_get_device(host);
- int dmach = host->dma_channel;
+ int dmach = info->info.scsi.dma;
- writeb(ALATCH_DIS_DMA, info->alatch);
+ writeb(ALATCH_DIS_DMA, info->base + CUMANASCSI2_ALATCH);
if (dmach != NO_DMA &&
(min_type == fasdma_real_all || SCp->this_residual >= 512)) {
disable_dma(dmach);
set_dma_sg(dmach, info->sg, bufs + 1);
- writeb(alatch_dir, info->alatch);
+ writeb(alatch_dir, info->base + CUMANASCSI2_ALATCH);
set_dma_mode(dmach, dma_dir);
enable_dma(dmach);
- writeb(ALATCH_ENA_DMA, info->alatch);
- writeb(ALATCH_DIS_BIT32, info->alatch);
+ writeb(ALATCH_ENA_DMA, info->base + CUMANASCSI2_ALATCH);
+ writeb(ALATCH_DIS_BIT32, info->base + CUMANASCSI2_ALATCH);
return fasdma_real_all;
}
#if 0
while (length > 1) {
unsigned long word;
- unsigned int status = readb(info->status);
+ unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
if (status & STATUS_INT)
goto end;
continue;
word = *addr | *(addr + 1) << 8;
- writew(word, info->dmaarea);
+ writew(word, info->base + CUMANASCSI2_PSEUDODMA);
addr += 2;
length -= 2;
}
else {
if (transfer && (transfer & 255)) {
while (length >= 256) {
- unsigned int status = readb(info->status);
+ unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
if (status & STATUS_INT)
return;
if (!(status & STATUS_DRQ))
continue;
- readsw(info->dmaarea, addr, 256 >> 1);
+ readsw(info->base + CUMANASCSI2_PSEUDODMA,
+ addr, 256 >> 1);
addr += 256;
length -= 256;
}
while (length > 0) {
unsigned long word;
- unsigned int status = readb(info->status);
+ unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
if (status & STATUS_INT)
return;
if (!(status & STATUS_DRQ))
continue;
- word = readw(info->dmaarea);
+ word = readw(info->base + CUMANASCSI2_PSEUDODMA);
*addr++ = word;
if (--length > 0) {
*addr++ = word >> 8;
cumanascsi_2_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
{
struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
- if (host->dma_channel != NO_DMA) {
- writeb(ALATCH_DIS_DMA, info->alatch);
- disable_dma(host->dma_channel);
+ if (info->info.scsi.dma != NO_DMA) {
+ writeb(ALATCH_DIS_DMA, info->base + CUMANASCSI2_ALATCH);
+ disable_dma(info->info.scsi.dma);
}
}
struct Scsi_Host *host;
struct cumanascsi2_info *info;
unsigned long resbase, reslen;
- unsigned char *base;
+ void __iomem *base;
int ret;
ret = ecard_request_resources(ec);
goto out_unmap;
}
- host->base = (unsigned long)base;
- host->irq = ec->irq;
- host->dma_channel = ec->dma;
-
ecard_set_drvdata(ec, host);
info = (struct cumanascsi2_info *)host->hostdata;
info->ec = ec;
- info->dmaarea = base + CUMANASCSI2_PSEUDODMA;
- info->status = base + CUMANASCSI2_STATUS;
- info->alatch = base + CUMANASCSI2_ALATCH;
-
- ec->irqaddr = info->status;
- ec->irqmask = STATUS_INT;
- ec->irq_data = base + CUMANASCSI2_ALATCH;
- ec->ops = &cumanascsi_2_ops;
+ info->base = base;
cumanascsi_2_terminator_ctl(host, term[ec->slot_no]);
info->info.scsi.io_base = base + CUMANASCSI2_FAS216_OFFSET;
info->info.scsi.io_shift = CUMANASCSI2_FAS216_SHIFT;
- info->info.scsi.irq = host->irq;
+ info->info.scsi.irq = ec->irq;
+ info->info.scsi.dma = ec->dma;
info->info.ifcfg.clockrate = 40; /* MHz */
info->info.ifcfg.select_timeout = 255;
info->info.ifcfg.asyncperiod = 200; /* ns */
info->info.dma.pseudo = cumanascsi_2_dma_pseudo;
info->info.dma.stop = cumanascsi_2_dma_stop;
+ ec->irqaddr = info->base + CUMANASCSI2_STATUS;
+ ec->irqmask = STATUS_INT;
+ ec->irq_data = info;
+ ec->ops = &cumanascsi_2_ops;
+
ret = fas216_init(host);
if (ret)
goto out_free;
- ret = request_irq(host->irq, cumanascsi_2_intr,
+ ret = request_irq(ec->irq, cumanascsi_2_intr,
SA_INTERRUPT, "cumanascsi2", info);
if (ret) {
printk("scsi%d: IRQ%d not free: %d\n",
- host->host_no, host->irq, ret);
+ host->host_no, ec->irq, ret);
goto out_release;
}
- if (host->dma_channel != NO_DMA) {
- if (request_dma(host->dma_channel, "cumanascsi2")) {
+ if (info->info.scsi.dma != NO_DMA) {
+ if (request_dma(info->info.scsi.dma, "cumanascsi2")) {
printk("scsi%d: DMA%d not free, using PIO\n",
- host->host_no, host->dma_channel);
- host->dma_channel = NO_DMA;
+ host->host_no, info->info.scsi.dma);
+ info->info.scsi.dma = NO_DMA;
} else {
- set_dma_speed(host->dma_channel, 180);
+ set_dma_speed(info->info.scsi.dma, 180);
info->info.ifcfg.capabilities |= FASCAP_DMA;
}
}
if (ret == 0)
goto out;
- if (host->dma_channel != NO_DMA)
- free_dma(host->dma_channel);
- free_irq(host->irq, host);
+ if (info->info.scsi.dma != NO_DMA)
+ free_dma(info->info.scsi.dma);
+ free_irq(ec->irq, host);
out_release:
fas216_release(host);
ecard_set_drvdata(ec, NULL);
fas216_remove(host);
- if (host->dma_channel != NO_DMA)
- free_dma(host->dma_channel);
- free_irq(host->irq, info);
+ if (info->info.scsi.dma != NO_DMA)
+ free_dma(info->info.scsi.dma);
+ free_irq(ec->irq, info);
- iounmap((void *)host->base);
+ iounmap(info->base);
fas216_release(host);
scsi_host_put(host);