Commit 7ff4c2b9 authored by Christoph Hellwig's avatar Christoph Hellwig

[PATCH] wd33c93 updates

The PC98 folks have some updates in their tree to make the generic
wd33c93 driver usable in PIO mode, but unfortunately the way they do it
(include a header specific to their lowlevel driver in wd33c93.c
conditionally) is rather ugly.

I reworked it to provide different implementations of the access method
inside wd33c93.c independent of the lowlevel driver.  In addition the
patch contains various patches to actually get the driver compile in 2.5
and a reindent to follow kernel codingstyle (sorry, but the maintainer
hasn't touched it for four years and it made my eyes bleed..)
parent 498a7c08
/*
* wd33c93.c - Linux-68k device driver for the Commodore
* Amiga A2091/590 SCSI controller card
*
* Copyright (c) 1996 John Shifflett, GeoLog Consulting
* john@geolog.com
* jshiffle@netcom.com
......@@ -15,8 +12,9 @@
* 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.
*
*
*/
/*
* Drew Eckhardt's excellent 'Generic NCR5380' sources from Linux-PC
* provided much of the inspiration and some of the code for this
* driver. Everything I know about Amiga DMA was gleaned from careful
......@@ -76,38 +74,26 @@
#include <linux/config.h>
#include <linux/module.h>
#include <asm/system.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/version.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <linux/blk.h>
#include <asm/irq.h>
#include "scsi.h"
#include "hosts.h"
#define WD33C93_VERSION "1.25"
#define WD33C93_DATE "09/Jul/1997"
/* NOTE: 1.25 for m68k is related to in2000-1.31 for x86 */
/*
* Note - the following defines have been moved to 'wd33c93.h':
*
* PROC_INTERFACE
* PROC_STATISTICS
* SYNC_DEBUG
* DEBUGGING_ON
* DEBUG_DEFAULTS
*
*/
#include "wd33c93.h"
#define WD33C93_VERSION "1.26"
#define WD33C93_DATE "22/Feb/2003"
MODULE_AUTHOR("John Shifflett");
MODULE_DESCRIPTION("Generic WD33C93 SCSI driver");
MODULE_LICENSE("GPL");
/*
* 'setup_strings' is a single string used to pass operating parameters and
......@@ -163,65 +149,111 @@
*/
/* Normally, no defaults are specified */
static char *setup_args[] =
{"","","","","","","","",""};
/* filled in by 'insmod' */
static char *setup_strings = 0;
static char *setup_args[] = { "", "", "", "", "", "", "", "", "" };
#ifdef MODULE_PARM
static char *setup_strings;
MODULE_PARM(setup_strings, "s");
#endif
static void wd33c93_execute(struct Scsi_Host *instance);
#ifdef CONFIG_WD33C93_PIO
static inline uchar
read_wd33c93(const wd33c93_regs regs, uchar reg_num)
{
uchar data;
static inline uchar read_wd33c93(const wd33c93_regs regs, uchar reg_num)
outb(reg_num, *regs.SASR);
data = inb(*regs.SCMD);
return data;
}
static inline unsigned long
read_wd33c93_count(const wd33c93_regs regs)
{
*regs.SASR = reg_num;
mb();
return(*regs.SCMD);
unsigned long value;
outb(WD_TRANSFER_COUNT_MSB, *regs.SASR);
value = inb(*regs.SCMD) << 16;
value |= inb(*regs.SCMD) << 8;
value |= inb(*regs.SCMD);
return value;
}
static inline uchar
read_aux_stat(const wd33c93_regs regs)
{
return inb(*regs.SASR);
}
#define READ_AUX_STAT() (*regs.SASR)
static inline void
write_wd33c93(const wd33c93_regs regs, uchar reg_num, uchar value)
{
outb(reg_num, *regs.SASR);
outb(value, *regs.SCMD);
}
static inline void
write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
{
outb(WD_TRANSFER_COUNT_MSB, *regs.SASR);
outb((value >> 16) & 0xff, *regs.SCMD);
outb((value >> 8) & 0xff, *regs.SCMD);
outb( value & 0xff, *regs.SCMD);
}
#define write_wd33c93_cmd(regs, cmd) \
write_wd33c93((regs), WD_COMMAND, (cmd))
static inline void write_wd33c93(const wd33c93_regs regs, uchar reg_num,
uchar value)
static inline void
write_wd33c93_cdb(const wd33c93_regs regs, uint len, uchar cmnd[])
{
int i;
outb(WD_CDB_1, *regs.SASR);
for (i=0; i<len; i++)
outb(cmnd[i], *regs.SCMD);
}
#else /* CONFIG_WD33C93_PIO */
static inline uchar
read_wd33c93(const wd33c93_regs regs, uchar reg_num)
{
*regs.SASR = reg_num;
mb();
*regs.SCMD = value;
mb();
return (*regs.SCMD);
}
static inline void write_wd33c93_cmd(const wd33c93_regs regs, uchar cmd)
static unsigned long
read_wd33c93_count(const wd33c93_regs regs)
{
*regs.SASR = WD_COMMAND;
unsigned long value;
*regs.SASR = WD_TRANSFER_COUNT_MSB;
mb();
*regs.SCMD = cmd;
value = *regs.SCMD << 16;
value |= *regs.SCMD << 8;
value |= *regs.SCMD;
mb();
return value;
}
static inline uchar read_1_byte(const wd33c93_regs regs)
static inline uchar
read_aux_stat(const wd33c93_regs regs)
{
uchar asr;
uchar x = 0;
write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
write_wd33c93_cmd(regs, WD_CMD_TRANS_INFO|0x80);
do {
asr = READ_AUX_STAT();
if (asr & ASR_DBR)
x = read_wd33c93(regs, WD_DATA);
} while (!(asr & ASR_INT));
return x;
return *regs.SASR;
}
static inline void
write_wd33c93(const wd33c93_regs regs, uchar reg_num, uchar value)
{
*regs.SASR = reg_num;
mb();
*regs.SCMD = value;
mb();
}
static void write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
static void
write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
{
*regs.SASR = WD_TRANSFER_COUNT_MSB;
mb();
......@@ -231,39 +263,80 @@ static void write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
mb();
}
static unsigned long read_wd33c93_count(const wd33c93_regs regs)
static inline void
write_wd33c93_cmd(const wd33c93_regs regs, uchar cmd)
{
unsigned long value;
*regs.SASR = WD_TRANSFER_COUNT_MSB;
*regs.SASR = WD_COMMAND;
mb();
value = *regs.SCMD << 16;
value |= *regs.SCMD << 8;
value |= *regs.SCMD;
*regs.SCMD = cmd;
mb();
return value;
}
static inline void
write_wd33c93_cdb(const wd33c93_regs regs, uint len, uchar cmnd[])
{
int i;
*regs.SASR = WD_CDB_1;
for (i = 0; i < len; i++)
*regs.SCMD = cmnd[i];
}
#endif /* CONFIG_WD33C93_PIO */
static inline uchar
read_1_byte(const wd33c93_regs regs)
{
uchar asr;
uchar x = 0;
write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
write_wd33c93_cmd(regs, WD_CMD_TRANS_INFO | 0x80);
do {
asr = read_aux_stat(regs);
if (asr & ASR_DBR)
x = read_wd33c93(regs, WD_DATA);
} while (!(asr & ASR_INT));
return x;
}
/* The 33c93 needs to be told which direction a command transfers its
* data; we use this function to figure it out. Returns true if there
* will be a DATA_OUT phase with this command, false otherwise.
* (Thanks to Joerg Dorchain for the research and suggestion.)
*/
static int is_dir_out(Scsi_Cmnd *cmd)
static int
is_dir_out(Scsi_Cmnd * cmd)
{
switch (cmd->cmnd[0]) {
case WRITE_6: case WRITE_10: case WRITE_12:
case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER:
case WRITE_VERIFY: case WRITE_VERIFY_12:
case COMPARE: case COPY: case COPY_VERIFY:
case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12:
case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE:
case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT:
case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK:
case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG:
case WRITE_6:
case WRITE_10:
case WRITE_12:
case WRITE_LONG:
case WRITE_SAME:
case WRITE_BUFFER:
case WRITE_VERIFY:
case WRITE_VERIFY_12:
case COMPARE:
case COPY:
case COPY_VERIFY:
case SEARCH_EQUAL:
case SEARCH_HIGH:
case SEARCH_LOW:
case SEARCH_EQUAL_12:
case SEARCH_HIGH_12:
case SEARCH_LOW_12:
case FORMAT_UNIT:
case REASSIGN_BLOCKS:
case RESERVE:
case MODE_SELECT:
case MODE_SELECT_10:
case LOG_SELECT:
case SEND_DIAGNOSTIC:
case CHANGE_DEFINITION:
case UPDATE_BLOCK:
case SET_WINDOW:
case MEDIUM_SCAN:
case SEND_VOLUME_TAG:
case 0xea:
return 1;
default:
......@@ -271,61 +344,59 @@ static int is_dir_out(Scsi_Cmnd *cmd)
}
}
static struct sx_period sx_table[] = {
{ 1, 0x20},
{1, 0x20},
{252, 0x20},
{376, 0x30},
{500, 0x40},
{624, 0x50},
{752, 0x60},
{876, 0x70},
{1000,0x00},
{0, 0} };
{1000, 0x00},
{0, 0}
};
static int round_period(unsigned int period)
static int
round_period(unsigned int period)
{
int x;
int x;
for (x=1; sx_table[x].period_ns; x++) {
if ((period <= sx_table[x-0].period_ns) &&
(period > sx_table[x-1].period_ns)) {
for (x = 1; sx_table[x].period_ns; x++) {
if ((period <= sx_table[x - 0].period_ns) &&
(period > sx_table[x - 1].period_ns)) {
return x;
}
}
return 7;
}
static uchar calc_sync_xfer(unsigned int period, unsigned int offset)
static uchar
calc_sync_xfer(unsigned int period, unsigned int offset)
{
uchar result;
uchar result;
period *= 4; /* convert SDTR code to ns */
result = sx_table[round_period(period)].reg_value;
result |= (offset < OPTIMUM_SX_OFF)?offset:OPTIMUM_SX_OFF;
result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF;
return result;
}
static void wd33c93_execute(struct Scsi_Host *instance);
int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
int
wd33c93_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
{
struct WD33C93_hostdata *hostdata;
Scsi_Cmnd *tmp;
hostdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata;
DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld( ",cmd->target,cmd->cmnd[0],cmd->pid))
DB(DB_QUEUE_COMMAND,
printk("Q-%d-%02x-%ld( ", cmd->device->id, cmd->cmnd[0], cmd->pid))
/* Set up a few fields in the Scsi_Cmnd structure for our own use:
* - host_scribble is the pointer to the next cmd in the input queue
* - scsi_done points to the routine we call when a cmd is finished
* - result is what you'd expect
*/
cmd->host_scribble = NULL;
cmd->scsi_done = done;
cmd->result = 0;
......@@ -346,16 +417,15 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld( ",cmd->target,cmd->cmnd[0],cmd->pid))
*/
if (cmd->use_sg) {
cmd->SCp.buffer = (struct scatterlist *)cmd->buffer;
cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
cmd->SCp.buffers_residual = cmd->use_sg - 1;
cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+
cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
cmd->SCp.buffer->offset;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
}
else {
} else {
cmd->SCp.buffer = NULL;
cmd->SCp.buffers_residual = 0;
cmd->SCp.ptr = (char *)cmd->request_buffer;
cmd->SCp.ptr = (char *) cmd->request_buffer;
cmd->SCp.this_residual = cmd->request_bufflen;
}
......@@ -387,30 +457,26 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld( ",cmd->target,cmd->cmnd[0],cmd->pid))
spin_lock_irq(&hostdata->lock);
if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
cmd->host_scribble = (uchar *)hostdata->input_Q;
cmd->host_scribble = (uchar *) hostdata->input_Q;
hostdata->input_Q = cmd;
}
else { /* find the end of the queue */
for (tmp=(Scsi_Cmnd *)hostdata->input_Q; tmp->host_scribble;
tmp=(Scsi_Cmnd *)tmp->host_scribble)
;
tmp->host_scribble = (uchar *)cmd;
} else { /* find the end of the queue */
for (tmp = (Scsi_Cmnd *) hostdata->input_Q; tmp->host_scribble;
tmp = (Scsi_Cmnd *) tmp->host_scribble) ;
tmp->host_scribble = (uchar *) cmd;
}
/* We know that there's at least one command in 'input_Q' now.
* Go see if any of them are runnable!
*/
wd33c93_execute(cmd->host);
wd33c93_execute(cmd->device->host);
DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->pid))
spin_unlock_irq(&hostdata->lock);
return 0;
}
/*
* This routine attempts to start a scsi command. If the host_card is
* already connected, we give up immediately. Otherwise, look through
......@@ -421,19 +487,17 @@ DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
* the wd33c93_intr itself, which means that a wd33c93 interrupt
* cannot occur while we are in here.
*/
static void wd33c93_execute (struct Scsi_Host *instance)
static void
wd33c93_execute(struct Scsi_Host *instance)
{
struct WD33C93_hostdata *hostdata = (struct WD33C93_hostdata *)instance->hostdata;
const wd33c93_regs regs = hostdata->regs;
Scsi_Cmnd *cmd, *prev;
int i;
DB(DB_EXECUTE,printk("EX("))
struct WD33C93_hostdata *hostdata =
(struct WD33C93_hostdata *) instance->hostdata;
const wd33c93_regs regs = hostdata->regs;
Scsi_Cmnd *cmd, *prev;
DB(DB_EXECUTE, printk("EX("))
if (hostdata->selecting || hostdata->connected) {
DB(DB_EXECUTE,printk(")EX-0 "))
DB(DB_EXECUTE, printk(")EX-0 "))
return;
}
......@@ -442,21 +506,19 @@ DB(DB_EXECUTE,printk(")EX-0 "))
* for an idle target/lun.
*/
cmd = (Scsi_Cmnd *)hostdata->input_Q;
cmd = (Scsi_Cmnd *) hostdata->input_Q;
prev = 0;
while (cmd) {
if (!(hostdata->busy[cmd->target] & (1 << cmd->lun)))
if (!(hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)))
break;
prev = cmd;
cmd = (Scsi_Cmnd *)cmd->host_scribble;
cmd = (Scsi_Cmnd *) cmd->host_scribble;
}
/* quit if queue empty or all possible targets are busy */
if (!cmd) {
DB(DB_EXECUTE,printk(")EX-1 "))
DB(DB_EXECUTE, printk(")EX-1 "))
return;
}
......@@ -465,10 +527,10 @@ DB(DB_EXECUTE,printk(")EX-1 "))
if (prev)
prev->host_scribble = cmd->host_scribble;
else
hostdata->input_Q = (Scsi_Cmnd *)cmd->host_scribble;
hostdata->input_Q = (Scsi_Cmnd *) cmd->host_scribble;
#ifdef PROC_STATISTICS
hostdata->cmd_cnt[cmd->target]++;
hostdata->cmd_cnt[cmd->device->id]++;
#endif
/*
......@@ -476,9 +538,9 @@ DB(DB_EXECUTE,printk(")EX-1 "))
*/
if (is_dir_out(cmd))
write_wd33c93(regs, WD_DESTINATION_ID, cmd->target);
write_wd33c93(regs, WD_DESTINATION_ID, cmd->device->id);
else
write_wd33c93(regs, WD_DESTINATION_ID, cmd->target | DSTID_DPD);
write_wd33c93(regs, WD_DESTINATION_ID, cmd->device->id | DSTID_DPD);
/* Now we need to figure out whether or not this command is a good
* candidate for disconnect/reselect. We guess to the best of our
......@@ -514,34 +576,37 @@ DB(DB_EXECUTE,printk(")EX-1 "))
goto yes;
if (!(hostdata->input_Q)) /* input_Q empty? */
goto no;
for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev;
prev=(Scsi_Cmnd *)prev->host_scribble) {
if ((prev->target != cmd->target) || (prev->lun != cmd->lun)) {
for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev;
prev=(Scsi_Cmnd *)prev->host_scribble)
for (prev = (Scsi_Cmnd *) hostdata->input_Q; prev;
prev = (Scsi_Cmnd *) prev->host_scribble) {
if ((prev->device->id != cmd->device->id) ||
(prev->device->lun != cmd->device->lun)) {
for (prev = (Scsi_Cmnd *) hostdata->input_Q; prev;
prev = (Scsi_Cmnd *) prev->host_scribble)
prev->SCp.phase = 1;
goto yes;
}
}
goto no;
yes:
yes:
cmd->SCp.phase = 1;
#ifdef PROC_STATISTICS
hostdata->disc_allowed_cnt[cmd->target]++;
hostdata->disc_allowed_cnt[cmd->device->id]++;
#endif
no:
no:
write_wd33c93(regs, WD_SOURCE_ID, ((cmd->SCp.phase)?SRCID_ER:0));
write_wd33c93(regs, WD_SOURCE_ID, ((cmd->SCp.phase) ? SRCID_ER : 0));
write_wd33c93(regs, WD_TARGET_LUN, cmd->lun);
write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]);
hostdata->busy[cmd->target] |= (1 << cmd->lun);
write_wd33c93(regs, WD_TARGET_LUN, cmd->device->lun);
write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
hostdata->sync_xfer[cmd->device->id]);
hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
if ((hostdata->level2 == L2_NONE) ||
(hostdata->sync_stat[cmd->target] == SS_UNSET)) {
(hostdata->sync_stat[cmd->device->id] == SS_UNSET)) {
/*
* Do a 'Select-With-ATN' command. This will end with
......@@ -565,14 +630,12 @@ DB(DB_EXECUTE,printk(")EX-1 "))
* later, but at that time we'll negotiate for async by specifying a
* sync fifo depth of 0.
*/
if (hostdata->sync_stat[cmd->target] == SS_UNSET)
hostdata->sync_stat[cmd->target] = SS_FIRST;
if (hostdata->sync_stat[cmd->device->id] == SS_UNSET)
hostdata->sync_stat[cmd->device->id] = SS_FIRST;
hostdata->state = S_SELECTING;
write_wd33c93_count(regs, 0); /* guarantee a DATA_PHASE interrupt */
write_wd33c93_cmd(regs, WD_CMD_SEL_ATN);
}
else {
} else {
/*
* Do a 'Select-With-ATN-Xfer' command. This will end with
......@@ -589,9 +652,7 @@ DB(DB_EXECUTE,printk(")EX-1 "))
* (take advantage of auto-incrementing)
*/
*regs.SASR = WD_CDB_1;
for (i=0; i<cmd->cmd_len; i++)
*regs.SCMD = cmd->cmnd[i];
write_wd33c93_cdb(regs, cmd->cmd_len, cmd->cmnd);
/* The wd33c93 only knows about Group 0, 1, and 5 commands when
* it's doing a 'select-and-transfer'. To be safe, we write the
......@@ -608,15 +669,17 @@ DB(DB_EXECUTE,printk(")EX-1 "))
if ((cmd->SCp.phase == 0) && (hostdata->no_dma == 0)) {
if (hostdata->dma_setup(cmd,
(is_dir_out(cmd))?DATA_OUT_DIR:DATA_IN_DIR))
(is_dir_out(cmd)) ? DATA_OUT_DIR
: DATA_IN_DIR))
write_wd33c93_count(regs, 0); /* guarantee a DATA_PHASE interrupt */
else {
write_wd33c93_count(regs, cmd->SCp.this_residual);
write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA);
write_wd33c93_count(regs,
cmd->SCp.this_residual);
write_wd33c93(regs, WD_CONTROL,
CTRL_IDI | CTRL_EDI | CTRL_DMA);
hostdata->dma = D_DMA_RUNNING;
}
}
else
} else
write_wd33c93_count(regs, 0); /* guarantee a DATA_PHASE interrupt */
hostdata->state = S_RUNNING_LEVEL2;
......@@ -630,31 +693,31 @@ DB(DB_EXECUTE,printk(")EX-1 "))
* to search the input_Q again...
*/
DB(DB_EXECUTE,printk("%s%ld)EX-2 ",(cmd->SCp.phase)?"d:":"",cmd->pid))
DB(DB_EXECUTE,
printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->pid))
}
static void transfer_pio(const wd33c93_regs regs, uchar *buf, int cnt,
static void
transfer_pio(const wd33c93_regs regs, uchar * buf, int cnt,
int data_in_dir, struct WD33C93_hostdata *hostdata)
{
uchar asr;
uchar asr;
DB(DB_TRANSFER,printk("(%p,%d,%s:",buf,cnt,data_in_dir?"in":"out"))
DB(DB_TRANSFER,
printk("(%p,%d,%s:", buf, cnt, data_in_dir ? "in" : "out"))
write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
write_wd33c93_count(regs, cnt);
write_wd33c93_cmd(regs, WD_CMD_TRANS_INFO);
if (data_in_dir) {
do {
asr = READ_AUX_STAT();
asr = read_aux_stat(regs);
if (asr & ASR_DBR)
*buf++ = read_wd33c93(regs, WD_DATA);
} while (!(asr & ASR_INT));
}
else {
} else {
do {
asr = READ_AUX_STAT();
asr = read_aux_stat(regs);
if (asr & ASR_DBR)
write_wd33c93(regs, WD_DATA, *buf++);
} while (!(asr & ASR_INT));
......@@ -669,15 +732,13 @@ DB(DB_TRANSFER,printk("(%p,%d,%s:",buf,cnt,data_in_dir?"in":"out"))
}
static void transfer_bytes(const wd33c93_regs regs, Scsi_Cmnd *cmd,
int data_in_dir)
static void
transfer_bytes(const wd33c93_regs regs, Scsi_Cmnd * cmd, int data_in_dir)
{
struct WD33C93_hostdata *hostdata;
unsigned long length;
struct WD33C93_hostdata *hostdata;
unsigned long length;
hostdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata;
/* Normally, you'd expect 'this_residual' to be non-zero here.
* In a series of scatter-gather transfers, however, this
......@@ -691,30 +752,23 @@ unsigned long length;
++cmd->SCp.buffer;
--cmd->SCp.buffers_residual;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+
cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
cmd->SCp.buffer->offset;
}
write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]);
write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
hostdata->sync_xfer[cmd->device->id]);
/* 'hostdata->no_dma' is TRUE if we don't even want to try DMA.
* Update 'this_residual' and 'ptr' after 'transfer_pio()' returns.
*/
if (hostdata->no_dma)
goto use_transfer_pio;
/* 'dma_setup()' will return TRUE if we can't do DMA.
* Update 'this_residual' and 'ptr' after 'transfer_pio()' returns.
*/
else if (hostdata->dma_setup(cmd, data_in_dir)) {
use_transfer_pio:
if (hostdata->no_dma || hostdata->dma_setup(cmd, data_in_dir)) {
#ifdef PROC_STATISTICS
hostdata->pio_cnt++;
#endif
transfer_pio(regs, (uchar *)cmd->SCp.ptr, cmd->SCp.this_residual,
data_in_dir, hostdata);
transfer_pio(regs, (uchar *) cmd->SCp.ptr,
cmd->SCp.this_residual, data_in_dir, hostdata);
length = cmd->SCp.this_residual;
cmd->SCp.this_residual = read_wd33c93_count(regs);
cmd->SCp.ptr += (length - cmd->SCp.this_residual);
......@@ -741,25 +795,24 @@ unsigned long length;
write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);
write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
hostdata->state = S_RUNNING_LEVEL2;
}
else
} else
write_wd33c93_cmd(regs, WD_CMD_TRANS_INFO);
hostdata->dma = D_DMA_RUNNING;
}
}
void wd33c93_intr (struct Scsi_Host *instance)
void
wd33c93_intr(struct Scsi_Host *instance)
{
struct WD33C93_hostdata *hostdata = (struct WD33C93_hostdata *)instance->hostdata;
const wd33c93_regs regs = hostdata->regs;
Scsi_Cmnd *patch, *cmd;
uchar asr, sr, phs, id, lun, *ucp, msg;
unsigned long length, flags;
asr = READ_AUX_STAT();
struct WD33C93_hostdata *hostdata =
(struct WD33C93_hostdata *) instance->hostdata;
const wd33c93_regs regs = hostdata->regs;
Scsi_Cmnd *patch, *cmd;
uchar asr, sr, phs, id, lun, *ucp, msg;
unsigned long length, flags;
asr = read_aux_stat(regs);
if (!(asr & ASR_INT) || (asr & ASR_BSY))
return;
......@@ -769,11 +822,11 @@ unsigned long length, flags;
hostdata->int_cnt++;
#endif
cmd = (Scsi_Cmnd *)hostdata->connected; /* assume we're connected */
cmd = (Scsi_Cmnd *) hostdata->connected; /* assume we're connected */
sr = read_wd33c93(regs, WD_SCSI_STATUS); /* clear the interrupt */
phs = read_wd33c93(regs, WD_COMMAND_PHASE);
DB(DB_INTR,printk("{%02x:%02x-",asr,sr))
DB(DB_INTR, printk("{%02x:%02x-", asr, sr))
/* After starting a DMA transfer, the next interrupt
* is guaranteed to be in response to completion of
......@@ -789,33 +842,32 @@ DB(DB_INTR,printk("{%02x:%02x-",asr,sr))
* whatever is needed, we go on and service the WD3393
* interrupt normally.
*/
if (hostdata->dma == D_DMA_RUNNING) {
DB(DB_TRANSFER,printk("[%p/%d:",cmd->SCp.ptr,cmd->SCp.this_residual))
hostdata->dma_stop(cmd->host, cmd, 1);
DB(DB_TRANSFER,
printk("[%p/%d:", cmd->SCp.ptr, cmd->SCp.this_residual))
hostdata->dma_stop(cmd->device->host, cmd, 1);
hostdata->dma = D_DMA_OFF;
length = cmd->SCp.this_residual;
cmd->SCp.this_residual = read_wd33c93_count(regs);
cmd->SCp.ptr += (length - cmd->SCp.this_residual);
DB(DB_TRANSFER,printk("%p/%d]",cmd->SCp.ptr,cmd->SCp.this_residual))
DB(DB_TRANSFER,
printk("%p/%d]", cmd->SCp.ptr, cmd->SCp.this_residual))
}
/* Respond to the specific WD3393 interrupt - there are quite a few! */
switch (sr) {
case CSR_TIMEOUT:
DB(DB_INTR,printk("TIMEOUT"))
DB(DB_INTR, printk("TIMEOUT"))
if (hostdata->state == S_RUNNING_LEVEL2)
hostdata->connected = NULL;
else {
cmd = (Scsi_Cmnd *)hostdata->selecting; /* get a valid cmd */
cmd = (Scsi_Cmnd *) hostdata->selecting; /* get a valid cmd */
hostdata->selecting = NULL;
}
cmd->result = DID_NO_CONNECT << 16;
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
hostdata->state = S_UNCONNECTED;
cmd->scsi_done(cmd);
......@@ -838,27 +890,26 @@ DB(DB_INTR,printk("TIMEOUT"))
wd33c93_execute(instance);
break;
/* Note: this interrupt should not occur in a LEVEL2 command */
case CSR_SELECT:
DB(DB_INTR,printk("SELECT"))
hostdata->connected = cmd = (Scsi_Cmnd *)hostdata->selecting;
DB(DB_INTR, printk("SELECT"))
hostdata->connected = cmd =
(Scsi_Cmnd *) hostdata->selecting;
hostdata->selecting = NULL;
/* construct an IDENTIFY message with correct disconnect bit */
hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->lun);
hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->device->lun);
if (cmd->SCp.phase)
hostdata->outgoing_msg[0] |= 0x40;
if (hostdata->sync_stat[cmd->target] == SS_FIRST) {
if (hostdata->sync_stat[cmd->device->id] == SS_FIRST) {
#ifdef SYNC_DEBUG
printk(" sending SDTR ");
printk(" sending SDTR ");
#endif
hostdata->sync_stat[cmd->target] = SS_WAITING;
hostdata->sync_stat[cmd->device->id] = SS_WAITING;
/* Tack on a 2nd message to ask about synchronous transfers. If we've
* been asked to do only asynchronous transfers on this device, we
......@@ -869,82 +920,79 @@ printk(" sending SDTR ");
hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;
hostdata->outgoing_msg[2] = 3;
hostdata->outgoing_msg[3] = EXTENDED_SDTR;
if (hostdata->no_sync & (1 << cmd->target)) {
hostdata->outgoing_msg[4] = hostdata->default_sx_per/4;
if (hostdata->no_sync & (1 << cmd->device->id)) {
hostdata->outgoing_msg[4] =
hostdata->default_sx_per / 4;
hostdata->outgoing_msg[5] = 0;
}
else {
hostdata->outgoing_msg[4] = OPTIMUM_SX_PER/4;
} else {
hostdata->outgoing_msg[4] = OPTIMUM_SX_PER / 4;
hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;
}
hostdata->outgoing_len = 6;
}
else
} else
hostdata->outgoing_len = 1;
hostdata->state = S_CONNECTED;
spin_unlock_irqrestore(&hostdata->lock, flags);
break;
case CSR_XFER_DONE|PHS_DATA_IN:
case CSR_UNEXP |PHS_DATA_IN:
case CSR_SRV_REQ |PHS_DATA_IN:
DB(DB_INTR,printk("IN-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
case CSR_XFER_DONE | PHS_DATA_IN:
case CSR_UNEXP | PHS_DATA_IN:
case CSR_SRV_REQ | PHS_DATA_IN:
DB(DB_INTR,
printk("IN-%d.%d", cmd->SCp.this_residual,
cmd->SCp.buffers_residual))
transfer_bytes(regs, cmd, DATA_IN_DIR);
if (hostdata->state != S_RUNNING_LEVEL2)
hostdata->state = S_CONNECTED;
spin_unlock_irqrestore(&hostdata->lock, flags);
break;
case CSR_XFER_DONE|PHS_DATA_OUT:
case CSR_UNEXP |PHS_DATA_OUT:
case CSR_SRV_REQ |PHS_DATA_OUT:
DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
case CSR_XFER_DONE | PHS_DATA_OUT:
case CSR_UNEXP | PHS_DATA_OUT:
case CSR_SRV_REQ | PHS_DATA_OUT:
DB(DB_INTR,
printk("OUT-%d.%d", cmd->SCp.this_residual,
cmd->SCp.buffers_residual))
transfer_bytes(regs, cmd, DATA_OUT_DIR);
if (hostdata->state != S_RUNNING_LEVEL2)
hostdata->state = S_CONNECTED;
spin_unlock_irqrestore(&hostdata->lock, flags);
break;
/* Note: this interrupt should not occur in a LEVEL2 command */
case CSR_XFER_DONE|PHS_COMMAND:
case CSR_UNEXP |PHS_COMMAND:
case CSR_SRV_REQ |PHS_COMMAND:
DB(DB_INTR,printk("CMND-%02x,%ld",cmd->cmnd[0],cmd->pid))
transfer_pio(regs, cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata);
case CSR_XFER_DONE | PHS_COMMAND:
case CSR_UNEXP | PHS_COMMAND:
case CSR_SRV_REQ | PHS_COMMAND:
DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->pid))
transfer_pio(regs, cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR,
hostdata);
hostdata->state = S_CONNECTED;
spin_unlock_irqrestore(&hostdata->lock, flags);
break;
case CSR_XFER_DONE|PHS_STATUS:
case CSR_UNEXP |PHS_STATUS:
case CSR_SRV_REQ |PHS_STATUS:
DB(DB_INTR,printk("STATUS="))
case CSR_XFER_DONE | PHS_STATUS:
case CSR_UNEXP | PHS_STATUS:
case CSR_SRV_REQ | PHS_STATUS:
DB(DB_INTR, printk("STATUS="))
cmd->SCp.Status = read_1_byte(regs);
DB(DB_INTR,printk("%02x",cmd->SCp.Status))
DB(DB_INTR, printk("%02x", cmd->SCp.Status))
if (hostdata->level2 >= L2_BASIC) {
sr = read_wd33c93(regs, WD_SCSI_STATUS); /* clear interrupt */
hostdata->state = S_RUNNING_LEVEL2;
write_wd33c93(regs, WD_COMMAND_PHASE, 0x50);
write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
}
else {
} else {
hostdata->state = S_CONNECTED;
}
spin_unlock_irqrestore(&hostdata->lock, flags);
break;
case CSR_XFER_DONE|PHS_MESS_IN:
case CSR_UNEXP |PHS_MESS_IN:
case CSR_SRV_REQ |PHS_MESS_IN:
DB(DB_INTR,printk("MSG_IN="))
case CSR_XFER_DONE | PHS_MESS_IN:
case CSR_UNEXP | PHS_MESS_IN:
case CSR_SRV_REQ | PHS_MESS_IN:
DB(DB_INTR, printk("MSG_IN="))
msg = read_1_byte(regs);
sr = read_wd33c93(regs, WD_SCSI_STATUS); /* clear interrupt */
......@@ -959,55 +1007,54 @@ DB(DB_INTR,printk("MSG_IN="))
switch (msg) {
case COMMAND_COMPLETE:
DB(DB_INTR,printk("CCMP-%ld",cmd->pid))
DB(DB_INTR, printk("CCMP-%ld", cmd->pid))
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
hostdata->state = S_PRE_CMP_DISC;
break;
case SAVE_POINTERS:
DB(DB_INTR,printk("SDP"))
DB(DB_INTR, printk("SDP"))
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
hostdata->state = S_CONNECTED;
break;
case RESTORE_POINTERS:
DB(DB_INTR,printk("RDP"))
DB(DB_INTR, printk("RDP"))
if (hostdata->level2 >= L2_BASIC) {
write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);
write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
hostdata->state = S_RUNNING_LEVEL2;
}
else {
} else {
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
hostdata->state = S_CONNECTED;
}
break;
case DISCONNECT:
DB(DB_INTR,printk("DIS"))
DB(DB_INTR, printk("DIS"))
cmd->device->disconnect = 1;
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
hostdata->state = S_PRE_TMP_DISC;
break;
case MESSAGE_REJECT:
DB(DB_INTR,printk("REJ"))
DB(DB_INTR, printk("REJ"))
#ifdef SYNC_DEBUG
printk("-REJ-");
printk("-REJ-");
#endif
if (hostdata->sync_stat[cmd->target] == SS_WAITING)
hostdata->sync_stat[cmd->target] = SS_SET;
if (hostdata->sync_stat[cmd->device->id] == SS_WAITING)
hostdata->sync_stat[cmd->device->id] = SS_SET;
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
hostdata->state = S_CONNECTED;
break;
case EXTENDED_MESSAGE:
DB(DB_INTR,printk("EXT"))
DB(DB_INTR, printk("EXT"))
ucp = hostdata->incoming_msg;
#ifdef SYNC_DEBUG
printk("%02x",ucp[hostdata->incoming_ptr]);
printk("%02x", ucp[hostdata->incoming_ptr]);
#endif
/* Is this the last byte of the extended message? */
......@@ -1016,8 +1063,9 @@ printk("%02x",ucp[hostdata->incoming_ptr]);
switch (ucp[2]) { /* what's the EXTENDED code? */
case EXTENDED_SDTR:
id = calc_sync_xfer(ucp[3],ucp[4]);
if (hostdata->sync_stat[cmd->target] != SS_WAITING) {
id = calc_sync_xfer(ucp[3], ucp[4]);
if (hostdata->sync_stat[cmd->device->id] !=
SS_WAITING) {
/* A device has sent an unsolicited SDTR message; rather than go
* through the effort of decoding it and then figuring out what
......@@ -1029,42 +1077,57 @@ printk("%02x",ucp[hostdata->incoming_ptr]);
*/
write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN); /* want MESS_OUT */
hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
hostdata->outgoing_msg[0] =
EXTENDED_MESSAGE;
hostdata->outgoing_msg[1] = 3;
hostdata->outgoing_msg[2] = EXTENDED_SDTR;
hostdata->outgoing_msg[3] = hostdata->default_sx_per/4;
hostdata->outgoing_msg[2] =
EXTENDED_SDTR;
hostdata->outgoing_msg[3] =
hostdata->default_sx_per /
4;
hostdata->outgoing_msg[4] = 0;
hostdata->outgoing_len = 5;
hostdata->sync_xfer[cmd->target] =
calc_sync_xfer(hostdata->default_sx_per/4,0);
}
else {
hostdata->sync_xfer[cmd->target] = id;
hostdata->sync_xfer[cmd->device->id] =
calc_sync_xfer(hostdata->
default_sx_per
/ 4, 0);
} else {
hostdata->sync_xfer[cmd->device->id] = id;
}
#ifdef SYNC_DEBUG
printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);
printk("sync_xfer=%02x",
hostdata->sync_xfer[cmd->device->id]);
#endif
hostdata->sync_stat[cmd->target] = SS_SET;
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
hostdata->sync_stat[cmd->device->id] =
SS_SET;
write_wd33c93_cmd(regs,
WD_CMD_NEGATE_ACK);
hostdata->state = S_CONNECTED;
break;
case EXTENDED_WDTR:
write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN); /* want MESS_OUT */
printk("sending WDTR ");
hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
hostdata->outgoing_msg[0] =
EXTENDED_MESSAGE;
hostdata->outgoing_msg[1] = 2;
hostdata->outgoing_msg[2] = EXTENDED_WDTR;
hostdata->outgoing_msg[2] =
EXTENDED_WDTR;
hostdata->outgoing_msg[3] = 0; /* 8 bit transfer width */
hostdata->outgoing_len = 4;
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
write_wd33c93_cmd(regs,
WD_CMD_NEGATE_ACK);
hostdata->state = S_CONNECTED;
break;
default:
write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN); /* want MESS_OUT */
printk("Rejecting Unknown Extended Message(%02x). ",ucp[2]);
hostdata->outgoing_msg[0] = MESSAGE_REJECT;
printk
("Rejecting Unknown Extended Message(%02x). ",
ucp[2]);
hostdata->outgoing_msg[0] =
MESSAGE_REJECT;
hostdata->outgoing_len = 1;
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
write_wd33c93_cmd(regs,
WD_CMD_NEGATE_ACK);
hostdata->state = S_CONNECTED;
break;
}
......@@ -1081,7 +1144,7 @@ printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);
break;
default:
printk("Rejecting Unknown Message(%02x) ",msg);
printk("Rejecting Unknown Message(%02x) ", msg);
write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN); /* want MESS_OUT */
hostdata->outgoing_msg[0] = MESSAGE_REJECT;
hostdata->outgoing_len = 1;
......@@ -1091,7 +1154,6 @@ printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);
spin_unlock_irqrestore(&hostdata->lock, flags);
break;
/* Note: this interrupt will occur only after a LEVEL2 command */
case CSR_SEL_XFER_DONE:
......@@ -1102,19 +1164,23 @@ printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);
write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);
if (phs == 0x60) {
DB(DB_INTR,printk("SX-DONE-%ld",cmd->pid))
DB(DB_INTR, printk("SX-DONE-%ld", cmd->pid))
cmd->SCp.Message = COMMAND_COMPLETE;
lun = read_wd33c93(regs, WD_TARGET_LUN);
DB(DB_INTR,printk(":%d.%d",cmd->SCp.Status,lun))
DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun))
hostdata->connected = NULL;
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
hostdata->state = S_UNCONNECTED;
if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE)
cmd->SCp.Status = lun;
if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)
cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
if (cmd->cmnd[0] == REQUEST_SENSE
&& cmd->SCp.Status != GOOD)
cmd->result =
(cmd->
result & 0x00ffff) | (DID_ERROR << 16);
else
cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
cmd->result =
cmd->SCp.Status | (cmd->SCp.Message << 8);
cmd->scsi_done(cmd);
/* We are no longer connected to a target - check to see if
......@@ -1122,29 +1188,28 @@ DB(DB_INTR,printk(":%d.%d",cmd->SCp.Status,lun))
*/
spin_unlock_irqrestore(&hostdata->lock, flags);
wd33c93_execute(instance);
}
else {
printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---",asr,sr,phs,cmd->pid);
} else {
printk
("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---",
asr, sr, phs, cmd->pid);
spin_unlock_irqrestore(&hostdata->lock, flags);
}
break;
/* Note: this interrupt will occur only after a LEVEL2 command */
case CSR_SDP:
DB(DB_INTR,printk("SDP"))
DB(DB_INTR, printk("SDP"))
hostdata->state = S_RUNNING_LEVEL2;
write_wd33c93(regs, WD_COMMAND_PHASE, 0x41);
write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
spin_unlock_irqrestore(&hostdata->lock, flags);
break;
case CSR_XFER_DONE|PHS_MESS_OUT:
case CSR_UNEXP |PHS_MESS_OUT:
case CSR_SRV_REQ |PHS_MESS_OUT:
DB(DB_INTR,printk("MSG_OUT="))
case CSR_XFER_DONE | PHS_MESS_OUT:
case CSR_UNEXP | PHS_MESS_OUT:
case CSR_SRV_REQ | PHS_MESS_OUT:
DB(DB_INTR, printk("MSG_OUT="))
/* To get here, we've probably requested MESSAGE_OUT and have
* already put the correct bytes in outgoing_msg[] and filled
......@@ -1158,20 +1223,18 @@ DB(DB_INTR,printk("MSG_OUT="))
* NOP messages in these situations results in no harm and
* makes everyone happy.
*/
if (hostdata->outgoing_len == 0) {
hostdata->outgoing_len = 1;
hostdata->outgoing_msg[0] = NOP;
}
transfer_pio(regs, hostdata->outgoing_msg, hostdata->outgoing_len,
DATA_OUT_DIR, hostdata);
DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
transfer_pio(regs, hostdata->outgoing_msg,
hostdata->outgoing_len, DATA_OUT_DIR, hostdata);
DB(DB_INTR, printk("%02x", hostdata->outgoing_msg[0]))
hostdata->outgoing_len = 0;
hostdata->state = S_CONNECTED;
spin_unlock_irqrestore(&hostdata->lock, flags);
break;
case CSR_UNEXP_DISC:
/* I think I've seen this after a request-sense that was in response
......@@ -1193,12 +1256,13 @@ DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
spin_unlock_irqrestore(&hostdata->lock, flags);
return;
}
DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->pid))
hostdata->connected = NULL;
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
hostdata->state = S_UNCONNECTED;
if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)
cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
cmd->result =
(cmd->result & 0x00ffff) | (DID_ERROR << 16);
else
cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
cmd->scsi_done(cmd);
......@@ -1211,7 +1275,6 @@ DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
wd33c93_execute(instance);
break;
case CSR_DISC:
/* Make sure that reselection is enabled at this point - it may
......@@ -1219,7 +1282,7 @@ DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
*/
write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);
DB(DB_INTR,printk("DISC-%ld",cmd->pid))
DB(DB_INTR, printk("DISC-%ld", cmd->pid))
if (cmd == NULL) {
printk(" - Already disconnected! ");
hostdata->state = S_UNCONNECTED;
......@@ -1227,24 +1290,28 @@ DB(DB_INTR,printk("DISC-%ld",cmd->pid))
switch (hostdata->state) {
case S_PRE_CMP_DISC:
hostdata->connected = NULL;
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
hostdata->state = S_UNCONNECTED;
DB(DB_INTR,printk(":%d",cmd->SCp.Status))
if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)
cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
DB(DB_INTR, printk(":%d", cmd->SCp.Status))
if (cmd->cmnd[0] == REQUEST_SENSE
&& cmd->SCp.Status != GOOD)
cmd->result =
(cmd->
result & 0x00ffff) | (DID_ERROR << 16);
else
cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
cmd->result =
cmd->SCp.Status | (cmd->SCp.Message << 8);
cmd->scsi_done(cmd);
break;
case S_PRE_TMP_DISC:
case S_RUNNING_LEVEL2:
cmd->host_scribble = (uchar *)hostdata->disconnected_Q;
cmd->host_scribble = (uchar *) hostdata->disconnected_Q;
hostdata->disconnected_Q = cmd;
hostdata->connected = NULL;
hostdata->state = S_UNCONNECTED;
#ifdef PROC_STATISTICS
hostdata->disc_done_cnt[cmd->target]++;
hostdata->disc_done_cnt[cmd->device->id]++;
#endif
break;
......@@ -1260,10 +1327,9 @@ DB(DB_INTR,printk(":%d",cmd->SCp.Status))
wd33c93_execute(instance);
break;
case CSR_RESEL_AM:
case CSR_RESEL:
DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
DB(DB_INTR, printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
/* Old chips (pre -A ???) don't have advanced features and will
* generate CSR_RESEL. In that case we have to extract the LUN the
......@@ -1272,14 +1338,14 @@ DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
* happen during Arbitration/Selection of some other device.
* If yes, put losing command back on top of input_Q.
*/
if (hostdata->level2 <= L2_NONE) {
if (hostdata->selecting) {
cmd = (Scsi_Cmnd *)hostdata->selecting;
cmd = (Scsi_Cmnd *) hostdata->selecting;
hostdata->selecting = NULL;
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
cmd->host_scribble = (uchar *)hostdata->input_Q;
hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
cmd->host_scribble =
(uchar *) hostdata->input_Q;
hostdata->input_Q = cmd;
}
}
......@@ -1288,12 +1354,15 @@ DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
if (cmd) {
if (phs == 0x00) {
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
cmd->host_scribble = (uchar *)hostdata->input_Q;
hostdata->busy[cmd->device->id] &=
~(1 << cmd->device->lun);
cmd->host_scribble =
(uchar *) hostdata->input_Q;
hostdata->input_Q = cmd;
}
else {
printk("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",asr,sr,phs);
} else {
printk
("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",
asr, sr, phs);
while (1)
printk("\r");
}
......@@ -1316,19 +1385,18 @@ DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
if (hostdata->level2 < L2_RESELECT)
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
lun &= 7;
}
else {
} else {
/* Old chip; wait for msgin phase to pick up the LUN. */
for (lun = 255; lun; lun--) {
if ((asr = READ_AUX_STAT()) & ASR_INT)
if ((asr = read_aux_stat(regs)) & ASR_INT)
break;
udelay(10);
}
if (!(asr & ASR_INT)) {
printk("wd33c93: Reselected without IDENTIFY\n");
printk
("wd33c93: Reselected without IDENTIFY\n");
lun = 0;
}
else {
} else {
/* Verify this is a change to MSG_IN and read the message */
sr = read_wd33c93(regs, WD_SCSI_STATUS);
if (sr == (CSR_ABORT | PHS_MESS_IN) ||
......@@ -1337,23 +1405,27 @@ DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
/* Got MSG_IN, grab target LUN */
lun = read_1_byte(regs);
/* Now we expect a 'paused with ACK asserted' int.. */
asr = READ_AUX_STAT();
asr = read_aux_stat(regs);
if (!(asr & ASR_INT)) {
udelay(10);
asr = READ_AUX_STAT();
asr = read_aux_stat(regs);
if (!(asr & ASR_INT))
printk("wd33c93: No int after LUN on RESEL (%02x)\n",
printk
("wd33c93: No int after LUN on RESEL (%02x)\n",
asr);
}
sr = read_wd33c93(regs, WD_SCSI_STATUS);
if (sr != CSR_MSGIN)
printk("wd33c93: Not paused with ACK on RESEL (%02x)\n",
printk
("wd33c93: Not paused with ACK on RESEL (%02x)\n",
sr);
lun &= 7;
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
}
else {
printk("wd33c93: Not MSG_IN on reselect (%02x)\n", sr);
write_wd33c93_cmd(regs,
WD_CMD_NEGATE_ACK);
} else {
printk
("wd33c93: Not MSG_IN on reselect (%02x)\n",
sr);
lun = 0;
}
}
......@@ -1361,19 +1433,21 @@ DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
/* Now we look for the command that's reconnecting. */
cmd = (Scsi_Cmnd *)hostdata->disconnected_Q;
cmd = (Scsi_Cmnd *) hostdata->disconnected_Q;
patch = NULL;
while (cmd) {
if (id == cmd->target && lun == cmd->lun)
if (id == cmd->device->id && lun == cmd->device->lun)
break;
patch = cmd;
cmd = (Scsi_Cmnd *)cmd->host_scribble;
cmd = (Scsi_Cmnd *) cmd->host_scribble;
}
/* Hmm. Couldn't find a valid command.... What to do? */
if (!cmd) {
printk("---TROUBLE: target %d.%d not in disconnect queue---",id,lun);
printk
("---TROUBLE: target %d.%d not in disconnect queue---",
id, lun);
spin_unlock_irqrestore(&hostdata->lock, flags);
return;
}
......@@ -1383,7 +1457,8 @@ DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
if (patch)
patch->host_scribble = cmd->host_scribble;
else
hostdata->disconnected_Q = (Scsi_Cmnd *)cmd->host_scribble;
hostdata->disconnected_Q =
(Scsi_Cmnd *) cmd->host_scribble;
hostdata->connected = cmd;
/* We don't need to worry about 'initialize_SCp()' or 'hostdata->busy[]'
......@@ -1392,50 +1467,52 @@ DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
*/
if (is_dir_out(cmd))
write_wd33c93(regs, WD_DESTINATION_ID, cmd->target);
write_wd33c93(regs, WD_DESTINATION_ID, cmd->device->id);
else
write_wd33c93(regs, WD_DESTINATION_ID, cmd->target | DSTID_DPD);
write_wd33c93(regs, WD_DESTINATION_ID,
cmd->device->id | DSTID_DPD);
if (hostdata->level2 >= L2_RESELECT) {
write_wd33c93_count(regs, 0); /* we want a DATA_PHASE interrupt */
write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);
write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
hostdata->state = S_RUNNING_LEVEL2;
}
else
} else
hostdata->state = S_CONNECTED;
DB(DB_INTR,printk("-%ld",cmd->pid))
DB(DB_INTR, printk("-%ld", cmd->pid))
spin_unlock_irqrestore(&hostdata->lock, flags);
break;
default:
printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--",asr,sr,phs);
printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--", asr, sr, phs);
spin_unlock_irqrestore(&hostdata->lock, flags);
}
DB(DB_INTR,printk("} "))
DB(DB_INTR, printk("} "))
}
static void reset_wd33c93(struct Scsi_Host *instance)
static void
reset_wd33c93(struct Scsi_Host *instance)
{
struct WD33C93_hostdata *hostdata = (struct WD33C93_hostdata *)instance->hostdata;
const wd33c93_regs regs = hostdata->regs;
uchar sr;
struct WD33C93_hostdata *hostdata =
(struct WD33C93_hostdata *) instance->hostdata;
const wd33c93_regs regs = hostdata->regs;
uchar sr;
write_wd33c93(regs, WD_OWN_ID, OWNID_EAF | OWNID_RAF |
instance->this_id | hostdata->clock_freq);
write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF));
calc_sync_xfer(hostdata->default_sx_per / 4,
DEFAULT_SX_OFF));
write_wd33c93(regs, WD_COMMAND, WD_CMD_RESET);
#ifdef CONFIG_MVME147_SCSI
udelay(25); /* The old wd33c93 on MVME147 needs this, at least */
#endif
while (!(READ_AUX_STAT() & ASR_INT))
while (!(read_aux_stat(regs) & ASR_INT))
;
sr = read_wd33c93(regs, WD_SCSI_STATUS);
......@@ -1448,35 +1525,33 @@ uchar sr;
if (sr == 0xa5) {
hostdata->chip = C_WD33C93B;
write_wd33c93(regs, WD_QUEUE_TAG, 0);
}
else
} else
hostdata->chip = C_WD33C93A;
}
else
} else
hostdata->chip = C_UNKNOWN_CHIP;
write_wd33c93(regs, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
}
int wd33c93_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
int
wd33c93_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
{
struct Scsi_Host *instance;
struct WD33C93_hostdata *hostdata;
int i;
struct Scsi_Host *instance;
struct WD33C93_hostdata *hostdata;
int i;
instance = SCpnt->host;
hostdata = (struct WD33C93_hostdata *)instance->hostdata;
instance = SCpnt->device->host;
hostdata = (struct WD33C93_hostdata *) instance->hostdata;
printk("scsi%d: reset. ", instance->host_no);
disable_irq(instance->irq);
((struct WD33C93_hostdata *)instance->hostdata)->dma_stop(instance,NULL,0);
hostdata->dma_stop(instance, NULL, 0);
for (i = 0; i < 8; i++) {
hostdata->busy[i] = 0;
hostdata->sync_xfer[i] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF);
hostdata->sync_xfer[i] =
calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF);
hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */
}
hostdata->input_Q = NULL;
......@@ -1494,19 +1569,18 @@ int i;
return 0;
}
int wd33c93_abort (Scsi_Cmnd *cmd)
int
wd33c93_abort(Scsi_Cmnd * cmd)
{
struct Scsi_Host *instance;
struct WD33C93_hostdata *hostdata;
wd33c93_regs regs;
Scsi_Cmnd *tmp, *prev;
struct Scsi_Host *instance;
struct WD33C93_hostdata *hostdata;
wd33c93_regs regs;
Scsi_Cmnd *tmp, *prev;
disable_irq(cmd->host->irq);
disable_irq(cmd->device->host->irq);
instance = cmd->host;
hostdata = (struct WD33C93_hostdata *)instance->hostdata;
instance = cmd->device->host;
hostdata = (struct WD33C93_hostdata *) instance->hostdata;
regs = hostdata->regs;
/*
......@@ -1514,24 +1588,26 @@ Scsi_Cmnd *tmp, *prev;
* from the input_Q.
*/
tmp = (Scsi_Cmnd *)hostdata->input_Q;
tmp = (Scsi_Cmnd *) hostdata->input_Q;
prev = 0;
while (tmp) {
if (tmp == cmd) {
if (prev)
prev->host_scribble = cmd->host_scribble;
else
hostdata->input_Q = (Scsi_Cmnd *)cmd->host_scribble;
hostdata->input_Q =
(Scsi_Cmnd *) cmd->host_scribble;
cmd->host_scribble = NULL;
cmd->result = DID_ABORT << 16;
printk("scsi%d: Abort - removing command %ld from input_Q. ",
printk
("scsi%d: Abort - removing command %ld from input_Q. ",
instance->host_no, cmd->pid);
enable_irq(cmd->host->irq);
enable_irq(cmd->device->host->irq);
cmd->scsi_done(cmd);
return SCSI_ABORT_SUCCESS;
}
prev = tmp;
tmp = (Scsi_Cmnd *)tmp->host_scribble;
tmp = (Scsi_Cmnd *) tmp->host_scribble;
}
/*
......@@ -1559,7 +1635,8 @@ Scsi_Cmnd *tmp, *prev;
}
printk("sending wd33c93 ABORT command - ");
write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
write_wd33c93(regs, WD_CONTROL,
CTRL_IDI | CTRL_EDI | CTRL_POLLED);
write_wd33c93_cmd(regs, WD_CMD_ABORT);
/* Now we have to attempt to flush out the FIFO... */
......@@ -1567,12 +1644,13 @@ Scsi_Cmnd *tmp, *prev;
printk("flushing fifo - ");
timeout = 1000000;
do {
asr = READ_AUX_STAT();
asr = read_aux_stat(regs);
if (asr & ASR_DBR)
read_wd33c93(regs, WD_DATA);
} while (!(asr & ASR_INT) && timeout-- > 0);
sr = read_wd33c93(regs, WD_SCSI_STATUS);
printk("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ",
printk
("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ",
asr, sr, read_wd33c93_count(regs), timeout);
/*
......@@ -1585,21 +1663,21 @@ Scsi_Cmnd *tmp, *prev;
write_wd33c93_cmd(regs, WD_CMD_DISCONNECT);
timeout = 1000000;
asr = READ_AUX_STAT();
asr = read_aux_stat(regs);
while ((asr & ASR_CIP) && timeout-- > 0)
asr = READ_AUX_STAT();
asr = read_aux_stat(regs);
sr = read_wd33c93(regs, WD_SCSI_STATUS);
printk("asr=%02x, sr=%02x.",asr,sr);
printk("asr=%02x, sr=%02x.", asr, sr);
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
hostdata->connected = NULL;
hostdata->state = S_UNCONNECTED;
cmd->result = DID_ABORT << 16;
/* sti();*/
wd33c93_execute (instance);
wd33c93_execute(instance);
enable_irq(cmd->host->irq);
enable_irq(cmd->device->host->irq);
cmd->scsi_done(cmd);
return SCSI_ABORT_SUCCESS;
}
......@@ -1610,16 +1688,17 @@ Scsi_Cmnd *tmp, *prev;
* an ABORT_SNOOZE and hope for the best...
*/
tmp = (Scsi_Cmnd *)hostdata->disconnected_Q;
tmp = (Scsi_Cmnd *) hostdata->disconnected_Q;
while (tmp) {
if (tmp == cmd) {
printk("scsi%d: Abort - command %ld found on disconnected_Q - ",
printk
("scsi%d: Abort - command %ld found on disconnected_Q - ",
instance->host_no, cmd->pid);
printk("returning ABORT_SNOOZE. ");
enable_irq(cmd->host->irq);
enable_irq(cmd->device->host->irq);
return SCSI_ABORT_SNOOZE;
}
tmp = (Scsi_Cmnd *)tmp->host_scribble;
tmp = (Scsi_Cmnd *) tmp->host_scribble;
}
/*
......@@ -1633,16 +1712,14 @@ Scsi_Cmnd *tmp, *prev;
*/
/* sti();*/
wd33c93_execute (instance);
wd33c93_execute(instance);
enable_irq(cmd->host->irq);
enable_irq(cmd->device->host->irq);
printk("scsi%d: warning : SCSI command probably completed successfully"
" before abortion. ", instance->host_no);
return SCSI_ABORT_NOT_RUNNING;
}
#define MAX_WD33C93_HOSTS 4
#define MAX_SETUP_ARGS ((int)(sizeof(setup_args) / sizeof(char *)))
#define SETUP_BUFFER_SIZE 200
......@@ -1650,10 +1727,11 @@ static char setup_buffer[SETUP_BUFFER_SIZE];
static char setup_used[MAX_SETUP_ARGS];
static int done_setup = 0;
int wd33c93_setup (char *str)
int
wd33c93_setup(char *str)
{
int i;
char *p1,*p2;
char *p1, *p2;
/* The kernel does some processing of the command-line before calling
* this function: If it begins with any decimal or hex number arguments,
......@@ -1666,17 +1744,6 @@ int wd33c93_setup (char *str)
p1 = setup_buffer;
*p1 = '\0';
#if 0
/*
* Old style command line arguments are now dead
*/
if (ints[0]) {
for (i=0; i<ints[0]; i++) {
x = vsprintf(p1,"nosync:0x%02x,",&(ints[i+1]));
p1 += x;
}
}
#endif
if (str)
strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
......@@ -1690,31 +1757,28 @@ int wd33c93_setup (char *str)
setup_args[i] = p1;
p1 = p2 + 1;
i++;
}
else {
} else {
setup_args[i] = p1;
break;
}
}
for (i=0; i<MAX_SETUP_ARGS; i++)
for (i = 0; i < MAX_SETUP_ARGS; i++)
setup_used[i] = 0;
done_setup = 1;
return 1;
}
__setup("wd33c93", wd33c93_setup);
__setup("wd33c9=", wd33c93_setup);
/* check_setup_args() returns index if key found, 0 if not
*/
static int check_setup_args(char *key, int *flags, int *val, char *buf)
static int
check_setup_args(char *key, int *flags, int *val, char *buf)
{
int x;
char *cp;
int x;
char *cp;
for (x=0; x<MAX_SETUP_ARGS; x++) {
for (x = 0; x < MAX_SETUP_ARGS; x++) {
if (setup_used[x])
continue;
if (!strncmp(setup_args[x], key, strlen(key)))
......@@ -1731,26 +1795,25 @@ char *cp;
return ++x;
cp++;
if ((*cp >= '0') && (*cp <= '9')) {
*val = simple_strtoul(cp,NULL,0);
*val = simple_strtoul(cp, NULL, 0);
}
return ++x;
}
void wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
void
wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
dma_setup_t setup, dma_stop_t stop, int clock_freq)
{
struct WD33C93_hostdata *hostdata;
int i;
int flags;
int val;
char buf[32];
struct WD33C93_hostdata *hostdata;
int i;
int flags;
int val;
char buf[32];
if (!done_setup && setup_strings)
wd33c93_setup(setup_strings);
hostdata = (struct WD33C93_hostdata *)instance->hostdata;
hostdata = (struct WD33C93_hostdata *) instance->hostdata;
hostdata->regs = regs;
hostdata->clock_freq = clock_freq;
......@@ -1760,7 +1823,8 @@ char buf[32];
hostdata->dma_bounce_len = 0;
for (i = 0; i < 8; i++) {
hostdata->busy[i] = 0;
hostdata->sync_xfer[i] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF);
hostdata->sync_xfer[i] =
calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF);
hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */
#ifdef PROC_STATISTICS
hostdata->cmd_cnt[i] = 0;
......@@ -1784,9 +1848,8 @@ char buf[32];
hostdata->no_dma = 0; /* default is DMA enabled */
#ifdef PROC_INTERFACE
hostdata->proc = PR_VERSION|PR_INFO|PR_STATISTICS|
PR_CONNECTED|PR_INPUTQ|PR_DISCQ|
PR_STOP;
hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |
PR_CONNECTED | PR_INPUTQ | PR_DISCQ | PR_STOP;
#ifdef PROC_STATISTICS
hostdata->dma_cnt = 0;
hostdata->pio_cnt = 0;
......@@ -1794,94 +1857,94 @@ char buf[32];
#endif
#endif
if (check_setup_args("nosync",&flags,&val,buf))
if (check_setup_args("nosync", &flags, &val, buf))
hostdata->no_sync = val;
if (check_setup_args("nodma",&flags,&val,buf))
if (check_setup_args("nodma", &flags, &val, buf))
hostdata->no_dma = (val == -1) ? 1 : val;
if (check_setup_args("period",&flags,&val,buf))
hostdata->default_sx_per = sx_table[round_period((unsigned int)val)].period_ns;
if (check_setup_args("period", &flags, &val, buf))
hostdata->default_sx_per =
sx_table[round_period((unsigned int) val)].period_ns;
if (check_setup_args("disconnect",&flags,&val,buf)) {
if (check_setup_args("disconnect", &flags, &val, buf)) {
if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
hostdata->disconnect = val;
else
hostdata->disconnect = DIS_ADAPTIVE;
}
if (check_setup_args("level2",&flags,&val,buf))
if (check_setup_args("level2", &flags, &val, buf))
hostdata->level2 = val;
if (check_setup_args("debug",&flags,&val,buf))
if (check_setup_args("debug", &flags, &val, buf))
hostdata->args = val & DB_MASK;
if (check_setup_args("clock",&flags,&val,buf)) {
if (val>7 && val<11)
if (check_setup_args("clock", &flags, &val, buf)) {
if (val > 7 && val < 11)
val = WD33C93_FS_8_10;
else if (val>11 && val<16)
else if (val > 11 && val < 16)
val = WD33C93_FS_12_15;
else if (val>15 && val<21)
else if (val > 15 && val < 21)
val = WD33C93_FS_16_20;
else
val = WD33C93_FS_8_10;
hostdata->clock_freq = val;
}
if ((i = check_setup_args("next",&flags,&val,buf))) {
if ((i = check_setup_args("next", &flags, &val, buf))) {
while (i)
setup_used[--i] = 1;
}
#ifdef PROC_INTERFACE
if (check_setup_args("proc",&flags,&val,buf))
if (check_setup_args("proc", &flags, &val, buf))
hostdata->proc = val;
#endif
spin_lock_irq(&hostdata->lock);
reset_wd33c93(instance);
spin_unlock_irq(&hostdata->lock);
printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d",instance->host_no,
(hostdata->chip==C_WD33C93)?"WD33c93":
(hostdata->chip==C_WD33C93A)?"WD33c93A":
(hostdata->chip==C_WD33C93B)?"WD33c93B":"unknown",
hostdata->microcode,hostdata->no_sync,hostdata->no_dma);
printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d",
instance->host_no,
(hostdata->chip == C_WD33C93) ? "WD33c93" : (hostdata->chip ==
C_WD33C93A) ?
"WD33c93A" : (hostdata->chip ==
C_WD33C93B) ? "WD33c93B" : "unknown",
hostdata->microcode, hostdata->no_sync, hostdata->no_dma);
#ifdef DEBUGGING_ON
printk(" debug_flags=0x%02x\n",hostdata->args);
printk(" debug_flags=0x%02x\n", hostdata->args);
#else
printk(" debugging=OFF\n");
#endif
printk(" setup_args=");
for (i=0; i<MAX_SETUP_ARGS; i++)
printk("%s,",setup_args[i]);
for (i = 0; i < MAX_SETUP_ARGS; i++)
printk("%s,", setup_args[i]);
printk("\n");
printk(" Version %s - %s, Compiled %s at %s\n",
WD33C93_VERSION,WD33C93_DATE,__DATE__,__TIME__);
WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__);
}
int wd33c93_proc_info(char *buf, char **start, off_t off, int len, int hn, int in)
int
wd33c93_proc_info(char *buf, char **start, off_t off, int len, int hn, int in)
{
#ifdef PROC_INTERFACE
char *bp;
char tbuf[128];
struct Scsi_Host *instance;
struct WD33C93_hostdata *hd;
Scsi_Cmnd *cmd;
int x,i;
static int stop = 0;
char *bp;
char tbuf[128];
struct Scsi_Host *instance;
struct WD33C93_hostdata *hd;
Scsi_Cmnd *cmd;
int x, i;
static int stop = 0;
instance = scsi_host_hn_get(hn);
if (!instance) {
printk("*** Hmm... Can't find host #%d!\n",hn);
printk("*** Hmm... Can't find host #%d!\n", hn);
return (-ESRCH);
}
hd = (struct WD33C93_hostdata *)instance->hostdata;
hd = (struct WD33C93_hostdata *) instance->hostdata;
/* If 'in' is TRUE we need to _read_ the proc file. We accept the following
* keywords (same format as command-line, but only ONE per read):
......@@ -1896,40 +1959,35 @@ static int stop = 0;
if (in) {
buf[len] = '\0';
bp = buf;
if (!strncmp(bp,"debug:",6)) {
if (!strncmp(bp, "debug:", 6)) {
bp += 6;
hd->args = simple_strtoul(bp,NULL,0) & DB_MASK;
}
else if (!strncmp(bp,"disconnect:",11)) {
hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
} else if (!strncmp(bp, "disconnect:", 11)) {
bp += 11;
x = simple_strtoul(bp,NULL,0);
x = simple_strtoul(bp, NULL, 0);
if (x < DIS_NEVER || x > DIS_ALWAYS)
x = DIS_ADAPTIVE;
hd->disconnect = x;
}
else if (!strncmp(bp,"period:",7)) {
} else if (!strncmp(bp, "period:", 7)) {
bp += 7;
x = simple_strtoul(bp,NULL,0);
hd->default_sx_per = sx_table[round_period((unsigned int)x)].period_ns;
}
else if (!strncmp(bp,"resync:",7)) {
x = simple_strtoul(bp, NULL, 0);
hd->default_sx_per =
sx_table[round_period((unsigned int) x)].period_ns;
} else if (!strncmp(bp, "resync:", 7)) {
bp += 7;
x = simple_strtoul(bp,NULL,0);
for (i=0; i<7; i++)
if (x & (1<<i))
x = simple_strtoul(bp, NULL, 0);
for (i = 0; i < 7; i++)
if (x & (1 << i))
hd->sync_stat[i] = SS_UNSET;
}
else if (!strncmp(bp,"proc:",5)) {
} else if (!strncmp(bp, "proc:", 5)) {
bp += 5;
hd->proc = simple_strtoul(bp,NULL,0);
}
else if (!strncmp(bp,"nodma:",6)) {
hd->proc = simple_strtoul(bp, NULL, 0);
} else if (!strncmp(bp, "nodma:", 6)) {
bp += 6;
hd->no_dma = simple_strtoul(bp,NULL,0);
}
else if (!strncmp(bp,"level2:",7)) {
hd->no_dma = simple_strtoul(bp, NULL, 0);
} else if (!strncmp(bp, "level2:", 7)) {
bp += 7;
hd->level2 = simple_strtoul(bp,NULL,0);
hd->level2 = simple_strtoul(bp, NULL, 0);
}
return len;
}
......@@ -1938,77 +1996,78 @@ static int stop = 0;
bp = buf;
*bp = '\0';
if (hd->proc & PR_VERSION) {
sprintf(tbuf,"\nVersion %s - %s. Compiled %s %s",
WD33C93_VERSION,WD33C93_DATE,__DATE__,__TIME__);
strcat(bp,tbuf);
sprintf(tbuf, "\nVersion %s - %s. Compiled %s %s",
WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__);
strcat(bp, tbuf);
}
if (hd->proc & PR_INFO) {
sprintf(tbuf,"\nclock_freq=%02x no_sync=%02x no_dma=%d",
hd->clock_freq,hd->no_sync,hd->no_dma);
strcat(bp,tbuf);
strcat(bp,"\nsync_xfer[] = ");
for (x=0; x<7; x++) {
sprintf(tbuf,"\t%02x",hd->sync_xfer[x]);
strcat(bp,tbuf);
sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d",
hd->clock_freq, hd->no_sync, hd->no_dma);
strcat(bp, tbuf);
strcat(bp, "\nsync_xfer[] = ");
for (x = 0; x < 7; x++) {
sprintf(tbuf, "\t%02x", hd->sync_xfer[x]);
strcat(bp, tbuf);
}
strcat(bp,"\nsync_stat[] = ");
for (x=0; x<7; x++) {
sprintf(tbuf,"\t%02x",hd->sync_stat[x]);
strcat(bp,tbuf);
strcat(bp, "\nsync_stat[] = ");
for (x = 0; x < 7; x++) {
sprintf(tbuf, "\t%02x", hd->sync_stat[x]);
strcat(bp, tbuf);
}
}
#ifdef PROC_STATISTICS
if (hd->proc & PR_STATISTICS) {
strcat(bp,"\ncommands issued: ");
for (x=0; x<7; x++) {
sprintf(tbuf,"\t%ld",hd->cmd_cnt[x]);
strcat(bp,tbuf);
}
strcat(bp,"\ndisconnects allowed:");
for (x=0; x<7; x++) {
sprintf(tbuf,"\t%ld",hd->disc_allowed_cnt[x]);
strcat(bp,tbuf);
}
strcat(bp,"\ndisconnects done: ");
for (x=0; x<7; x++) {
sprintf(tbuf,"\t%ld",hd->disc_done_cnt[x]);
strcat(bp,tbuf);
}
sprintf(tbuf,"\ninterrupts: %ld, DATA_PHASE ints: %ld DMA, %ld PIO",
hd->int_cnt,hd->dma_cnt,hd->pio_cnt);
strcat(bp,tbuf);
strcat(bp, "\ncommands issued: ");
for (x = 0; x < 7; x++) {
sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]);
strcat(bp, tbuf);
}
strcat(bp, "\ndisconnects allowed:");
for (x = 0; x < 7; x++) {
sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]);
strcat(bp, tbuf);
}
strcat(bp, "\ndisconnects done: ");
for (x = 0; x < 7; x++) {
sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]);
strcat(bp, tbuf);
}
sprintf(tbuf,
"\ninterrupts: %ld, DATA_PHASE ints: %ld DMA, %ld PIO",
hd->int_cnt, hd->dma_cnt, hd->pio_cnt);
strcat(bp, tbuf);
}
#endif
if (hd->proc & PR_CONNECTED) {
strcat(bp,"\nconnected: ");
strcat(bp, "\nconnected: ");
if (hd->connected) {
cmd = (Scsi_Cmnd *)hd->connected;
sprintf(tbuf," %ld-%d:%d(%02x)",
cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
strcat(bp,tbuf);
cmd = (Scsi_Cmnd *) hd->connected;
sprintf(tbuf, " %ld-%d:%d(%02x)",
cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
strcat(bp, tbuf);
}
}
if (hd->proc & PR_INPUTQ) {
strcat(bp,"\ninput_Q: ");
cmd = (Scsi_Cmnd *)hd->input_Q;
strcat(bp, "\ninput_Q: ");
cmd = (Scsi_Cmnd *) hd->input_Q;
while (cmd) {
sprintf(tbuf," %ld-%d:%d(%02x)",
cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
strcat(bp,tbuf);
cmd = (Scsi_Cmnd *)cmd->host_scribble;
sprintf(tbuf, " %ld-%d:%d(%02x)",
cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
strcat(bp, tbuf);
cmd = (Scsi_Cmnd *) cmd->host_scribble;
}
}
if (hd->proc & PR_DISCQ) {
strcat(bp,"\ndisconnected_Q:");
cmd = (Scsi_Cmnd *)hd->disconnected_Q;
strcat(bp, "\ndisconnected_Q:");
cmd = (Scsi_Cmnd *) hd->disconnected_Q;
while (cmd) {
sprintf(tbuf," %ld-%d:%d(%02x)",
cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
strcat(bp,tbuf);
cmd = (Scsi_Cmnd *)cmd->host_scribble;
sprintf(tbuf, " %ld-%d:%d(%02x)",
cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
strcat(bp, tbuf);
cmd = (Scsi_Cmnd *) cmd->host_scribble;
}
}
strcat(bp,"\n");
strcat(bp, "\n");
spin_unlock_irq(&hd->lock);
*start = buf;
if (stop) {
......@@ -2029,12 +2088,14 @@ static int stop = 0;
}
#ifdef MODULE
int init_module(void) { return 0; }
void cleanup_module(void) {}
#endif
void wd33c93_release(void)
void
wd33c93_release(void)
{
}
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(wd33c93_reset);
EXPORT_SYMBOL(wd33c93_init);
EXPORT_SYMBOL(wd33c93_release);
EXPORT_SYMBOL(wd33c93_abort);
EXPORT_SYMBOL(wd33c93_queuecommand);
EXPORT_SYMBOL(wd33c93_intr);
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