116 #include <linux/module.h>
119 #include <linux/string.h>
123 #include <linux/stat.h>
130 #define IN2000_VERSION "1.33-2.5"
131 #define IN2000_DATE "2002/11/03"
183 static char *setup_args[] = {
"",
"",
"",
"",
"",
"",
"",
"",
"" };
186 static char *setup_strings;
197 #define READ_AUX_STAT() read1_io(IO_WD_ASR)
225 x = read_3393(hostdata,
WD_DATA);
259 switch (cmd->
cmnd[0]) {
310 static int round_period(
unsigned int period)
322 static uchar calc_sync_xfer(
unsigned int period,
unsigned int offset)
327 result = sx_table[round_period(period)].
reg_value;
334 static void in2000_execute(
struct Scsi_Host *instance);
342 instance = cmd->
device->host;
371 if (scsi_bufflen(cmd)) {
372 cmd->
SCp.buffer = scsi_sglist(cmd);
373 cmd->
SCp.buffers_residual = scsi_sg_count(cmd) - 1;
374 cmd->
SCp.ptr = sg_virt(cmd->
SCp.buffer);
375 cmd->
SCp.this_residual = cmd->
SCp.buffer->length;
378 cmd->
SCp.buffers_residual = 0;
380 cmd->
SCp.this_residual = 0;
382 cmd->
SCp.have_data_in = 0;
427 in2000_execute(cmd->
device->host);
452 unsigned short flushbuf[16];
474 if (!(hostdata->
busy[cmd->device->id] & (1 << cmd->device->lun)))
492 prev->host_scribble = cmd->host_scribble;
494 hostdata->input_Q = (
Scsi_Cmnd *) cmd->host_scribble;
496 #ifdef PROC_STATISTICS
497 hostdata->
cmd_cnt[cmd->device->id]++;
537 if (cmd->device->type == 1)
544 if ((prev->
device->id != cmd->device->id) || (prev->
device->lun != cmd->device->lun)) {
555 #ifdef PROC_STATISTICS
564 hostdata->
busy[cmd->device->id] |= (1 << cmd->device->lun);
589 if (hostdata->
sync_off & (1 << cmd->device->id))
595 write_3393_count(hostdata, 0);
617 for (i = 0; i < cmd->cmd_len; i++)
626 write_3393(hostdata,
WD_OWN_ID, cmd->cmd_len);
646 if (!(cmd->SCp.phase)) {
647 write_3393_count(hostdata, cmd->SCp.this_residual);
651 if (is_dir_out(cmd)) {
655 cmd->SCp.have_data_in =
i;
657 sp = (
unsigned short *) cmd->SCp.ptr;
690 cmd->SCp.have_data_in = 0;
694 write_3393_count(hostdata, 0);
720 write_3393_count(hostdata, cnt);
726 *buf++ = read_3393(hostdata,
WD_DATA);
732 write_3393(hostdata,
WD_DATA, *buf++);
747 static void transfer_bytes(
Scsi_Cmnd * cmd,
int data_in_dir)
764 if (!cmd->
SCp.this_residual && cmd->
SCp.buffers_residual) {
766 --cmd->
SCp.buffers_residual;
767 cmd->
SCp.this_residual = cmd->
SCp.buffer->length;
768 cmd->
SCp.ptr = sg_virt(cmd->
SCp.buffer);
774 write_3393_count(hostdata, cmd->
SCp.this_residual);
789 write_3393_cmd(hostdata, WD_CMD_TRANS_INFO);
791 cmd->
SCp.have_data_in = 0;
805 write_3393_cmd(hostdata, WD_CMD_TRANS_INFO);
807 sp = (
unsigned short *) cmd->
SCp.ptr;
811 cmd->
SCp.have_data_in =
i;
851 #ifdef PROC_STATISTICS
920 sp = (
unsigned short *) (cmd->SCp.
ptr + cmd->SCp.have_data_in);
934 i = sp - (
unsigned short *) (cmd->
SCp.ptr + cmd->
SCp.have_data_in);
936 cmd->
SCp.have_data_in +=
i;
953 if (cmd->SCp.this_residual == cmd->SCp.have_data_in) {
964 sp = (
unsigned short *) (cmd->
SCp.ptr + cmd->
SCp.have_data_in);
965 i = cmd->
SCp.this_residual - cmd->
SCp.have_data_in;
973 i = sp - (
unsigned short *) (cmd->
SCp.ptr + cmd->
SCp.have_data_in);
975 cmd->
SCp.have_data_in +=
i;
980 printk(
"*** Spurious FIFO interrupt ***");
986 spin_unlock_irqrestore(instance->
host_lock, flags);
1000 printk(
"\nNR:wd-intr-1\n");
1004 spin_unlock_irqrestore(instance->
host_lock, flags);
1026 sp = (
unsigned short *) (cmd->
SCp.ptr + cmd->
SCp.have_data_in);
1030 i = (cmd->
SCp.this_residual - read_3393_count(hostdata)) - cmd->
SCp.have_data_in;
1032 f = hostdata->
io_base + IO_FIFO;
1044 length = cmd->
SCp.this_residual;
1045 cmd->
SCp.this_residual = read_3393_count(hostdata);
1046 cmd->
SCp.ptr += (length - cmd->
SCp.this_residual);
1054 length = cmd->
SCp.this_residual;
1055 cmd->
SCp.this_residual = read_3393_count(hostdata);
1056 cmd->
SCp.ptr += (length - cmd->
SCp.this_residual);
1086 in2000_execute(instance);
1096 hostdata->selecting = NULL;
1106 printk(
" sending SDTR ");
1142 hostdata->
state = S_CONNECTED;
1151 DB(DB_INTR,
printk("CMND-%02x", cmd->cmnd[0]))
1152 transfer_pio(cmd->cmnd, cmd->
cmd_len, DATA_OUT_DIR, hostdata);
1153 hostdata->
state = S_CONNECTED;
1162 cmd->SCp.
Status = read_1_byte(hostdata);
1180 msg = read_1_byte(hostdata);
1189 cmd->SCp.Message = msg;
1200 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1230 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1234 case EXTENDED_MESSAGE:
1240 printk(
"%02x", ucp[hostdata->incoming_ptr]);
1244 if ((hostdata->incoming_ptr >= 2) && (hostdata->incoming_ptr == (ucp[1] + 1))) {
1248 id = calc_sync_xfer(ucp[3], ucp[4]);
1262 hostdata->outgoing_msg[1] = 3;
1264 hostdata->outgoing_msg[3] = hostdata->default_sx_per / 4;
1265 hostdata->outgoing_msg[4] = 0;
1266 hostdata->outgoing_len = 5;
1267 hostdata->sync_xfer[cmd->
device->id] = calc_sync_xfer(hostdata->default_sx_per / 4, 0);
1269 hostdata->sync_xfer[cmd->
device->id] =
id;
1272 printk(
"sync_xfer=%02x", hostdata->sync_xfer[cmd->
device->id]);
1275 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1282 hostdata->outgoing_msg[1] = 2;
1284 hostdata->outgoing_msg[3] = 0;
1285 hostdata->outgoing_len = 4;
1286 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1291 printk(
"Rejecting Unknown Extended Message(%02x). ", ucp[2]);
1293 hostdata->outgoing_len = 1;
1294 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1298 hostdata->incoming_ptr = 0;
1304 hostdata->incoming_ptr++;
1305 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1311 printk(
"Rejecting Unknown Message(%02x) ", msg);
1314 hostdata->outgoing_len = 1;
1315 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1339 cmd->SCp.Status = lun;
1343 cmd->
result = cmd->SCp.Status | (cmd->SCp.Message << 8);
1344 cmd->scsi_done(cmd);
1350 in2000_execute(instance);
1352 printk(
"%02x:%02x:%02x: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs);
1385 hostdata->outgoing_len = 1;
1386 hostdata->outgoing_msg[0] =
NOP;
1388 transfer_pio(hostdata->outgoing_msg, hostdata->outgoing_len,
DATA_OUT_DIR, hostdata);
1389 DB(DB_INTR,
printk(
"%02x", hostdata->outgoing_msg[0]))
1412 printk(
" - Already disconnected! ");
1416 spin_unlock_irqrestore(instance->
host_lock, flags);
1426 cmd->
result = cmd->SCp.
Status | (cmd->SCp.Message << 8);
1427 cmd->scsi_done(cmd);
1433 in2000_execute(instance);
1446 printk(
" - Already disconnected! ");
1449 switch (hostdata->state) {
1451 hostdata->connected =
NULL;
1452 hostdata->busy[cmd->
device->id] &= ~(1 << cmd->
device->lun);
1458 cmd->
result = cmd->SCp.
Status | (cmd->SCp.Message << 8);
1459 cmd->scsi_done(cmd);
1461 case S_PRE_TMP_DISC:
1464 hostdata->disconnected_Q = cmd;
1468 #ifdef PROC_STATISTICS
1469 hostdata->disc_done_cnt[cmd->device->id]++;
1474 printk(
"*** Unexpected DISCONNECT interrupt! ***");
1482 in2000_execute(instance);
1494 if (hostdata->selecting) {
1495 cmd = (
Scsi_Cmnd *) hostdata->selecting;
1496 hostdata->selecting = NULL;
1497 hostdata->busy[cmd->
device->id] &= ~(1 << cmd->
device->lun);
1499 hostdata->input_Q = cmd;
1507 hostdata->busy[cmd->
device->id] &= ~(1 << cmd->
device->lun);
1509 hostdata->input_Q = cmd;
1511 printk(
"---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---", asr, sr, phs);
1529 lun = read_3393(hostdata,
WD_DATA);
1531 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1536 cmd = (
Scsi_Cmnd *) hostdata->disconnected_Q;
1548 printk(
"---TROUBLE: target %d.%d not in disconnect queue---",
id, lun);
1558 hostdata->connected = cmd;
1565 if (is_dir_out(cmd))
1570 write_3393_count(hostdata, 0);
1580 printk(
"--UNKNOWN INTERRUPT:%02x:%02x:%02x--", asr, sr, phs);
1588 spin_unlock_irqrestore(instance->host_lock, flags);
1594 #define RESET_CARD 0
1595 #define RESET_CARD_AND_BUS 1
1602 static int reset_hardware(
struct Scsi_Host *instance,
int type)
1614 x = read_3393(hostdata, WD_SCSI_STATUS);
1626 x = read_3393(hostdata, WD_SCSI_STATUS);
1642 static int in2000_bus_reset(
Scsi_Cmnd * cmd)
1647 unsigned long flags;
1649 instance = cmd->
device->host;
1658 for (x = 0; x < 8; x++) {
1659 hostdata->
busy[
x] = 0;
1674 spin_unlock_irqrestore(instance->
host_lock, flags);
1678 static int __in2000_abort(
Scsi_Cmnd * cmd)
1686 instance = cmd->
device->host;
1690 printk(
"(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ",
READ_AUX_STAT(), read_3393_count(hostdata), cmd->
SCp.this_residual, cmd->
SCp.buffers_residual, cmd->
SCp.have_data_in,
read1_io(
IO_FIFO_COUNT));
1728 printk(
"sending wd33c93 ABORT command - ");
1734 printk(
"flushing fifo - ");
1740 }
while (!(asr & ASR_INT) && timeout-- > 0);
1741 sr = read_3393(hostdata, WD_SCSI_STATUS);
1742 printk(
"asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ", asr, sr, read_3393_count(hostdata), timeout);
1750 printk(
"sending wd33c93 DISCONNECT command - ");
1755 while ((asr &
ASR_CIP) && timeout-- > 0)
1757 sr = read_3393(hostdata, WD_SCSI_STATUS);
1758 printk(
"asr=%02x, sr=%02x.", asr, sr);
1766 in2000_execute(instance);
1793 in2000_execute(instance);
1795 printk(
"scsi%d: warning : SCSI command probably completed successfully" " before abortion. ", instance->
host_no);
1799 static int in2000_abort(
Scsi_Cmnd * cmd)
1803 spin_lock_irq(cmd->
device->host->host_lock);
1804 rc = __in2000_abort(cmd);
1805 spin_unlock_irq(cmd->
device->host->host_lock);
1811 #define MAX_IN2000_HOSTS 3
1812 #define MAX_SETUP_ARGS ARRAY_SIZE(setup_args)
1813 #define SETUP_BUFFER_SIZE 200
1816 static int done_setup = 0;
1818 static void __init in2000_setup(
char *
str,
int *ints)
1848 static int __init check_setup_args(
char *
key,
int *
val,
char *buf)
1859 if (x == MAX_SETUP_ARGS)
1862 cp = setup_args[
x] +
strlen(key);
1867 if ((*cp >=
'0') && (*cp <=
'9')) {
1887 static unsigned short base_tab[] in2000__INITDATA = {
1894 static int int_tab[] in2000__INITDATA = {
1906 *s1 =
readl(p + 0x10);
1907 if (*s1 == 0x41564f4e ||
readl(p + 0x30) == 0x61776c41) {
1909 *switches = ~
readb(p + 0x20);
1924 unsigned short base;
1927 unsigned long flags;
1943 if (!done_setup && setup_strings)
1944 in2000_setup(setup_strings, NULL);
1947 for (bios = 0; bios_tab[
bios]; bios++) {
1949 if (check_setup_args(
"ioport", &val, buf)) {
1952 printk(
"Forcing IN2000 detection at IOport 0x%x ", base);
1960 else if (probe_bios(bios_tab[bios], &s1, &switches)) {
1961 printk(
"Found IN2000 BIOS at 0x%x ", (
unsigned int) bios_tab[bios]);
1971 if (x != switches) {
1972 printk(
"Bad IO signature: %02x vs %02x.\n", x, switches);
1981 printk(
"There is no IN-2000 SCSI card at IOport 0x%03x!\n", base);
1994 printk(
"The IN-2000 SCSI card at IOport 0x%03x ", base);
1995 printk(
"is not configured for interrupt operation!\n");
1996 printk(
"This driver requires an interrupt: cancelling detection.\n");
2006 if (instance == NULL)
2012 hostdata->
hrev = hrev;
2019 printk(
"in2000_detect: Unable to allocate IRQ.\n");
2027 for (x = 0; x < 8; x++) {
2028 hostdata->
busy[
x] = 0;
2031 #ifdef PROC_STATISTICS
2057 #ifdef PROC_INTERFACE
2059 #ifdef PROC_STATISTICS
2064 if (check_setup_args(
"nosync", &val, buf))
2067 if (check_setup_args(
"period", &val, buf))
2070 if (check_setup_args(
"disconnect", &val, buf)) {
2077 if (check_setup_args(
"noreset", &val, buf))
2080 if (check_setup_args(
"level2", &val, buf))
2083 if (check_setup_args(
"debug", &val, buf))
2086 #ifdef PROC_INTERFACE
2087 if (check_setup_args(
"proc", &val, buf))
2088 hostdata->
proc = val;
2096 spin_unlock_irqrestore(instance->
host_lock, flags);
2107 printk(
"dip_switch=%02x irq=%d ioport=%02x floppy=%s sync/DOS5=%s ", (switches & 0x7f), instance->
irq, hostdata->
io_base, (switches &
SW_FLOPPY) ?
"Yes" :
"No", (switches & SW_SYNC_DOS5) ?
"Yes" :
"No");
2112 printk(
"%s,", setup_args[x]);
2116 printk(
"Sync-transfer DISABLED on all devices: ENABLE from command-line\n");
2120 return detect_count;
2144 iinfo[2] = size >> 11;
2150 if (iinfo[2] > 1024) {
2153 iinfo[2] = (
unsigned long) capacity / (iinfo[0] * iinfo[1]);
2155 if (iinfo[2] > 1024) {
2158 iinfo[2] = (
unsigned long) capacity / (iinfo[0] * iinfo[1]);
2160 if (iinfo[2] > 1024) {
2163 iinfo[2] = (
unsigned long) capacity / (iinfo[0] * iinfo[1]);
2169 static int in2000_proc_info(
struct Scsi_Host *instance,
char *buf,
char **
start,
off_t off,
int len,
int in)
2172 #ifdef PROC_INTERFACE
2176 unsigned long flags;
2180 static int stop = 0;
2196 if (!
strncmp(bp,
"debug:", 6)) {
2199 }
else if (!
strncmp(bp,
"disconnect:", 11)) {
2205 }
else if (!
strncmp(bp,
"period:", 7)) {
2209 }
else if (!
strncmp(bp,
"resync:", 7)) {
2212 for (i = 0; i < 7; i++)
2215 }
else if (!
strncmp(bp,
"proc:", 5)) {
2218 }
else if (!
strncmp(bp,
"level2:", 7)) {
2235 strcat(bp,
"\nsync_xfer[] = ");
2236 for (x = 0; x < 7; x++) {
2240 strcat(bp,
"\nsync_stat[] = ");
2241 for (x = 0; x < 7; x++) {
2246 #ifdef PROC_STATISTICS
2248 strcat(bp,
"\ncommands issued: ");
2249 for (x = 0; x < 7; x++) {
2253 strcat(bp,
"\ndisconnects allowed:");
2254 for (x = 0; x < 7; x++) {
2258 strcat(bp,
"\ndisconnects done: ");
2259 for (x = 0; x < 7; x++) {
2268 strcat(bp,
"\nconnected: ");
2276 strcat(bp,
"\ninput_Q: ");
2285 strcat(bp,
"\ndisconnected_Q:");
2297 spin_unlock_irqrestore(instance->
host_lock, flags);
2321 .proc_name =
"in2000",
2322 .proc_info = in2000_proc_info,
2323 .name =
"Always IN2000",
2324 .detect = in2000_detect,
2325 .release = in2000_release,
2326 .queuecommand = in2000_queuecommand,
2327 .eh_abort_handler = in2000_abort,
2328 .eh_bus_reset_handler = in2000_bus_reset,
2329 .bios_param = in2000_biosparam,