ppc32: Update the PowerMac 53c94 SCSI driver

Adapt to the "macio" driver infrastructure, cleanup IO accessors,
remove local list of command/directions, uses infos provided by
the SCSI layer. This driver certainly could use some more work.
parent 3d8e5084
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#include <asm/macio.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
...@@ -37,13 +38,12 @@ enum fsc_phase { ...@@ -37,13 +38,12 @@ enum fsc_phase {
}; };
struct fsc_state { struct fsc_state {
volatile struct mac53c94_regs *regs; struct mac53c94_regs *regs;
int intr; int intr;
volatile struct dbdma_regs *dma; struct dbdma_regs *dma;
int dmaintr; int dmaintr;
int clk_freq; int clk_freq;
struct Scsi_Host *host; struct Scsi_Host *host;
struct fsc_state *next;
Scsi_Cmnd *request_q; Scsi_Cmnd *request_q;
Scsi_Cmnd *request_qtail; Scsi_Cmnd *request_qtail;
Scsi_Cmnd *current_req; /* req we're currently working on */ Scsi_Cmnd *current_req; /* req we're currently working on */
...@@ -52,151 +52,23 @@ struct fsc_state { ...@@ -52,151 +52,23 @@ struct fsc_state {
void *dma_cmd_space; void *dma_cmd_space;
struct pci_dev *pdev; struct pci_dev *pdev;
dma_addr_t dma_addr; dma_addr_t dma_addr;
struct macio_dev *mdev;
}; };
static struct fsc_state *all_53c94s;
static void mac53c94_init(struct fsc_state *); static void mac53c94_init(struct fsc_state *);
static void mac53c94_start(struct fsc_state *); static void mac53c94_start(struct fsc_state *);
static void mac53c94_interrupt(int, void *, struct pt_regs *); static void mac53c94_interrupt(int, void *, struct pt_regs *);
static irqreturn_t do_mac53c94_interrupt(int, void *, struct pt_regs *); static irqreturn_t do_mac53c94_interrupt(int, void *, struct pt_regs *);
static void cmd_done(struct fsc_state *, int result); static void cmd_done(struct fsc_state *, int result);
static void set_dma_cmds(struct fsc_state *, Scsi_Cmnd *); static void set_dma_cmds(struct fsc_state *, Scsi_Cmnd *);
static int data_goes_out(Scsi_Cmnd *);
int
mac53c94_detect(Scsi_Host_Template *tp)
{
struct device_node *node;
int nfscs;
struct fsc_state *state, **prev_statep;
struct Scsi_Host *host;
void *dma_cmd_space;
unsigned char *clkprop;
int proplen;
struct pci_dev *pdev;
u8 pbus, devfn;
nfscs = 0;
prev_statep = &all_53c94s;
for (node = find_devices("53c94"); node != 0; node = node->next) {
if (node->n_addrs != 2 || node->n_intrs != 2) {
printk(KERN_ERR "mac53c94: expected 2 addrs and intrs"
" (got %d/%d) for node %s\n",
node->n_addrs, node->n_intrs, node->full_name);
continue;
}
pdev = NULL;
if (node->parent != NULL
&& !pci_device_from_OF_node(node->parent, &pbus, &devfn))
pdev = pci_find_slot(pbus, devfn);
if (pdev == NULL) {
printk(KERN_ERR "mac53c94: can't find PCI device "
"for %s\n", node->full_name);
continue;
}
host = scsi_register(tp, sizeof(struct fsc_state));
if (host == NULL)
break;
host->unique_id = nfscs;
state = (struct fsc_state *) host->hostdata;
if (state == 0) {
/* "can't happen" */
printk(KERN_ERR "mac53c94: no state for %s?!\n",
node->full_name);
scsi_unregister(host);
break;
}
state->host = host;
state->pdev = pdev;
state->regs = (volatile struct mac53c94_regs *)
ioremap(node->addrs[0].address, 0x1000);
state->intr = node->intrs[0].line;
state->dma = (volatile struct dbdma_regs *)
ioremap(node->addrs[1].address, 0x1000);
state->dmaintr = node->intrs[1].line;
if (state->regs == NULL || state->dma == NULL) {
printk(KERN_ERR "mac53c94: ioremap failed for %s\n",
node->full_name);
if (state->dma != NULL)
iounmap(state->dma);
if (state->regs != NULL)
iounmap(state->regs);
scsi_unregister(host);
break;
}
clkprop = get_property(node, "clock-frequency", &proplen);
if (clkprop == NULL || proplen != sizeof(int)) {
printk(KERN_ERR "%s: can't get clock frequency, "
"assuming 25MHz\n", node->full_name);
state->clk_freq = 25000000;
} else
state->clk_freq = *(int *)clkprop;
/* Space for dma command list: +1 for stop command,
+1 to allow for aligning. */
dma_cmd_space = kmalloc((host->sg_tablesize + 2) *
sizeof(struct dbdma_cmd), GFP_KERNEL);
if (dma_cmd_space == 0) {
printk(KERN_ERR "mac53c94: couldn't allocate dma "
"command space for %s\n", node->full_name);
goto err_cleanup;
}
state->dma_cmds = (struct dbdma_cmd *)
DBDMA_ALIGN(dma_cmd_space);
memset(state->dma_cmds, 0, (host->sg_tablesize + 1)
* sizeof(struct dbdma_cmd));
state->dma_cmd_space = dma_cmd_space;
*prev_statep = state;
prev_statep = &state->next;
if (request_irq(state->intr, do_mac53c94_interrupt, 0,
"53C94", state)) {
printk(KERN_ERR "mac53C94: can't get irq %d for %s\n",
state->intr, node->full_name);
err_cleanup:
iounmap(state->dma);
iounmap(state->regs);
scsi_unregister(host);
break;
}
mac53c94_init(state);
++nfscs;
}
return nfscs;
}
int
mac53c94_release(struct Scsi_Host *host)
{
struct fsc_state *fp = (struct fsc_state *) host->hostdata;
if (fp == 0)
return 0;
if (fp->regs)
iounmap((void *) fp->regs);
if (fp->dma)
iounmap((void *) fp->dma);
kfree(fp->dma_cmd_space);
free_irq(fp->intr, fp);
return 0;
}
int static int mac53c94_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
mac53c94_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
{ {
struct fsc_state *state; struct fsc_state *state;
#if 0 #if 0
if (data_goes_out(cmd)) { if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
int i; int i;
printk(KERN_DEBUG "mac53c94_queue %p: command is", cmd); printk(KERN_DEBUG "mac53c94_queue %p: command is", cmd);
for (i = 0; i < cmd->cmd_len; ++i) for (i = 0; i < cmd->cmd_len; ++i)
...@@ -223,60 +95,52 @@ mac53c94_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) ...@@ -223,60 +95,52 @@ mac53c94_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
return 0; return 0;
} }
int static int mac53c94_abort(Scsi_Cmnd *cmd)
mac53c94_abort(Scsi_Cmnd *cmd)
{ {
return SCSI_ABORT_SNOOZE; return SCSI_ABORT_SNOOZE;
} }
int static int mac53c94_host_reset(Scsi_Cmnd *cmd)
mac53c94_host_reset(Scsi_Cmnd *cmd)
{ {
struct fsc_state *state = (struct fsc_state *) cmd->device->host->hostdata; struct fsc_state *state = (struct fsc_state *) cmd->device->host->hostdata;
volatile struct mac53c94_regs *regs = state->regs; struct mac53c94_regs *regs = state->regs;
volatile struct dbdma_regs *dma = state->dma; struct dbdma_regs *dma = state->dma;
st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
regs->command = CMD_SCSI_RESET; /* assert RST */ writeb(CMD_SCSI_RESET, &regs->command); /* assert RST */
eieio();
udelay(100); /* leave it on for a while (>= 25us) */ udelay(100); /* leave it on for a while (>= 25us) */
regs->command = CMD_RESET; writeb(CMD_RESET, &regs->command);
eieio();
udelay(20); udelay(20);
mac53c94_init(state); mac53c94_init(state);
regs->command = CMD_NOP; writeb(CMD_NOP, &regs->command);
eieio();
return SUCCESS; return SUCCESS;
} }
static void static void mac53c94_init(struct fsc_state *state)
mac53c94_init(struct fsc_state *state)
{ {
volatile struct mac53c94_regs *regs = state->regs; struct mac53c94_regs *regs = state->regs;
volatile struct dbdma_regs *dma = state->dma; struct dbdma_regs *dma = state->dma;
int x; int x;
regs->config1 = state->host->this_id | CF1_PAR_ENABLE; writeb(state->host->this_id | CF1_PAR_ENABLE, &regs->config1);
regs->sel_timeout = TIMO_VAL(250); /* 250ms */ writeb(TIMO_VAL(250), &regs->sel_timeout); /* 250ms */
regs->clk_factor = CLKF_VAL(state->clk_freq); writeb(CLKF_VAL(state->clk_freq), &regs->clk_factor);
regs->config2 = CF2_FEATURE_EN; writeb(CF2_FEATURE_EN, &regs->config2);
regs->config3 = 0; writeb(0, &regs->config3);
regs->sync_period = 0; writeb(0, &regs->sync_period);
regs->sync_offset = 0; writeb(0, &regs->sync_offset);
eieio(); x = readb(&regs->interrupt);
x = regs->interrupt; writel((RUN|PAUSE|FLUSH|WAKE) << 16, &dma->control);
st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
} }
/* /*
* Start the next command for a 53C94. * Start the next command for a 53C94.
* Should be called with interrupts disabled. * Should be called with interrupts disabled.
*/ */
static void static void mac53c94_start(struct fsc_state *state)
mac53c94_start(struct fsc_state *state)
{ {
Scsi_Cmnd *cmd; Scsi_Cmnd *cmd;
volatile struct mac53c94_regs *regs = state->regs; struct mac53c94_regs *regs = state->regs;
int i; int i;
if (state->phase != idle || state->current_req != NULL) if (state->phase != idle || state->current_req != NULL)
...@@ -287,37 +151,30 @@ mac53c94_start(struct fsc_state *state) ...@@ -287,37 +151,30 @@ mac53c94_start(struct fsc_state *state)
state->request_q = (Scsi_Cmnd *) cmd->host_scribble; state->request_q = (Scsi_Cmnd *) cmd->host_scribble;
/* Off we go */ /* Off we go */
regs->count_lo = 0; writeb(0, &regs->count_lo);
regs->count_mid = 0; writeb(0, &regs->count_mid);
regs->count_hi = 0; writeb(0, &regs->count_hi);
eieio(); writeb(CMD_NOP + CMD_DMA_MODE, &regs->command);
regs->command = CMD_NOP + CMD_DMA_MODE;
udelay(1); udelay(1);
eieio(); writeb(CMD_FLUSH, &regs->command);
regs->command = CMD_FLUSH;
udelay(1); udelay(1);
eieio(); writeb(cmd->device->id, &regs->dest_id);
regs->dest_id = cmd->device->id; writeb(0, &regs->sync_period);
regs->sync_period = 0; writeb(0, &regs->sync_offset);
regs->sync_offset = 0;
eieio();
/* load the command into the FIFO */ /* load the command into the FIFO */
for (i = 0; i < cmd->cmd_len; ++i) { for (i = 0; i < cmd->cmd_len; ++i)
regs->fifo = cmd->cmnd[i]; writeb(cmd->cmnd[i], &regs->fifo);
eieio();
}
/* do select without ATN XXX */ /* do select without ATN XXX */
regs->command = CMD_SELECT; writeb(CMD_SELECT, &regs->command);
state->phase = selecting; state->phase = selecting;
if (cmd->use_sg > 0 || cmd->request_bufflen != 0) if (cmd->use_sg > 0 || cmd->request_bufflen != 0)
set_dma_cmds(state, cmd); set_dma_cmds(state, cmd);
} }
static irqreturn_t static irqreturn_t do_mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
do_mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
{ {
unsigned long flags; unsigned long flags;
struct Scsi_Host *dev = ((struct fsc_state *) dev_id)->current_req->device->host; struct Scsi_Host *dev = ((struct fsc_state *) dev_id)->current_req->device->host;
...@@ -328,12 +185,11 @@ do_mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -328,12 +185,11 @@ do_mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void static void mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
{ {
struct fsc_state *state = (struct fsc_state *) dev_id; struct fsc_state *state = (struct fsc_state *) dev_id;
volatile struct mac53c94_regs *regs = state->regs; struct mac53c94_regs *regs = state->regs;
volatile struct dbdma_regs *dma = state->dma; struct dbdma_regs *dma = state->dma;
Scsi_Cmnd *cmd = state->current_req; Scsi_Cmnd *cmd = state->current_req;
int nb, stat, seq, intr; int nb, stat, seq, intr;
static int mac53c94_errors; static int mac53c94_errors;
...@@ -343,9 +199,9 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -343,9 +199,9 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
* Apparently, reading the interrupt register unlatches * Apparently, reading the interrupt register unlatches
* the status and sequence step registers. * the status and sequence step registers.
*/ */
seq = regs->seqstep; seq = readb(&regs->seqstep);
stat = regs->status; stat = readb(&regs->status);
intr = regs->interrupt; intr = readb(&regs->interrupt);
#if 0 #if 0
printk(KERN_DEBUG "mac53c94_intr, intr=%x stat=%x seq=%x phase=%d\n", printk(KERN_DEBUG "mac53c94_intr, intr=%x stat=%x seq=%x phase=%d\n",
...@@ -355,8 +211,8 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -355,8 +211,8 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
if (intr & INTR_RESET) { if (intr & INTR_RESET) {
/* SCSI bus was reset */ /* SCSI bus was reset */
printk(KERN_INFO "external SCSI bus reset detected\n"); printk(KERN_INFO "external SCSI bus reset detected\n");
regs->command = CMD_NOP; writeb(CMD_NOP, &regs->command);
st_le32(&dma->control, RUN << 16); /* stop dma */ writel(RUN << 16, &dma->control); /* stop dma */
cmd_done(state, DID_RESET << 16); cmd_done(state, DID_RESET << 16);
return; return;
} }
...@@ -373,8 +229,7 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -373,8 +229,7 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
intr, stat, seq, state->phase); intr, stat, seq, state->phase);
#endif #endif
++mac53c94_errors; ++mac53c94_errors;
regs->command = CMD_NOP + CMD_DMA_MODE; writeb(CMD_NOP + CMD_DMA_MODE, &regs->command);
eieio();
} }
if (cmd == 0) { if (cmd == 0) {
printk(KERN_DEBUG "53c94: interrupt with no command active?\n"); printk(KERN_DEBUG "53c94: interrupt with no command active?\n");
...@@ -402,7 +257,7 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -402,7 +257,7 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
cmd_done(state, DID_ERROR << 16); cmd_done(state, DID_ERROR << 16);
return; return;
} }
regs->command = CMD_NOP; writeb(CMD_NOP, &regs->command);
/* set DMA controller going if any data to transfer */ /* set DMA controller going if any data to transfer */
if ((stat & (STAT_MSG|STAT_CD)) == 0 if ((stat & (STAT_MSG|STAT_CD)) == 0
&& (cmd->use_sg > 0 || cmd->request_bufflen != 0)) { && (cmd->use_sg > 0 || cmd->request_bufflen != 0)) {
...@@ -410,20 +265,17 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -410,20 +265,17 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
if (nb > 0xfff0) if (nb > 0xfff0)
nb = 0xfff0; nb = 0xfff0;
cmd->SCp.this_residual -= nb; cmd->SCp.this_residual -= nb;
regs->count_lo = nb; writeb(nb, &regs->count_lo);
regs->count_mid = nb >> 8; writeb(nb >> 8, &regs->count_mid);
eieio(); writeb(CMD_DMA_MODE + CMD_NOP, &regs->command);
regs->command = CMD_DMA_MODE + CMD_NOP; writel(virt_to_phys(state->dma_cmds), &dma->cmdptr);
eieio(); writel((RUN << 16) | RUN, &dma->control);
st_le32(&dma->cmdptr, virt_to_phys(state->dma_cmds)); writeb(CMD_DMA_MODE + CMD_XFER_DATA, &regs->command);
st_le32(&dma->control, (RUN << 16) | RUN);
eieio();
regs->command = CMD_DMA_MODE + CMD_XFER_DATA;
state->phase = dataing; state->phase = dataing;
break; break;
} else if ((stat & STAT_PHASE) == STAT_CD + STAT_IO) { } else if ((stat & STAT_PHASE) == STAT_CD + STAT_IO) {
/* up to status phase already */ /* up to status phase already */
regs->command = CMD_I_COMPLETE; writeb(CMD_I_COMPLETE, &regs->command);
state->phase = completing; state->phase = completing;
} else { } else {
printk(KERN_DEBUG "in unexpected phase %x after cmd\n", printk(KERN_DEBUG "in unexpected phase %x after cmd\n",
...@@ -446,18 +298,16 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -446,18 +298,16 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
if (nb > 0xfff0) if (nb > 0xfff0)
nb = 0xfff0; nb = 0xfff0;
cmd->SCp.this_residual -= nb; cmd->SCp.this_residual -= nb;
regs->count_lo = nb; writeb(nb, &regs->count_lo);
regs->count_mid = nb >> 8; writeb(nb >> 8, &regs->count_mid);
eieio(); writeb(CMD_DMA_MODE + CMD_NOP, &regs->command);
regs->command = CMD_DMA_MODE + CMD_NOP; writeb(CMD_DMA_MODE + CMD_XFER_DATA, &regs->command);
eieio();
regs->command = CMD_DMA_MODE + CMD_XFER_DATA;
break; break;
} }
if ((stat & STAT_PHASE) != STAT_CD + STAT_IO) { if ((stat & STAT_PHASE) != STAT_CD + STAT_IO) {
printk(KERN_DEBUG "intr %x before data xfer complete\n", intr); printk(KERN_DEBUG "intr %x before data xfer complete\n", intr);
} }
out_le32(&dma->control, RUN << 16); /* stop dma */ writel(RUN << 16, &dma->control); /* stop dma */
dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
if (cmd->use_sg != 0) { if (cmd->use_sg != 0) {
pci_unmap_sg(state->pdev, pci_unmap_sg(state->pdev,
...@@ -468,7 +318,7 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -468,7 +318,7 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
cmd->request_bufflen, dma_dir); cmd->request_bufflen, dma_dir);
} }
/* should check dma status */ /* should check dma status */
regs->command = CMD_I_COMPLETE; writeb(CMD_I_COMPLETE, &regs->command);
state->phase = completing; state->phase = completing;
break; break;
case completing: case completing:
...@@ -477,10 +327,10 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -477,10 +327,10 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
cmd_done(state, DID_ERROR << 16); cmd_done(state, DID_ERROR << 16);
return; return;
} }
cmd->SCp.Status = regs->fifo; eieio(); cmd->SCp.Status = readb(&regs->fifo);
cmd->SCp.Message = regs->fifo; eieio(); cmd->SCp.Message = readb(&regs->fifo);
cmd->result = cmd->result = CMD_ACCEPT_MSG;
regs->command = CMD_ACCEPT_MSG; writeb(CMD_ACCEPT_MSG, &regs->command);
state->phase = busfreeing; state->phase = busfreeing;
break; break;
case busfreeing: case busfreeing:
...@@ -495,8 +345,7 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -495,8 +345,7 @@ mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
} }
} }
static void static void cmd_done(struct fsc_state *state, int result)
cmd_done(struct fsc_state *state, int result)
{ {
Scsi_Cmnd *cmd; Scsi_Cmnd *cmd;
...@@ -513,8 +362,7 @@ cmd_done(struct fsc_state *state, int result) ...@@ -513,8 +362,7 @@ cmd_done(struct fsc_state *state, int result)
/* /*
* Set up DMA commands for transferring data. * Set up DMA commands for transferring data.
*/ */
static void static void set_dma_cmds(struct fsc_state *state, Scsi_Cmnd *cmd)
set_dma_cmds(struct fsc_state *state, Scsi_Cmnd *cmd)
{ {
int i, dma_cmd, total; int i, dma_cmd, total;
struct scatterlist *scl; struct scatterlist *scl;
...@@ -523,7 +371,8 @@ set_dma_cmds(struct fsc_state *state, Scsi_Cmnd *cmd) ...@@ -523,7 +371,8 @@ set_dma_cmds(struct fsc_state *state, Scsi_Cmnd *cmd)
u32 dma_len; u32 dma_len;
int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
dma_cmd = data_goes_out(cmd)? OUTPUT_MORE: INPUT_MORE; dma_cmd = cmd->sc_data_direction == SCSI_DATA_WRITE? OUTPUT_MORE:
INPUT_MORE;
dcmds = state->dma_cmds; dcmds = state->dma_cmds;
if (cmd->use_sg > 0) { if (cmd->use_sg > 0) {
int nseg; int nseg;
...@@ -562,63 +411,9 @@ set_dma_cmds(struct fsc_state *state, Scsi_Cmnd *cmd) ...@@ -562,63 +411,9 @@ set_dma_cmds(struct fsc_state *state, Scsi_Cmnd *cmd)
cmd->SCp.this_residual = total; cmd->SCp.this_residual = total;
} }
/* static Scsi_Host_Template mac53c94_template = {
* Work out whether data will be going out from the host adaptor or into it.
*/
static int
data_goes_out(Scsi_Cmnd *cmd)
{
switch (cmd->sc_data_direction) {
case SCSI_DATA_WRITE:
return 1;
case SCSI_DATA_READ:
return 0;
}
/* for SCSI_DATA_UNKNOWN or SCSI_DATA_NONE, fall back on the
old method for now... */
switch (cmd->cmnd[0]) {
case CHANGE_DEFINITION:
case COMPARE:
case COPY:
case COPY_VERIFY:
case FORMAT_UNIT:
case LOG_SELECT:
case MEDIUM_SCAN:
case MODE_SELECT:
case MODE_SELECT_10:
case REASSIGN_BLOCKS:
case RESERVE:
case SEARCH_EQUAL:
case SEARCH_EQUAL_12:
case SEARCH_HIGH:
case SEARCH_HIGH_12:
case SEARCH_LOW:
case SEARCH_LOW_12:
case SEND_DIAGNOSTIC:
case SEND_VOLUME_TAG:
case SET_WINDOW:
case UPDATE_BLOCK:
case WRITE_BUFFER:
case WRITE_6:
case WRITE_10:
case WRITE_12:
case WRITE_LONG:
case WRITE_LONG_2: /* alternate code for WRITE_LONG */
case WRITE_SAME:
case WRITE_VERIFY:
case WRITE_VERIFY_12:
return 1;
default:
return 0;
}
}
static Scsi_Host_Template driver_template = {
.proc_name = "53c94", .proc_name = "53c94",
.name = "53C94", .name = "53C94",
.detect = mac53c94_detect,
.release = mac53c94_release,
.queuecommand = mac53c94_queue, .queuecommand = mac53c94_queue,
.eh_abort_handler = mac53c94_abort, .eh_abort_handler = mac53c94_abort,
.eh_host_reset_handler = mac53c94_host_reset, .eh_host_reset_handler = mac53c94_host_reset,
...@@ -629,4 +424,158 @@ static Scsi_Host_Template driver_template = { ...@@ -629,4 +424,158 @@ static Scsi_Host_Template driver_template = {
.use_clustering = DISABLE_CLUSTERING, .use_clustering = DISABLE_CLUSTERING,
}; };
#include "scsi_module.c" static int mac53c94_probe(struct macio_dev *mdev, const struct of_match *match)
{
struct device_node *node = macio_get_of_node(mdev);
struct pci_dev *pdev = macio_get_pci_dev(mdev);
struct fsc_state *state;
struct Scsi_Host *host;
void *dma_cmd_space;
unsigned char *clkprop;
int proplen;
if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) {
printk(KERN_ERR "mac53c94: expected 2 addrs and intrs (got %d/%d)\n",
node->n_addrs, node->n_intrs);
return -ENODEV;
}
if (macio_request_resources(mdev, "mac53c94") != 0) {
printk(KERN_ERR "mac53c94: unable to request memory resources");
return -EBUSY;
}
host = scsi_host_alloc(&mac53c94_template, sizeof(struct fsc_state));
if (host == NULL) {
printk(KERN_ERR "mac53c94: couldn't register host");
goto out_release;
}
state = (struct fsc_state *) host->hostdata;
macio_set_drvdata(mdev, state);
state->host = host;
state->pdev = pdev;
state->mdev = mdev;
state->regs = (struct mac53c94_regs *)
ioremap(macio_resource_start(mdev, 0), 0x1000);
state->intr = macio_irq(mdev, 0);
state->dma = (struct dbdma_regs *)
ioremap(macio_resource_start(mdev, 1), 0x1000);
state->dmaintr = macio_irq(mdev, 1);
if (state->regs == NULL || state->dma == NULL) {
printk(KERN_ERR "mac53c94: ioremap failed for %s\n",
node->full_name);
goto out_free;
}
clkprop = get_property(node, "clock-frequency", &proplen);
if (clkprop == NULL || proplen != sizeof(int)) {
printk(KERN_ERR "%s: can't get clock frequency, "
"assuming 25MHz\n", node->full_name);
state->clk_freq = 25000000;
} else
state->clk_freq = *(int *)clkprop;
/* Space for dma command list: +1 for stop command,
* +1 to allow for aligning.
* XXX FIXME: Use DMA consistent routines
*/
dma_cmd_space = kmalloc((host->sg_tablesize + 2) *
sizeof(struct dbdma_cmd), GFP_KERNEL);
if (dma_cmd_space == 0) {
printk(KERN_ERR "mac53c94: couldn't allocate dma "
"command space for %s\n", node->full_name);
goto out_free;
}
state->dma_cmds = (struct dbdma_cmd *)DBDMA_ALIGN(dma_cmd_space);
memset(state->dma_cmds, 0, (host->sg_tablesize + 1)
* sizeof(struct dbdma_cmd));
state->dma_cmd_space = dma_cmd_space;
mac53c94_init(state);
if (request_irq(state->intr, do_mac53c94_interrupt, 0, "53C94", state)) {
printk(KERN_ERR "mac53C94: can't get irq %d for %s\n",
state->intr, node->full_name);
goto out_free_dma;
}
/* XXX FIXME: handle failure */
scsi_add_host(host, &mdev->ofdev.dev);
scsi_scan_host(host);
return 0;
out_free_dma:
kfree(state->dma_cmd_space);
out_free:
if (state->dma != NULL)
iounmap(state->dma);
if (state->regs != NULL)
iounmap(state->regs);
scsi_host_put(host);
out_release:
macio_release_resources(mdev);
return -ENODEV;
}
static int mac53c94_remove(struct macio_dev *mdev)
{
struct fsc_state *fp = (struct fsc_state *)macio_get_drvdata(mdev);
struct Scsi_Host *host = fp->host;
scsi_remove_host(host);
free_irq(fp->intr, fp);
if (fp->regs)
iounmap((void *) fp->regs);
if (fp->dma)
iounmap((void *) fp->dma);
kfree(fp->dma_cmd_space);
scsi_host_put(host);
macio_release_resources(mdev);
return 0;
}
static struct of_match mac53c94_match[] =
{
{
.name = "53c94",
.type = OF_ANY_MATCH,
.compatible = OF_ANY_MATCH
},
{},
};
static struct macio_driver mac53c94_driver =
{
.name = "mac53c94",
.match_table = mac53c94_match,
.probe = mac53c94_probe,
.remove = mac53c94_remove,
};
static int __init init_mac53c94(void)
{
return macio_register_driver(&mac53c94_driver);
}
static void __exit exit_mac53c94(void)
{
return macio_unregister_driver(&mac53c94_driver);
}
module_init(init_mac53c94);
module_exit(exit_mac53c94);
MODULE_DESCRIPTION("PowerMac 53c94 SCSI driver");
MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
MODULE_LICENSE("GPL");
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