/*
* linux/drivers/acorn/scsi/powertec.c
*
- * Copyright (C) 1997-2003 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
#include <asm/dma.h>
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/pgtable.h>
#include "../scsi.h"
struct powertec_info {
FAS216_Info info;
struct expansion_card *ec;
- void *term_port;
+ void __iomem *base;
unsigned int term_ctl;
struct scatterlist sg[NR_SG];
};
static void
powertecscsi_irqenable(struct expansion_card *ec, int irqnr)
{
- writeb(POWERTEC_INTR_ENABLE, ec->irq_data);
+ struct powertec_info *info = ec->irq_data;
+ writeb(POWERTEC_INTR_ENABLE, info->base + POWERTEC_INTR_CONTROL);
}
/* Prototype: void powertecscsi_irqdisable(ec, irqnr)
static void
powertecscsi_irqdisable(struct expansion_card *ec, int irqnr)
{
- writeb(POWERTEC_INTR_DISABLE, ec->irq_data);
+ struct powertec_info *info = ec->irq_data;
+ writeb(POWERTEC_INTR_DISABLE, info->base + POWERTEC_INTR_CONTROL);
}
static const expansioncard_ops_t powertecscsi_ops = {
struct powertec_info *info = (struct powertec_info *)host->hostdata;
info->term_ctl = on_off ? POWERTEC_TERM_ENABLE : 0;
- writeb(info->term_ctl, info->term_port);
+ writeb(info->term_ctl, info->base + POWERTEC_TERM_CONTROL);
}
/* Prototype: void powertecscsi_intr(irq, *dev_id, *regs)
* Returns : type of transfer to be performed
*/
static fasdmatype_t
-powertecscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
+powertecscsi_dma_setup(struct Scsi_Host *host, struct scsi_pointer *SCp,
fasdmadir_t direction, fasdmatype_t min_type)
{
struct powertec_info *info = (struct powertec_info *)host->hostdata;
struct device *dev = scsi_get_device(host);
- int dmach = host->dma_channel;
+ int dmach = info->info.scsi.dma;
if (info->info.ifcfg.capabilities & FASCAP_DMA &&
min_type == fasdma_real_all) {
* SCpnt - command
*/
static void
-powertecscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
+powertecscsi_dma_stop(struct Scsi_Host *host, struct scsi_pointer *SCp)
{
- if (host->dma_channel != NO_DMA)
- disable_dma(host->dma_channel);
+ struct powertec_info *info = (struct powertec_info *)host->hostdata;
+ if (info->info.scsi.dma != NO_DMA)
+ disable_dma(info->info.scsi.dma);
}
/* Prototype: const char *powertecscsi_info(struct Scsi_Host * host)
return pos;
}
-static ssize_t powertecscsi_show_term(struct device *dev, char *buf)
+static ssize_t powertecscsi_show_term(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
struct Scsi_Host *host = ecard_get_drvdata(ec);
}
static ssize_t
-powertecscsi_store_term(struct device *dev, const char *buf, size_t len)
+powertecscsi_store_term(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
{
struct expansion_card *ec = ECARD_DEV(dev);
struct Scsi_Host *host = ecard_get_drvdata(ec);
static DEVICE_ATTR(bus_term, S_IRUGO | S_IWUSR,
powertecscsi_show_term, powertecscsi_store_term);
-static Scsi_Host_Template powertecscsi_template = {
+static struct scsi_host_template powertecscsi_template = {
.module = THIS_MODULE,
.proc_info = powertecscsi_proc_info,
.name = "PowerTec SCSI",
struct Scsi_Host *host;
struct powertec_info *info;
unsigned long resbase, reslen;
- unsigned char *base;
+ void __iomem *base;
int ret;
- resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST);
- reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST);
-
- if (!request_mem_region(resbase, reslen, "powertecscsi")) {
- ret = -EBUSY;
+ ret = ecard_request_resources(ec);
+ if (ret)
goto out;
- }
+ resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST);
+ reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST);
base = ioremap(resbase, reslen);
if (!base) {
ret = -ENOMEM;
goto out_unmap;
}
- host->base = (unsigned long)base;
- host->irq = ec->irq;
- host->dma_channel = ec->dma;
-
- ec->irqaddr = base + POWERTEC_INTR_STATUS;
- ec->irqmask = POWERTEC_INTR_BIT;
- ec->irq_data = base + POWERTEC_INTR_CONTROL;
- ec->ops = &powertecscsi_ops;
-
ecard_set_drvdata(ec, host);
info = (struct powertec_info *)host->hostdata;
- info->term_port = base + POWERTEC_TERM_CONTROL;
+ info->base = base;
powertecscsi_terminator_ctl(host, term[ec->slot_no]);
- device_create_file(&ec->dev, &dev_attr_bus_term);
-
info->info.scsi.io_base = base + POWERTEC_FAS216_OFFSET;
info->info.scsi.io_shift = POWERTEC_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 = NULL;
info->info.dma.stop = powertecscsi_dma_stop;
+ ec->irqaddr = base + POWERTEC_INTR_STATUS;
+ ec->irqmask = POWERTEC_INTR_BIT;
+ ec->irq_data = info;
+ ec->ops = &powertecscsi_ops;
+
+ device_create_file(&ec->dev, &dev_attr_bus_term);
+
ret = fas216_init(host);
if (ret)
goto out_free;
- ret = request_irq(host->irq, powertecscsi_intr,
+ ret = request_irq(ec->irq, powertecscsi_intr,
SA_INTERRUPT, "powertec", 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, "powertec")) {
+ if (info->info.scsi.dma != NO_DMA) {
+ if (request_dma(info->info.scsi.dma, "powertec")) {
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);
iounmap(base);
out_region:
- release_mem_region(resbase, reslen);
+ ecard_release_resources(ec);
out:
return ret;
static void __devexit powertecscsi_remove(struct expansion_card *ec)
{
struct Scsi_Host *host = ecard_get_drvdata(ec);
- struct powertecscsi_info *info = (struct powertecscsi_info *)host->hostdata;
- unsigned long resbase, reslen;
+ struct powertec_info *info = (struct powertec_info *)host->hostdata;
ecard_set_drvdata(ec, NULL);
fas216_remove(host);
device_remove_file(&ec->dev, &dev_attr_bus_term);
- if (host->dma_channel != NO_DMA)
- free_dma(host->dma_channel);
- free_irq(host->irq, info);
-
- iounmap((void *)host->base);
-
- resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST);
- reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST);
+ if (info->info.scsi.dma != NO_DMA)
+ free_dma(info->info.scsi.dma);
+ free_irq(ec->irq, info);
- release_mem_region(resbase, reslen);
+ iounmap(info->base);
fas216_release(host);
scsi_host_put(host);
+ ecard_release_resources(ec);
}
static const struct ecard_id powertecscsi_cids[] = {