Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
8b8ee7f9
Commit
8b8ee7f9
authored
Nov 04, 2002
by
Alan Cox
Committed by
Dave Jones
Nov 04, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] in2000 new_eh and locking fixes
parent
19cd7f5f
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
1380 additions
and
1440 deletions
+1380
-1440
drivers/scsi/in2000.c
drivers/scsi/in2000.c
+1380
-1440
No files found.
drivers/scsi/in2000.c
View file @
8b8ee7f9
...
...
@@ -16,6 +16,11 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For the avoidance of doubt the "preferred form" of this code is one which
* is in an open non patent encumbered format. Where cryptographic key signing
* forms part of the process of creating an executable the information
* including keys needed to generate an equivalently functional executable
* are deemed to be part of the source code.
*
* Drew Eckhardt's excellent 'Generic NCR5380' sources provided
* much of the inspiration and some of the code for this driver.
...
...
@@ -102,6 +107,10 @@
* this thing into as good a shape as possible, and I'm positive
* there are lots of lurking bugs and "Stupid Places".
*
* Updated for Linux 2.5 by Alan Cox <alan@redhat.com>
* - Using new_eh handler
* - Hopefully got all the locking right again
* See "FIXME" notes for items that could do with more work
*/
#include <linux/module.h>
...
...
@@ -121,8 +130,8 @@
#include "scsi.h"
#include "hosts.h"
#define IN2000_VERSION "1.33"
#define IN2000_DATE "2
6/August/1998
"
#define IN2000_VERSION "1.33
-2.5
"
#define IN2000_DATE "2
002/11/03
"
#include "in2000.h"
...
...
@@ -174,8 +183,7 @@
*/
/* Normally, no defaults are specified... */
static
char
*
setup_args
[]
=
{
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
};
static
char
*
setup_args
[]
=
{
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
};
/* filled in by 'insmod' */
static
char
*
setup_strings
=
0
;
...
...
@@ -184,14 +192,9 @@ static char *setup_strings = 0;
MODULE_PARM
(
setup_strings
,
"s"
);
#endif
static
struct
Scsi_Host
*
instance_list
=
0
;
static
inline
uchar
read_3393
(
struct
IN2000_hostdata
*
hostdata
,
uchar
reg_num
)
{
write1_io
(
reg_num
,
IO_WD_ADDR
);
write1_io
(
reg_num
,
IO_WD_ADDR
);
return
read1_io
(
IO_WD_DATA
);
}
...
...
@@ -201,8 +204,8 @@ static inline uchar read_3393(struct IN2000_hostdata *hostdata, uchar reg_num)
static
inline
void
write_3393
(
struct
IN2000_hostdata
*
hostdata
,
uchar
reg_num
,
uchar
value
)
{
write1_io
(
reg_num
,
IO_WD_ADDR
);
write1_io
(
value
,
IO_WD_DATA
);
write1_io
(
reg_num
,
IO_WD_ADDR
);
write1_io
(
value
,
IO_WD_DATA
);
}
...
...
@@ -210,21 +213,21 @@ static inline void write_3393_cmd(struct IN2000_hostdata *hostdata, uchar cmd)
{
/* while (READ_AUX_STAT() & ASR_CIP)
printk("|");*/
write1_io
(
WD_COMMAND
,
IO_WD_ADDR
);
write1_io
(
cmd
,
IO_WD_DATA
);
write1_io
(
WD_COMMAND
,
IO_WD_ADDR
);
write1_io
(
cmd
,
IO_WD_DATA
);
}
static
uchar
read_1_byte
(
struct
IN2000_hostdata
*
hostdata
)
{
uchar
asr
,
x
=
0
;
uchar
asr
,
x
=
0
;
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_POLLED
);
write_3393_cmd
(
hostdata
,
WD_CMD_TRANS_INFO
|
0x80
);
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_POLLED
);
write_3393_cmd
(
hostdata
,
WD_CMD_TRANS_INFO
|
0x80
);
do
{
asr
=
READ_AUX_STAT
();
if
(
asr
&
ASR_DBR
)
x
=
read_3393
(
hostdata
,
WD_DATA
);
x
=
read_3393
(
hostdata
,
WD_DATA
);
}
while
(
!
(
asr
&
ASR_INT
));
return
x
;
}
...
...
@@ -232,18 +235,18 @@ uchar asr, x = 0;
static
void
write_3393_count
(
struct
IN2000_hostdata
*
hostdata
,
unsigned
long
value
)
{
write1_io
(
WD_TRANSFER_COUNT_MSB
,
IO_WD_ADDR
);
write1_io
((
value
>>
16
),
IO_WD_DATA
);
write1_io
((
value
>>
8
),
IO_WD_DATA
);
write1_io
(
value
,
IO_WD_DATA
);
write1_io
(
WD_TRANSFER_COUNT_MSB
,
IO_WD_ADDR
);
write1_io
((
value
>>
16
),
IO_WD_DATA
);
write1_io
((
value
>>
8
),
IO_WD_DATA
);
write1_io
(
value
,
IO_WD_DATA
);
}
static
unsigned
long
read_3393_count
(
struct
IN2000_hostdata
*
hostdata
)
{
unsigned
long
value
;
unsigned
long
value
;
write1_io
(
WD_TRANSFER_COUNT_MSB
,
IO_WD_ADDR
);
write1_io
(
WD_TRANSFER_COUNT_MSB
,
IO_WD_ADDR
);
value
=
read1_io
(
IO_WD_DATA
)
<<
16
;
value
|=
read1_io
(
IO_WD_DATA
)
<<
8
;
value
|=
read1_io
(
IO_WD_DATA
);
...
...
@@ -256,19 +259,38 @@ unsigned long value;
* 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:
...
...
@@ -279,23 +301,23 @@ 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
)
{
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
;
}
}
...
...
@@ -304,11 +326,11 @@ int x;
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
;
}
...
...
@@ -316,24 +338,22 @@ uchar result;
static
void
in2000_execute
(
struct
Scsi_Host
*
instance
);
static
int
in2000_queuecommand
(
Scsi_Cmnd
*
cmd
,
void
(
*
done
)
(
Scsi_Cmnd
*
))
static
int
in2000_queuecommand
(
Scsi_Cmnd
*
cmd
,
void
(
*
done
)
(
Scsi_Cmnd
*
))
{
struct
Scsi_Host
*
instance
;
struct
IN2000_hostdata
*
hostdata
;
Scsi_Cmnd
*
tmp
;
unsigned
long
flags
;
struct
Scsi_Host
*
instance
;
struct
IN2000_hostdata
*
hostdata
;
Scsi_Cmnd
*
tmp
;
instance
=
cmd
->
host
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
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
->
target
,
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
;
...
...
@@ -354,15 +374,14 @@ 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
=
(
char
*
)
page_address
(
cmd
->
SCp
.
buffer
->
page
)
+
cmd
->
SCp
.
buffer
->
offset
;
cmd
->
SCp
.
ptr
=
(
char
*
)
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
;
}
cmd
->
SCp
.
have_data_in
=
0
;
...
...
@@ -392,7 +411,6 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
* queue and calling in2000_execute().
*/
spin_lock_irqsave
(
instance
->
host_lock
,
flags
);
/*
* Add the cmd to the end of 'input_Q'. Note that REQUEST_SENSE
* commands are added to the head of the queue so that the desired
...
...
@@ -400,14 +418,11 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
*/
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.
...
...
@@ -416,8 +431,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid))
in2000_execute
(
cmd
->
host
);
DB
(
DB_QUEUE_COMMAND
,
printk
(
")Q-%ld "
,
cmd
->
pid
))
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
DB
(
DB_QUEUE_COMMAND
,
printk
(
")Q-%ld "
,
cmd
->
pid
))
return
0
;
}
...
...
@@ -431,23 +445,23 @@ DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
* Note that this function is always called with interrupts already
* disabled (either from in2000_queuecommand() or in2000_intr()).
*/
static
void
in2000_execute
(
struct
Scsi_Host
*
instance
)
static
void
in2000_execute
(
struct
Scsi_Host
*
instance
)
{
struct
IN2000_hostdata
*
hostdata
;
Scsi_Cmnd
*
cmd
,
*
prev
;
int
i
;
unsigned
short
*
sp
;
unsigned
short
f
;
unsigned
short
flushbuf
[
16
];
struct
IN2000_hostdata
*
hostdata
;
Scsi_Cmnd
*
cmd
,
*
prev
;
int
i
;
unsigned
short
*
sp
;
unsigned
short
f
;
unsigned
short
flushbuf
[
16
];
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
DB
(
DB_EXECUTE
,
printk
(
"EX("
))
DB
(
DB_EXECUTE
,
printk
(
"EX("
))
if
(
hostdata
->
selecting
||
hostdata
->
connected
)
{
DB
(
DB_EXECUTE
,
printk
(
")EX-0 "
))
DB
(
DB_EXECUTE
,
printk
(
")EX-0 "
))
return
;
}
...
...
@@ -457,20 +471,20 @@ 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
)))
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
;
}
...
...
@@ -480,7 +494,7 @@ 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
]
++
;
...
...
@@ -491,9 +505,9 @@ DB(DB_EXECUTE,printk(")EX-1 "))
*/
if
(
is_dir_out
(
cmd
))
write_3393
(
hostdata
,
WD_DESTINATION_ID
,
cmd
->
target
);
write_3393
(
hostdata
,
WD_DESTINATION_ID
,
cmd
->
target
);
else
write_3393
(
hostdata
,
WD_DESTINATION_ID
,
cmd
->
target
|
DSTID_DPD
);
write_3393
(
hostdata
,
WD_DESTINATION_ID
,
cmd
->
target
|
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
...
...
@@ -529,33 +543,30 @@ 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
)
{
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
)
prev
->
SCp
.
phase
=
1
;
goto
yes
;
}
}
goto
no
;
yes:
yes:
cmd
->
SCp
.
phase
=
1
;
#ifdef PROC_STATISTICS
hostdata
->
disc_allowed_cnt
[
cmd
->
target
]
++
;
#endif
no:
write_3393
(
hostdata
,
WD_SOURCE_ID
,((
cmd
->
SCp
.
phase
)
?
SRCID_ER
:
0
));
no:
write_3393
(
hostdata
,
WD_SOURCE_ID
,
((
cmd
->
SCp
.
phase
)
?
SRCID_ER
:
0
));
write_3393
(
hostdata
,
WD_TARGET_LUN
,
cmd
->
lun
);
write_3393
(
hostdata
,
WD_SYNCHRONOUS_TRANSFER
,
hostdata
->
sync_xfer
[
cmd
->
target
]);
write_3393
(
hostdata
,
WD_TARGET_LUN
,
cmd
->
lun
);
write_3393
(
hostdata
,
WD_SYNCHRONOUS_TRANSFER
,
hostdata
->
sync_xfer
[
cmd
->
target
]);
hostdata
->
busy
[
cmd
->
target
]
|=
(
1
<<
cmd
->
lun
);
if
((
hostdata
->
level2
<=
L2_NONE
)
||
(
hostdata
->
sync_stat
[
cmd
->
target
]
==
SS_UNSET
))
{
if
((
hostdata
->
level2
<=
L2_NONE
)
||
(
hostdata
->
sync_stat
[
cmd
->
target
]
==
SS_UNSET
))
{
/*
* Do a 'Select-With-ATN' command. This will end with
...
...
@@ -584,8 +595,8 @@ DB(DB_EXECUTE,printk(")EX-1 "))
hostdata
->
sync_stat
[
cmd
->
target
]
=
SS_FIRST
;
}
hostdata
->
state
=
S_SELECTING
;
write_3393_count
(
hostdata
,
0
);
/* this guarantees a DATA_PHASE interrupt */
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN
);
write_3393_count
(
hostdata
,
0
);
/* this guarantees a DATA_PHASE interrupt */
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN
);
}
else
{
...
...
@@ -599,14 +610,14 @@ DB(DB_EXECUTE,printk(")EX-1 "))
*/
hostdata
->
connected
=
cmd
;
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0
);
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0
);
/* copy command_descriptor_block into WD chip
* (take advantage of auto-incrementing)
*/
write1_io
(
WD_CDB_1
,
IO_WD_ADDR
);
for
(
i
=
0
;
i
<
cmd
->
cmd_len
;
i
++
)
for
(
i
=
0
;
i
<
cmd
->
cmd_len
;
i
++
)
write1_io
(
cmd
->
cmnd
[
i
],
IO_WD_DATA
);
/* The wd33c93 only knows about Group 0, 1, and 5 commands when
...
...
@@ -637,16 +648,16 @@ DB(DB_EXECUTE,printk(")EX-1 "))
if
(
!
(
cmd
->
SCp
.
phase
))
{
write_3393_count
(
hostdata
,
cmd
->
SCp
.
this_residual
);
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_BUS
);
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_BUS
);
write1_io
(
0
,
IO_FIFO_WRITE
);
/* clear fifo counter, write mode */
if
(
is_dir_out
(
cmd
))
{
hostdata
->
fifo
=
FI_FIFO_WRITING
;
if
((
i
=
cmd
->
SCp
.
this_residual
)
>
(
IN2000_FIFO_SIZE
-
16
)
)
if
((
i
=
cmd
->
SCp
.
this_residual
)
>
(
IN2000_FIFO_SIZE
-
16
)
)
i
=
IN2000_FIFO_SIZE
-
16
;
cmd
->
SCp
.
have_data_in
=
i
;
/* this much data in fifo */
i
>>=
1
;
/* Gulp. Assuming modulo 2. */
sp
=
(
unsigned
short
*
)
cmd
->
SCp
.
ptr
;
sp
=
(
unsigned
short
*
)
cmd
->
SCp
.
ptr
;
f
=
hostdata
->
io_base
+
IO_FIFO
;
#ifdef FAST_WRITE_IO
...
...
@@ -654,7 +665,7 @@ DB(DB_EXECUTE,printk(")EX-1 "))
FAST_WRITE2_IO
();
#else
while
(
i
--
)
write2_io
(
*
sp
++
,
IO_FIFO
);
write2_io
(
*
sp
++
,
IO_FIFO
);
#endif
...
...
@@ -669,7 +680,7 @@ DB(DB_EXECUTE,printk(")EX-1 "))
FAST_WRITE2_IO
();
#else
while
(
i
--
)
write2_io
(
0
,
IO_FIFO
);
write2_io
(
0
,
IO_FIFO
);
#endif
...
...
@@ -682,12 +693,11 @@ DB(DB_EXECUTE,printk(")EX-1 "))
cmd
->
SCp
.
have_data_in
=
0
;
/* nothing transferred yet */
}
}
else
{
write_3393_count
(
hostdata
,
0
);
/* this guarantees a DATA_PHASE interrupt */
}
else
{
write_3393_count
(
hostdata
,
0
);
/* this guarantees a DATA_PHASE interrupt */
}
hostdata
->
state
=
S_RUNNING_LEVEL2
;
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
}
/*
...
...
@@ -697,34 +707,32 @@ 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
(
uchar
*
buf
,
int
cnt
,
int
data_in_dir
,
struct
IN2000_hostdata
*
hostdata
)
static
void
transfer_pio
(
uchar
*
buf
,
int
cnt
,
int
data_in_dir
,
struct
IN2000_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_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_POLLED
);
write_3393_count
(
hostdata
,
cnt
);
write_3393_cmd
(
hostdata
,
WD_CMD_TRANS_INFO
);
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_POLLED
);
write_3393_count
(
hostdata
,
cnt
);
write_3393_cmd
(
hostdata
,
WD_CMD_TRANS_INFO
);
if
(
data_in_dir
)
{
do
{
asr
=
READ_AUX_STAT
();
if
(
asr
&
ASR_DBR
)
*
buf
++
=
read_3393
(
hostdata
,
WD_DATA
);
*
buf
++
=
read_3393
(
hostdata
,
WD_DATA
);
}
while
(
!
(
asr
&
ASR_INT
));
}
else
{
}
else
{
do
{
asr
=
READ_AUX_STAT
();
if
(
asr
&
ASR_DBR
)
write_3393
(
hostdata
,
WD_DATA
,
*
buf
++
);
write_3393
(
hostdata
,
WD_DATA
,
*
buf
++
);
}
while
(
!
(
asr
&
ASR_INT
));
}
...
...
@@ -739,14 +747,14 @@ DB(DB_TRANSFER,printk("(%p,%d,%s)",buf,cnt,data_in_dir?"in":"out"))
static
void
transfer_bytes
(
Scsi_Cmnd
*
cmd
,
int
data_in_dir
)
static
void
transfer_bytes
(
Scsi_Cmnd
*
cmd
,
int
data_in_dir
)
{
struct
IN2000_hostdata
*
hostdata
;
unsigned
short
*
sp
;
unsigned
short
f
;
int
i
;
struct
IN2000_hostdata
*
hostdata
;
unsigned
short
*
sp
;
unsigned
short
f
;
int
i
;
hostdata
=
(
struct
IN2000_hostdata
*
)
cmd
->
host
->
hostdata
;
hostdata
=
(
struct
IN2000_hostdata
*
)
cmd
->
host
->
hostdata
;
/* Normally, you'd expect 'this_residual' to be non-zero here.
* In a series of scatter-gather transfers, however, this
...
...
@@ -765,25 +773,23 @@ int i;
/* Set up hardware registers */
write_3393
(
hostdata
,
WD_SYNCHRONOUS_TRANSFER
,
hostdata
->
sync_xfer
[
cmd
->
target
]);
write_3393_count
(
hostdata
,
cmd
->
SCp
.
this_residual
);
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_BUS
);
write1_io
(
0
,
IO_FIFO_WRITE
);
/* zero counter, assume write */
write_3393
(
hostdata
,
WD_SYNCHRONOUS_TRANSFER
,
hostdata
->
sync_xfer
[
cmd
->
target
]);
write_3393_count
(
hostdata
,
cmd
->
SCp
.
this_residual
);
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_BUS
);
write1_io
(
0
,
IO_FIFO_WRITE
);
/* zero counter, assume write */
/* Reading is easy. Just issue the command and return - we'll
* get an interrupt later when we have actual data to worry about.
*/
if
(
data_in_dir
)
{
write1_io
(
0
,
IO_FIFO_READ
);
if
((
hostdata
->
level2
>=
L2_DATA
)
||
(
hostdata
->
level2
==
L2_BASIC
&&
cmd
->
SCp
.
phase
==
0
))
{
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x45
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
write1_io
(
0
,
IO_FIFO_READ
);
if
((
hostdata
->
level2
>=
L2_DATA
)
||
(
hostdata
->
level2
==
L2_BASIC
&&
cmd
->
SCp
.
phase
==
0
))
{
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x45
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
hostdata
->
state
=
S_RUNNING_LEVEL2
;
}
else
write_3393_cmd
(
hostdata
,
WD_CMD_TRANS_INFO
);
}
else
write_3393_cmd
(
hostdata
,
WD_CMD_TRANS_INFO
);
hostdata
->
fifo
=
FI_FIFO_READING
;
cmd
->
SCp
.
have_data_in
=
0
;
return
;
...
...
@@ -794,16 +800,14 @@ int i;
* write any bytes that don't make it at this stage.
*/
if
((
hostdata
->
level2
>=
L2_DATA
)
||
(
hostdata
->
level2
==
L2_BASIC
&&
cmd
->
SCp
.
phase
==
0
))
{
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x45
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
if
((
hostdata
->
level2
>=
L2_DATA
)
||
(
hostdata
->
level2
==
L2_BASIC
&&
cmd
->
SCp
.
phase
==
0
))
{
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x45
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
hostdata
->
state
=
S_RUNNING_LEVEL2
;
}
else
write_3393_cmd
(
hostdata
,
WD_CMD_TRANS_INFO
);
}
else
write_3393_cmd
(
hostdata
,
WD_CMD_TRANS_INFO
);
hostdata
->
fifo
=
FI_FIFO_WRITING
;
sp
=
(
unsigned
short
*
)
cmd
->
SCp
.
ptr
;
sp
=
(
unsigned
short
*
)
cmd
->
SCp
.
ptr
;
if
((
i
=
cmd
->
SCp
.
this_residual
)
>
IN2000_FIFO_SIZE
)
i
=
IN2000_FIFO_SIZE
;
...
...
@@ -816,7 +820,7 @@ int i;
FAST_WRITE2_IO
();
#else
while
(
i
--
)
write2_io
(
*
sp
++
,
IO_FIFO
);
write2_io
(
*
sp
++
,
IO_FIFO
);
#endif
...
...
@@ -829,19 +833,19 @@ int i;
* but it _does_ need to be able to compile and run in an SMP kernel.)
*/
static
void
in2000_intr
(
int
irqnum
,
void
*
dev_id
,
struct
pt_regs
*
ptregs
)
static
void
in2000_intr
(
int
irqnum
,
void
*
dev_id
,
struct
pt_regs
*
ptregs
)
{
struct
Scsi_Host
*
instance
=
dev_id
;
struct
IN2000_hostdata
*
hostdata
;
Scsi_Cmnd
*
patch
,
*
cmd
;
uchar
asr
,
sr
,
phs
,
id
,
lun
,
*
ucp
,
msg
;
int
i
,
j
;
unsigned
long
length
;
unsigned
short
*
sp
;
unsigned
short
f
;
unsigned
long
flags
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
struct
Scsi_Host
*
instance
=
dev_id
;
struct
IN2000_hostdata
*
hostdata
;
Scsi_Cmnd
*
patch
,
*
cmd
;
uchar
asr
,
sr
,
phs
,
id
,
lun
,
*
ucp
,
msg
;
int
i
,
j
;
unsigned
long
length
;
unsigned
short
*
sp
;
unsigned
short
f
;
unsigned
long
flags
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
/* Get the spin_lock and disable further ints, for SMP */
...
...
@@ -909,14 +913,14 @@ unsigned long flags;
* (Big thanks to Bill Earnest for getting me out of the mud in here.)
*/
cmd
=
(
Scsi_Cmnd
*
)
hostdata
->
connected
;
/* assume we're connected */
CHECK_NULL
(
cmd
,
"fifo_int"
)
cmd
=
(
Scsi_Cmnd
*
)
hostdata
->
connected
;
/* assume we're connected */
CHECK_NULL
(
cmd
,
"fifo_int"
)
if
(
hostdata
->
fifo
==
FI_FIFO_READING
)
{
DB
(
DB_FIFO
,
printk
(
"{R:%02x} "
,
read1_io
(
IO_FIFO_COUNT
)))
DB
(
DB_FIFO
,
printk
(
"{R:%02x} "
,
read1_io
(
IO_FIFO_COUNT
)))
sp
=
(
unsigned
short
*
)
(
cmd
->
SCp
.
ptr
+
cmd
->
SCp
.
have_data_in
);
sp
=
(
unsigned
short
*
)
(
cmd
->
SCp
.
ptr
+
cmd
->
SCp
.
have_data_in
);
i
=
read1_io
(
IO_FIFO_COUNT
)
&
0xfe
;
i
<<=
2
;
/* # of words waiting in the fifo */
f
=
hostdata
->
io_base
+
IO_FIFO
;
...
...
@@ -930,14 +934,14 @@ DB(DB_FIFO,printk("{R:%02x} ",read1_io(IO_FIFO_COUNT)))
#endif
i
=
sp
-
(
unsigned
short
*
)
(
cmd
->
SCp
.
ptr
+
cmd
->
SCp
.
have_data_in
);
i
=
sp
-
(
unsigned
short
*
)
(
cmd
->
SCp
.
ptr
+
cmd
->
SCp
.
have_data_in
);
i
<<=
1
;
cmd
->
SCp
.
have_data_in
+=
i
;
}
else
if
(
hostdata
->
fifo
==
FI_FIFO_WRITING
)
{
DB
(
DB_FIFO
,
printk
(
"{W:%02x} "
,
read1_io
(
IO_FIFO_COUNT
)))
DB
(
DB_FIFO
,
printk
(
"{W:%02x} "
,
read1_io
(
IO_FIFO_COUNT
)))
/* If all bytes have been written to the fifo, flush out the stragglers.
* Note that while writing 16 dummy words seems arbitrary, we don't
...
...
@@ -949,11 +953,10 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
* UPDATE: Bill says this is exactly what Always does, so there.
* More thanks due him for help in this section.
*/
if
(
cmd
->
SCp
.
this_residual
==
cmd
->
SCp
.
have_data_in
)
{
i
=
16
;
while
(
i
--
)
/* write 32 dummy bytes */
write2_io
(
0
,
IO_FIFO
);
write2_io
(
0
,
IO_FIFO
);
}
/* If there are still bytes left in the SCSI buffer, write as many as we
...
...
@@ -961,16 +964,16 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
*/
else
{
sp
=
(
unsigned
short
*
)
(
cmd
->
SCp
.
ptr
+
cmd
->
SCp
.
have_data_in
);
sp
=
(
unsigned
short
*
)
(
cmd
->
SCp
.
ptr
+
cmd
->
SCp
.
have_data_in
);
i
=
cmd
->
SCp
.
this_residual
-
cmd
->
SCp
.
have_data_in
;
/* bytes yet to go */
j
=
read1_io
(
IO_FIFO_COUNT
)
&
0xfe
;
j
<<=
2
;
/* how many words the fifo has room for */
if
((
j
<<
1
)
>
i
)
j
=
(
i
>>
1
);
while
(
j
--
)
write2_io
(
*
sp
++
,
IO_FIFO
);
write2_io
(
*
sp
++
,
IO_FIFO
);
i
=
sp
-
(
unsigned
short
*
)
(
cmd
->
SCp
.
ptr
+
cmd
->
SCp
.
have_data_in
);
i
=
sp
-
(
unsigned
short
*
)
(
cmd
->
SCp
.
ptr
+
cmd
->
SCp
.
have_data_in
);
i
<<=
1
;
cmd
->
SCp
.
have_data_in
+=
i
;
}
...
...
@@ -992,9 +995,9 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
* detailed info from FIFO_READING and FIFO_WRITING (see below).
*/
cmd
=
(
Scsi_Cmnd
*
)
hostdata
->
connected
;
/* assume we're connected */
sr
=
read_3393
(
hostdata
,
WD_SCSI_STATUS
);
/* clear the interrupt */
phs
=
read_3393
(
hostdata
,
WD_COMMAND_PHASE
);
cmd
=
(
Scsi_Cmnd
*
)
hostdata
->
connected
;
/* assume we're connected */
sr
=
read_3393
(
hostdata
,
WD_SCSI_STATUS
);
/* clear the interrupt */
phs
=
read_3393
(
hostdata
,
WD_COMMAND_PHASE
);
if
(
!
cmd
&&
(
sr
!=
CSR_RESEL_AM
&&
sr
!=
CSR_TIMEOUT
&&
sr
!=
CSR_SELECT
))
{
printk
(
"
\n
NR:wd-intr-1
\n
"
);
...
...
@@ -1005,7 +1008,7 @@ DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT)))
return
;
}
DB
(
DB_INTR
,
printk
(
"{%02x:%02x-"
,
asr
,
sr
))
DB
(
DB_INTR
,
printk
(
"{%02x:%02x-"
,
asr
,
sr
))
/* After starting a FIFO-based transfer, the next _WD3393_ interrupt is
* guaranteed to be in response to the completion of the transfer.
...
...
@@ -1019,12 +1022,11 @@ DB(DB_INTR,printk("{%02x:%02x-",asr,sr))
* After doing whatever is necessary with the fifo, we go on and
* service the WD3393 interrupt normally.
*/
if
(
hostdata
->
fifo
==
FI_FIFO_READING
)
{
/* buffer index = start-of-buffer + #-of-bytes-already-read */
sp
=
(
unsigned
short
*
)
(
cmd
->
SCp
.
ptr
+
cmd
->
SCp
.
have_data_in
);
sp
=
(
unsigned
short
*
)
(
cmd
->
SCp
.
ptr
+
cmd
->
SCp
.
have_data_in
);
/* bytes remaining in fifo = (total-wanted - #-not-got) - #-already-read */
...
...
@@ -1046,7 +1048,7 @@ DB(DB_INTR,printk("{%02x:%02x-",asr,sr))
cmd
->
SCp
.
this_residual
=
read_3393_count
(
hostdata
);
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
))
}
...
...
@@ -1056,7 +1058,7 @@ DB(DB_TRANSFER,printk("(%p,%d)",cmd->SCp.ptr,cmd->SCp.this_residual))
cmd
->
SCp
.
this_residual
=
read_3393_count
(
hostdata
);
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
))
}
...
...
@@ -1065,13 +1067,13 @@ DB(DB_TRANSFER,printk("(%p,%d)",cmd->SCp.ptr,cmd->SCp.this_residual))
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 */
CHECK_NULL
(
cmd
,
"csr_timeout"
)
cmd
=
(
Scsi_Cmnd
*
)
hostdata
->
selecting
;
/* get a valid cmd */
CHECK_NULL
(
cmd
,
"csr_timeout"
)
hostdata
->
selecting
=
NULL
;
}
...
...
@@ -1091,9 +1093,9 @@ CHECK_NULL(cmd,"csr_timeout")
/* 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
;
CHECK_NULL
(
cmd
,
"csr_select"
)
DB
(
DB_INTR
,
printk
(
"SELECT"
))
hostdata
->
connected
=
cmd
=
(
Scsi_Cmnd
*
)
hostdata
->
selecting
;
CHECK_NULL
(
cmd
,
"csr_select"
)
hostdata
->
selecting
=
NULL
;
/* construct an IDENTIFY message with correct disconnect bit */
...
...
@@ -1104,7 +1106,7 @@ CHECK_NULL(cmd,"csr_select")
if
(
hostdata
->
sync_stat
[
cmd
->
target
]
==
SS_FIRST
)
{
#ifdef SYNC_DEBUG
printk
(
" sending SDTR "
);
printk
(
" sending SDTR "
);
#endif
hostdata
->
sync_stat
[
cmd
->
target
]
=
SS_WAITING
;
...
...
@@ -1114,31 +1116,30 @@ printk(" sending SDTR ");
hostdata
->
outgoing_msg
[
1
]
=
EXTENDED_MESSAGE
;
hostdata
->
outgoing_msg
[
2
]
=
3
;
hostdata
->
outgoing_msg
[
3
]
=
EXTENDED_SDTR
;
hostdata
->
outgoing_msg
[
4
]
=
OPTIMUM_SX_PER
/
4
;
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
;
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
(
cmd
,
DATA_IN_DIR
);
if
(
hostdata
->
state
!=
S_RUNNING_LEVEL2
)
hostdata
->
state
=
S_CONNECTED
;
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
(
cmd
,
DATA_OUT_DIR
);
if
(
hostdata
->
state
!=
S_RUNNING_LEVEL2
)
hostdata
->
state
=
S_CONNECTED
;
...
...
@@ -1147,41 +1148,40 @@ DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
/* 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
))
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
(
cmd
->
cmnd
,
cmd
->
cmd_len
,
DATA_OUT_DIR
,
hostdata
);
hostdata
->
state
=
S_CONNECTED
;
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
(
hostdata
);
DB
(
DB_INTR
,
printk
(
"%02x"
,
cmd
->
SCp
.
Status
))
DB
(
DB_INTR
,
printk
(
"%02x"
,
cmd
->
SCp
.
Status
))
if
(
hostdata
->
level2
>=
L2_BASIC
)
{
sr
=
read_3393
(
hostdata
,
WD_SCSI_STATUS
);
/* clear interrupt */
sr
=
read_3393
(
hostdata
,
WD_SCSI_STATUS
);
/* clear interrupt */
hostdata
->
state
=
S_RUNNING_LEVEL2
;
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x50
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
}
else
{
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x50
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
}
else
{
hostdata
->
state
=
S_CONNECTED
;
}
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
(
hostdata
);
sr
=
read_3393
(
hostdata
,
WD_SCSI_STATUS
);
/* clear interrupt */
sr
=
read_3393
(
hostdata
,
WD_SCSI_STATUS
);
/* clear interrupt */
hostdata
->
incoming_msg
[
hostdata
->
incoming_ptr
]
=
msg
;
if
(
hostdata
->
incoming_msg
[
0
]
==
EXTENDED_MESSAGE
)
...
...
@@ -1193,64 +1193,62 @@ DB(DB_INTR,printk("MSG_IN="))
switch
(
msg
)
{
case
COMMAND_COMPLETE
:
DB
(
DB_INTR
,
printk
(
"CCMP-%ld"
,
cmd
->
pid
))
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
DB
(
DB_INTR
,
printk
(
"CCMP-%ld"
,
cmd
->
pid
))
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
hostdata
->
state
=
S_PRE_CMP_DISC
;
break
;
case
SAVE_POINTERS
:
DB
(
DB_INTR
,
printk
(
"SDP"
))
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
DB
(
DB_INTR
,
printk
(
"SDP"
))
write_3393_cmd
(
hostdata
,
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_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x45
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x45
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
hostdata
->
state
=
S_RUNNING_LEVEL2
;
}
else
{
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
}
else
{
write_3393_cmd
(
hostdata
,
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_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
write_3393_cmd
(
hostdata
,
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
;
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
write_3393_cmd
(
hostdata
,
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? */
if
((
hostdata
->
incoming_ptr
>=
2
)
&&
(
hostdata
->
incoming_ptr
==
(
ucp
[
1
]
+
1
)))
{
if
((
hostdata
->
incoming_ptr
>=
2
)
&&
(
hostdata
->
incoming_ptr
==
(
ucp
[
1
]
+
1
)))
{
switch
(
ucp
[
2
])
{
/* what's the EXTENDED code? */
case
EXTENDED_SDTR
:
id
=
calc_sync_xfer
(
ucp
[
3
],
ucp
[
4
]);
id
=
calc_sync_xfer
(
ucp
[
3
],
ucp
[
4
]);
if
(
hostdata
->
sync_stat
[
cmd
->
target
]
!=
SS_WAITING
)
{
/* A device has sent an unsolicited SDTR message; rather than go
...
...
@@ -1262,43 +1260,41 @@ printk("%02x",ucp[hostdata->incoming_ptr]);
* specifically ask for sync transfers, we won't do any.
*/
write_3393_cmd
(
hostdata
,
WD_CMD_ASSERT_ATN
);
/* want MESS_OUT */
write_3393_cmd
(
hostdata
,
WD_CMD_ASSERT_ATN
);
/* want MESS_OUT */
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
[
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
]
=
calc_sync_xfer
(
hostdata
->
default_sx_per
/
4
,
0
);
}
else
{
hostdata
->
sync_xfer
[
cmd
->
target
]
=
id
;
}
#ifdef SYNC_DEBUG
printk
(
"sync_xfer=%02x"
,
hostdata
->
sync_xfer
[
cmd
->
target
]);
printk
(
"sync_xfer=%02x"
,
hostdata
->
sync_xfer
[
cmd
->
target
]);
#endif
hostdata
->
sync_stat
[
cmd
->
target
]
=
SS_SET
;
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
hostdata
->
state
=
S_CONNECTED
;
break
;
case
EXTENDED_WDTR
:
write_3393_cmd
(
hostdata
,
WD_CMD_ASSERT_ATN
);
/* want MESS_OUT */
write_3393_cmd
(
hostdata
,
WD_CMD_ASSERT_ATN
);
/* want MESS_OUT */
printk
(
"sending WDTR "
);
hostdata
->
outgoing_msg
[
0
]
=
EXTENDED_MESSAGE
;
hostdata
->
outgoing_msg
[
1
]
=
2
;
hostdata
->
outgoing_msg
[
2
]
=
EXTENDED_WDTR
;
hostdata
->
outgoing_msg
[
3
]
=
0
;
/* 8 bit transfer width */
hostdata
->
outgoing_len
=
4
;
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
hostdata
->
state
=
S_CONNECTED
;
break
;
default:
write_3393_cmd
(
hostdata
,
WD_CMD_ASSERT_ATN
);
/* want MESS_OUT */
printk
(
"Rejecting Unknown Extended Message(%02x). "
,
ucp
[
2
]);
write_3393_cmd
(
hostdata
,
WD_CMD_ASSERT_ATN
);
/* want MESS_OUT */
printk
(
"Rejecting Unknown Extended Message(%02x). "
,
ucp
[
2
]);
hostdata
->
outgoing_msg
[
0
]
=
MESSAGE_REJECT
;
hostdata
->
outgoing_len
=
1
;
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
hostdata
->
state
=
S_CONNECTED
;
break
;
}
...
...
@@ -1309,17 +1305,17 @@ printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);
else
{
hostdata
->
incoming_ptr
++
;
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
hostdata
->
state
=
S_CONNECTED
;
}
break
;
default:
printk
(
"Rejecting Unknown Message(%02x) "
,
msg
);
write_3393_cmd
(
hostdata
,
WD_CMD_ASSERT_ATN
);
/* want MESS_OUT */
printk
(
"Rejecting Unknown Message(%02x) "
,
msg
);
write_3393_cmd
(
hostdata
,
WD_CMD_ASSERT_ATN
);
/* want MESS_OUT */
hostdata
->
outgoing_msg
[
0
]
=
MESSAGE_REJECT
;
hostdata
->
outgoing_len
=
1
;
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
hostdata
->
state
=
S_CONNECTED
;
}
break
;
...
...
@@ -1333,12 +1329,12 @@ printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);
* have been turned off for the command that just completed.
*/
write_3393
(
hostdata
,
WD_SOURCE_ID
,
SRCID_ER
);
write_3393
(
hostdata
,
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_3393
(
hostdata
,
WD_TARGET_LUN
);
DB
(
DB_INTR
,
printk
(
":%d.%d"
,
cmd
->
SCp
.
Status
,
lun
))
lun
=
read_3393
(
hostdata
,
WD_TARGET_LUN
);
DB
(
DB_INTR
,
printk
(
":%d.%d"
,
cmd
->
SCp
.
Status
,
lun
))
hostdata
->
connected
=
NULL
;
hostdata
->
busy
[
cmd
->
target
]
&=
~
(
1
<<
cmd
->
lun
);
hostdata
->
state
=
S_UNCONNECTED
;
...
...
@@ -1355,9 +1351,8 @@ DB(DB_INTR,printk(":%d.%d",cmd->SCp.Status,lun))
*/
in2000_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
);
}
break
;
...
...
@@ -1365,17 +1360,17 @@ DB(DB_INTR,printk(":%d.%d",cmd->SCp.Status,lun))
/* 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_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x41
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x41
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
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
...
...
@@ -1389,14 +1384,12 @@ 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
(
hostdata
->
outgoing_msg
,
hostdata
->
outgoing_len
,
DATA_OUT_DIR
,
hostdata
);
DB
(
DB_INTR
,
printk
(
"%02x"
,
hostdata
->
outgoing_msg
[
0
]))
transfer_pio
(
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
;
break
;
...
...
@@ -1417,7 +1410,7 @@ DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
* have been turned off for the command that just completed.
*/
write_3393
(
hostdata
,
WD_SOURCE_ID
,
SRCID_ER
);
write_3393
(
hostdata
,
WD_SOURCE_ID
,
SRCID_ER
);
if
(
cmd
==
NULL
)
{
printk
(
" - Already disconnected! "
);
hostdata
->
state
=
S_UNCONNECTED
;
...
...
@@ -1426,7 +1419,7 @@ DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
spin_unlock_irqrestore
(
instance
->
host_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
->
state
=
S_UNCONNECTED
;
...
...
@@ -1450,8 +1443,8 @@ DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
* have been turned off for the command that just completed.
*/
write_3393
(
hostdata
,
WD_SOURCE_ID
,
SRCID_ER
);
DB
(
DB_INTR
,
printk
(
"DISC-%ld"
,
cmd
->
pid
))
write_3393
(
hostdata
,
WD_SOURCE_ID
,
SRCID_ER
);
DB
(
DB_INTR
,
printk
(
"DISC-%ld"
,
cmd
->
pid
))
if
(
cmd
==
NULL
)
{
printk
(
" - Already disconnected! "
);
hostdata
->
state
=
S_UNCONNECTED
;
...
...
@@ -1461,7 +1454,7 @@ DB(DB_INTR,printk("DISC-%ld",cmd->pid))
hostdata
->
connected
=
NULL
;
hostdata
->
busy
[
cmd
->
target
]
&=
~
(
1
<<
cmd
->
lun
);
hostdata
->
state
=
S_UNCONNECTED
;
DB
(
DB_INTR
,
printk
(
":%d"
,
cmd
->
SCp
.
Status
))
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
...
...
@@ -1470,7 +1463,7 @@ DB(DB_INTR,printk(":%d",cmd->SCp.Status))
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
;
...
...
@@ -1494,19 +1487,18 @@ DB(DB_INTR,printk(":%d",cmd->SCp.Status))
case
CSR_RESEL_AM
:
DB
(
DB_INTR
,
printk
(
"RESEL"
))
DB
(
DB_INTR
,
printk
(
"RESEL"
))
/* First we have to make sure this reselection didn't */
/* 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
;
cmd
->
host_scribble
=
(
uchar
*
)
hostdata
->
input_Q
;
hostdata
->
input_Q
=
cmd
;
}
}
...
...
@@ -1516,11 +1508,10 @@ DB(DB_INTR,printk("RESEL"))
if
(
cmd
)
{
if
(
phs
==
0x00
)
{
hostdata
->
busy
[
cmd
->
target
]
&=
~
(
1
<<
cmd
->
lun
);
cmd
->
host_scribble
=
(
uchar
*
)
hostdata
->
input_Q
;
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
"
);
}
...
...
@@ -1530,7 +1521,7 @@ DB(DB_INTR,printk("RESEL"))
/* OK - find out which device reselected us. */
id
=
read_3393
(
hostdata
,
WD_SOURCE_ID
);
id
=
read_3393
(
hostdata
,
WD_SOURCE_ID
);
id
&=
SRCID_MASK
;
/* and extract the lun from the ID message. (Note that we don't
...
...
@@ -1538,26 +1529,26 @@ DB(DB_INTR,printk("RESEL"))
* not the right way to go, but....)
*/
lun
=
read_3393
(
hostdata
,
WD_DATA
);
lun
=
read_3393
(
hostdata
,
WD_DATA
);
if
(
hostdata
->
level2
<
L2_RESELECT
)
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
write_3393_cmd
(
hostdata
,
WD_CMD_NEGATE_ACK
);
lun
&=
7
;
/* 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
)
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
);
break
;
}
...
...
@@ -1566,7 +1557,7 @@ DB(DB_INTR,printk("RESEL"))
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[]'
...
...
@@ -1575,28 +1566,27 @@ DB(DB_INTR,printk("RESEL"))
*/
if
(
is_dir_out
(
cmd
))
write_3393
(
hostdata
,
WD_DESTINATION_ID
,
cmd
->
target
);
write_3393
(
hostdata
,
WD_DESTINATION_ID
,
cmd
->
target
);
else
write_3393
(
hostdata
,
WD_DESTINATION_ID
,
cmd
->
target
|
DSTID_DPD
);
write_3393
(
hostdata
,
WD_DESTINATION_ID
,
cmd
->
target
|
DSTID_DPD
);
if
(
hostdata
->
level2
>=
L2_RESELECT
)
{
write_3393_count
(
hostdata
,
0
);
/* we want a DATA_PHASE interrupt */
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x45
);
write_3393_cmd
(
hostdata
,
WD_CMD_SEL_ATN_XFER
);
write_3393_count
(
hostdata
,
0
);
/* we want a DATA_PHASE interrupt */
write_3393
(
hostdata
,
WD_COMMAND_PHASE
,
0x45
);
write_3393_cmd
(
hostdata
,
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
))
break
;
default:
printk
(
"--UNKNOWN INTERRUPT:%02x:%02x:%02x--"
,
asr
,
sr
,
phs
);
printk
(
"--UNKNOWN INTERRUPT:%02x:%02x:%02x--"
,
asr
,
sr
,
phs
);
}
write1_io
(
0
,
IO_LED_OFF
);
DB
(
DB_INTR
,
printk
(
"} "
))
DB
(
DB_INTR
,
printk
(
"} "
))
/* release the SMP spin_lock and restore irq state */
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
...
...
@@ -1615,65 +1605,61 @@ DB(DB_INTR,printk("} "))
static
int
reset_hardware
(
struct
Scsi_Host
*
instance
,
int
type
)
{
struct
IN2000_hostdata
*
hostdata
;
int
qt
,
x
;
struct
IN2000_hostdata
*
hostdata
;
int
qt
,
x
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
write1_io
(
0
,
IO_LED_ON
);
if
(
type
==
RESET_CARD_AND_BUS
)
{
write1_io
(
0
,
IO_CARD_RESET
);
write1_io
(
0
,
IO_CARD_RESET
);
x
=
read1_io
(
IO_HARDWARE
);
}
x
=
read_3393
(
hostdata
,
WD_SCSI_STATUS
);
/* clear any WD intrpt */
write_3393
(
hostdata
,
WD_OWN_ID
,
instance
->
this_id
|
OWNID_EAF
|
OWNID_RAF
|
OWNID_FS_8
);
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_POLLED
);
write_3393
(
hostdata
,
WD_SYNCHRONOUS_TRANSFER
,
calc_sync_xfer
(
hostdata
->
default_sx_per
/
4
,
DEFAULT_SX_OFF
));
x
=
read_3393
(
hostdata
,
WD_SCSI_STATUS
);
/* clear any WD intrpt */
write_3393
(
hostdata
,
WD_OWN_ID
,
instance
->
this_id
|
OWNID_EAF
|
OWNID_RAF
|
OWNID_FS_8
);
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_POLLED
);
write_3393
(
hostdata
,
WD_SYNCHRONOUS_TRANSFER
,
calc_sync_xfer
(
hostdata
->
default_sx_per
/
4
,
DEFAULT_SX_OFF
));
write1_io
(
0
,
IO_FIFO_WRITE
);
/* clear fifo counter */
write1_io
(
0
,
IO_FIFO_READ
);
/* start fifo out in read mode */
write_3393
(
hostdata
,
WD_COMMAND
,
WD_CMD_RESET
);
write1_io
(
0
,
IO_FIFO_WRITE
);
/* clear fifo counter */
write1_io
(
0
,
IO_FIFO_READ
);
/* start fifo out in read mode */
write_3393
(
hostdata
,
WD_COMMAND
,
WD_CMD_RESET
);
/* FIXME: timeout ?? */
while
(
!
(
READ_AUX_STAT
()
&
ASR_INT
))
cpu_relax
();
/* wait for RESET to complete */
x
=
read_3393
(
hostdata
,
WD_SCSI_STATUS
);
/* clear interrupt */
x
=
read_3393
(
hostdata
,
WD_SCSI_STATUS
);
/* clear interrupt */
write_3393
(
hostdata
,
WD_QUEUE_TAG
,
0xa5
);
/* any random number */
qt
=
read_3393
(
hostdata
,
WD_QUEUE_TAG
);
write_3393
(
hostdata
,
WD_QUEUE_TAG
,
0xa5
);
/* any random number */
qt
=
read_3393
(
hostdata
,
WD_QUEUE_TAG
);
if
(
qt
==
0xa5
)
{
x
|=
B_FLAG
;
write_3393
(
hostdata
,
WD_QUEUE_TAG
,
0
);
write_3393
(
hostdata
,
WD_QUEUE_TAG
,
0
);
}
write_3393
(
hostdata
,
WD_TIMEOUT_PERIOD
,
TIMEOUT_PERIOD_VALUE
);
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_POLLED
);
write_3393
(
hostdata
,
WD_TIMEOUT_PERIOD
,
TIMEOUT_PERIOD_VALUE
);
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_POLLED
);
write1_io
(
0
,
IO_LED_OFF
);
return
x
;
}
static
int
in2000_bus_reset
(
Scsi_Cmnd
*
cmd
)
static
int
in2000_bus_reset
(
Scsi_Cmnd
*
cmd
)
{
unsigned
long
flags
;
struct
Scsi_Host
*
instance
;
struct
IN2000_hostdata
*
hostdata
;
int
x
;
struct
Scsi_Host
*
instance
;
struct
IN2000_hostdata
*
hostdata
;
int
x
;
instance
=
cmd
->
host
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
printk
(
KERN_WARNING
"scsi%d: Reset. "
,
instance
->
host_no
);
spin_lock_irqsave
(
instance
->
host_lock
,
flags
);
/* do scsi-reset here */
reset_hardware
(
instance
,
RESET_CARD_AND_BUS
);
for
(
x
=
0
;
x
<
8
;
x
++
)
{
hostdata
->
busy
[
x
]
=
0
;
hostdata
->
sync_xfer
[
x
]
=
calc_sync_xfer
(
DEFAULT_SX_PER
/
4
,
DEFAULT_SX_OFF
);
hostdata
->
sync_xfer
[
x
]
=
calc_sync_xfer
(
DEFAULT_SX_PER
/
4
,
DEFAULT_SX_OFF
);
hostdata
->
sync_stat
[
x
]
=
SS_UNSET
;
/* using default sync values */
}
hostdata
->
input_Q
=
NULL
;
...
...
@@ -1686,45 +1672,40 @@ int x;
hostdata
->
outgoing_len
=
0
;
cmd
->
result
=
DID_RESET
<<
16
;
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
return
SUCCESS
;
}
static
int
in2000_host_reset
(
Scsi_Cmnd
*
cmd
)
static
int
in2000_host_reset
(
Scsi_Cmnd
*
cmd
)
{
return
FAILED
;
}
static
int
in2000_device_reset
(
Scsi_Cmnd
*
cmd
)
static
int
in2000_device_reset
(
Scsi_Cmnd
*
cmd
)
{
return
FAILED
;
}
static
int
in2000_abort
(
Scsi_Cmnd
*
cmd
)
static
int
in2000_abort
(
Scsi_Cmnd
*
cmd
)
{
struct
Scsi_Host
*
instance
;
struct
IN2000_hostdata
*
hostdata
;
Scsi_Cmnd
*
tmp
,
*
prev
;
unsigned
long
flags
;
uchar
sr
,
asr
;
unsigned
long
timeout
;
struct
Scsi_Host
*
instance
;
struct
IN2000_hostdata
*
hostdata
;
Scsi_Cmnd
*
tmp
,
*
prev
;
uchar
sr
,
asr
;
unsigned
long
timeout
;
instance
=
cmd
->
host
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
printk
(
KERN_DEBUG
"scsi%d: Abort-"
,
instance
->
host_no
);
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
));
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
));
/*
* Case 1 : If the command hasn't been issued yet, we simply remove it
* from the inout_Q.
*/
spin_lock_irqsave
(
instance
->
host_lock
,
flags
);
tmp
=
(
Scsi_Cmnd
*
)
hostdata
->
input_Q
;
tmp
=
(
Scsi_Cmnd
*
)
hostdata
->
input_Q
;
prev
=
0
;
while
(
tmp
)
{
if
(
tmp
==
cmd
)
{
...
...
@@ -1732,14 +1713,12 @@ unsigned long timeout;
prev
->
host_scribble
=
cmd
->
host_scribble
;
cmd
->
host_scribble
=
NULL
;
cmd
->
result
=
DID_ABORT
<<
16
;
printk
(
KERN_WARNING
"scsi%d: Abort - removing command %ld from input_Q. "
,
instance
->
host_no
,
cmd
->
pid
);
printk
(
KERN_WARNING
"scsi%d: Abort - removing command %ld from input_Q. "
,
instance
->
host_no
,
cmd
->
pid
);
cmd
->
scsi_done
(
cmd
);
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
return
SUCCESS
;
}
prev
=
tmp
;
tmp
=
(
Scsi_Cmnd
*
)
tmp
->
host_scribble
;
tmp
=
(
Scsi_Cmnd
*
)
tmp
->
host_scribble
;
}
/*
...
...
@@ -1755,8 +1734,7 @@ unsigned long timeout;
if
(
hostdata
->
connected
==
cmd
)
{
printk
(
KERN_WARNING
"scsi%d: Aborting connected command %ld - "
,
instance
->
host_no
,
cmd
->
pid
);
printk
(
KERN_WARNING
"scsi%d: Aborting connected command %ld - "
,
instance
->
host_no
,
cmd
->
pid
);
printk
(
"sending wd33c93 ABORT command - "
);
write_3393
(
hostdata
,
WD_CONTROL
,
CTRL_IDI
|
CTRL_EDI
|
CTRL_POLLED
);
...
...
@@ -1772,8 +1750,7 @@ unsigned long timeout;
read_3393
(
hostdata
,
WD_DATA
);
}
while
(
!
(
asr
&
ASR_INT
)
&&
timeout
--
>
0
);
sr
=
read_3393
(
hostdata
,
WD_SCSI_STATUS
);
printk
(
"asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - "
,
asr
,
sr
,
read_3393_count
(
hostdata
),
timeout
);
printk
(
"asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - "
,
asr
,
sr
,
read_3393_count
(
hostdata
),
timeout
);
/*
* Abort command processed.
...
...
@@ -1789,7 +1766,7 @@ unsigned long timeout;
while
((
asr
&
ASR_CIP
)
&&
timeout
--
>
0
)
asr
=
READ_AUX_STAT
();
sr
=
read_3393
(
hostdata
,
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
->
connected
=
NULL
;
...
...
@@ -1797,9 +1774,9 @@ unsigned long timeout;
cmd
->
result
=
DID_ABORT
<<
16
;
cmd
->
scsi_done
(
cmd
);
in2000_execute
(
instance
);
in2000_execute
(
instance
);
return
SCSI_ABORT_
SUCCESS
;
return
SUCCESS
;
}
/*
...
...
@@ -1808,10 +1785,8 @@ unsigned long timeout;
* an ABORT_SNOOZE and hope for the best...
*/
for
(
tmp
=
(
Scsi_Cmnd
*
)
hostdata
->
disconnected_Q
;
tmp
;
tmp
=
(
Scsi_Cmnd
*
)
tmp
->
host_scribble
)
for
(
tmp
=
(
Scsi_Cmnd
*
)
hostdata
->
disconnected_Q
;
tmp
;
tmp
=
(
Scsi_Cmnd
*
)
tmp
->
host_scribble
)
if
(
cmd
==
tmp
)
{
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
printk
(
KERN_DEBUG
"scsi%d: unable to abort disconnected command.
\n
"
,
instance
->
host_no
);
return
FAILED
;
}
...
...
@@ -1826,11 +1801,9 @@ unsigned long timeout;
* broke.
*/
in2000_execute
(
instance
);
in2000_execute
(
instance
);
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
printk
(
"scsi%d: warning : SCSI command probably completed successfully"
" before abortion. "
,
instance
->
host_no
);
printk
(
"scsi%d: warning : SCSI command probably completed successfully"
" before abortion. "
,
instance
->
host_no
);
return
SUCCESS
;
}
...
...
@@ -1843,12 +1816,12 @@ static char setup_buffer[SETUP_BUFFER_SIZE];
static
char
setup_used
[
MAX_SETUP_ARGS
];
static
int
done_setup
=
0
;
static
void
__init
in2000_setup
(
char
*
str
,
int
*
ints
)
static
void
__init
in2000_setup
(
char
*
str
,
int
*
ints
)
{
int
i
;
char
*
p1
,
*
p2
;
int
i
;
char
*
p1
,
*
p2
;
strncpy
(
setup_buffer
,
str
,
SETUP_BUFFER_SIZE
);
strncpy
(
setup_buffer
,
str
,
SETUP_BUFFER_SIZE
);
setup_buffer
[
SETUP_BUFFER_SIZE
-
1
]
=
'\0'
;
p1
=
setup_buffer
;
i
=
0
;
...
...
@@ -1860,13 +1833,12 @@ char *p1,*p2;
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
;
}
...
...
@@ -1877,10 +1849,10 @@ char *p1,*p2;
static
int
__init
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
)))
...
...
@@ -1895,7 +1867,7 @@ char *cp;
return
++
x
;
cp
++
;
if
((
*
cp
>=
'0'
)
&&
(
*
cp
<=
'9'
))
{
*
val
=
simple_strtoul
(
cp
,
NULL
,
0
);
*
val
=
simple_strtoul
(
cp
,
NULL
,
0
);
}
return
++
x
;
}
...
...
@@ -1912,36 +1884,36 @@ static u32 bios_tab[] in2000__INITDATA = {
0xd0000
,
0xd8000
,
0
};
};
static
const
unsigned
short
base_tab
[]
in2000__INITDATA
=
{
0x220
,
0x200
,
0x110
,
0x100
,
};
};
static
const
int
int_tab
[]
in2000__INITDATA
=
{
15
,
14
,
11
,
10
};
};
static
int
__init
in2000_detect
(
Scsi_Host_Template
*
tpnt
)
{
struct
Scsi_Host
*
instance
;
struct
IN2000_hostdata
*
hostdata
;
int
detect_count
;
int
bios
;
int
x
;
unsigned
short
base
;
uchar
switches
;
uchar
hrev
;
int
flags
;
int
val
;
char
buf
[
32
];
struct
Scsi_Host
*
instance
;
struct
IN2000_hostdata
*
hostdata
;
int
detect_count
;
int
bios
;
int
x
;
unsigned
short
base
;
uchar
switches
;
uchar
hrev
;
int
flags
;
int
val
;
char
buf
[
32
];
/* Thanks to help from Bill Earnest, probing for IN2000 cards is a
* pretty straightforward and fool-proof operation. There are 3
...
...
@@ -1956,14 +1928,14 @@ char buf[32];
*/
if
(
!
done_setup
&&
setup_strings
)
in2000_setup
(
setup_strings
,
0
);
in2000_setup
(
setup_strings
,
0
);
detect_count
=
0
;
for
(
bios
=
0
;
bios_tab
[
bios
];
bios
++
)
{
if
(
check_setup_args
(
"ioport"
,
&
flags
,
&
val
,
buf
))
{
if
(
check_setup_args
(
"ioport"
,
&
flags
,
&
val
,
buf
))
{
base
=
val
;
switches
=
~
inb
(
base
+
IO_SWITCHES
)
&
0xff
;
printk
(
"Forcing IN2000 detection at IOport 0x%x "
,
base
);
printk
(
"Forcing IN2000 detection at IOport 0x%x "
,
base
);
bios
=
2
;
}
/*
...
...
@@ -1971,13 +1943,12 @@ char buf[32];
* for the obvious ID strings. We look for the 2 most common ones and
* hope that they cover all the cases...
*/
else
if
(
isa_readl
(
bios_tab
[
bios
]
+
0x10
)
==
0x41564f4e
||
isa_readl
(
bios_tab
[
bios
]
+
0x30
)
==
0x61776c41
)
{
printk
(
"Found IN2000 BIOS at 0x%x "
,(
unsigned
int
)
bios_tab
[
bios
]);
else
if
(
isa_readl
(
bios_tab
[
bios
]
+
0x10
)
==
0x41564f4e
||
isa_readl
(
bios_tab
[
bios
]
+
0x30
)
==
0x61776c41
)
{
printk
(
"Found IN2000 BIOS at 0x%x "
,
(
unsigned
int
)
bios_tab
[
bios
]);
/* Read the switch image that's mapped into EPROM space */
switches
=
~
((
isa_readb
(
bios_tab
[
bios
]
+
0x20
)
&
0xff
));
switches
=
~
((
isa_readb
(
bios_tab
[
bios
]
+
0x20
)
&
0xff
));
/* Find out where the IO space is */
...
...
@@ -1988,17 +1959,16 @@ char buf[32];
x
=
~
inb
(
base
+
IO_SWITCHES
)
&
0xff
;
if
(
x
!=
switches
)
{
printk
(
"Bad IO signature: %02x vs %02x.
\n
"
,
x
,
switches
);
printk
(
"Bad IO signature: %02x vs %02x.
\n
"
,
x
,
switches
);
continue
;
}
}
else
}
else
continue
;
/* OK. We have a base address for the IO ports - run a few safety checks */
if
(
!
(
switches
&
SW_BIT7
))
{
/* I _think_ all cards do this */
printk
(
"There is no IN-2000 SCSI card at IOport 0x%03x!
\n
"
,
base
);
printk
(
"There is no IN-2000 SCSI card at IOport 0x%03x!
\n
"
,
base
);
continue
;
}
...
...
@@ -2011,7 +1981,7 @@ char buf[32];
/* Bit 2 tells us if interrupts are disabled */
if
(
switches
&
SW_DISINT
)
{
printk
(
"The IN-2000 SCSI card at IOport 0x%03x "
,
base
);
printk
(
"The IN-2000 SCSI card at IOport 0x%03x "
,
base
);
printk
(
"is not configured for interrupt operation!
\n
"
);
printk
(
"This driver requires an interrupt: cancelling detection.
\n
"
);
continue
;
...
...
@@ -2023,19 +1993,17 @@ char buf[32];
tpnt
->
proc_name
=
"in2000"
;
instance
=
scsi_register
(
tpnt
,
sizeof
(
struct
IN2000_hostdata
));
if
(
instance
==
NULL
)
if
(
instance
==
NULL
)
continue
;
detect_count
++
;
if
(
!
instance_list
)
instance_list
=
instance
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
hostdata
=
(
struct
IN2000_hostdata
*
)
instance
->
hostdata
;
instance
->
io_port
=
hostdata
->
io_base
=
base
;
hostdata
->
dip_switch
=
switches
;
hostdata
->
hrev
=
hrev
;
write1_io
(
0
,
IO_FIFO_WRITE
);
/* clear fifo counter */
write1_io
(
0
,
IO_FIFO_READ
);
/* start fifo out in read mode */
write1_io
(
0
,
IO_INTR_MASK
);
/* allow all ints */
write1_io
(
0
,
IO_FIFO_WRITE
);
/* clear fifo counter */
write1_io
(
0
,
IO_FIFO_READ
);
/* start fifo out in read mode */
write1_io
(
0
,
IO_INTR_MASK
);
/* allow all ints */
x
=
int_tab
[(
switches
&
(
SW_INT0
|
SW_INT1
))
>>
SW_INT_SHIFT
];
if
(
request_irq
(
x
,
in2000_intr
,
SA_INTERRUPT
,
"in2000"
,
instance
))
{
printk
(
"in2000_detect: Unable to allocate IRQ.
\n
"
);
...
...
@@ -2048,7 +2016,7 @@ char buf[32];
for
(
x
=
0
;
x
<
8
;
x
++
)
{
hostdata
->
busy
[
x
]
=
0
;
hostdata
->
sync_xfer
[
x
]
=
calc_sync_xfer
(
DEFAULT_SX_PER
/
4
,
DEFAULT_SX_OFF
);
hostdata
->
sync_xfer
[
x
]
=
calc_sync_xfer
(
DEFAULT_SX_PER
/
4
,
DEFAULT_SX_OFF
);
hostdata
->
sync_stat
[
x
]
=
SS_UNSET
;
/* using default sync values */
#ifdef PROC_STATISTICS
hostdata
->
cmd_cnt
[
x
]
=
0
;
...
...
@@ -2071,44 +2039,42 @@ char buf[32];
/* Older BIOS's had a 'sync on/off' switch - use its setting */
if
(
isa_readl
(
bios_tab
[
bios
]
+
0x10
)
==
0x41564f4e
&&
(
switches
&
SW_SYNC_DOS5
))
if
(
isa_readl
(
bios_tab
[
bios
]
+
0x10
)
==
0x41564f4e
&&
(
switches
&
SW_SYNC_DOS5
))
hostdata
->
sync_off
=
0x00
;
/* sync defaults to on */
else
hostdata
->
sync_off
=
0xff
;
/* sync defaults to off */
#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
->
int_cnt
=
0
;
#endif
#endif
if
(
check_setup_args
(
"nosync"
,
&
flags
,
&
val
,
buf
))
if
(
check_setup_args
(
"nosync"
,
&
flags
,
&
val
,
buf
))
hostdata
->
sync_off
=
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
(
"noreset"
,
&
flags
,
&
val
,
buf
))
if
(
check_setup_args
(
"noreset"
,
&
flags
,
&
val
,
buf
))
hostdata
->
args
^=
A_NO_SCSI_RESET
;
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
);
#ifdef PROC_INTERFACE
if
(
check_setup_args
(
"proc"
,
&
flags
,
&
val
,
buf
))
if
(
check_setup_args
(
"proc"
,
&
flags
,
&
val
,
buf
))
hostdata
->
proc
=
val
;
#endif
...
...
@@ -2116,39 +2082,29 @@ char buf[32];
/* FIXME: not strictly needed I think but the called code expects
to be locked */
spin_lock_irqsave
(
instance
->
host_lock
,
flags
);
x
=
reset_hardware
(
instance
,(
hostdata
->
args
&
A_NO_SCSI_RESET
)
?
RESET_CARD
:
RESET_CARD_AND_BUS
);
x
=
reset_hardware
(
instance
,
(
hostdata
->
args
&
A_NO_SCSI_RESET
)
?
RESET_CARD
:
RESET_CARD_AND_BUS
);
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
hostdata
->
microcode
=
read_3393
(
hostdata
,
WD_CDB_1
);
hostdata
->
microcode
=
read_3393
(
hostdata
,
WD_CDB_1
);
if
(
x
&
0x01
)
{
if
(
x
&
B_FLAG
)
hostdata
->
chip
=
C_WD33C93B
;
else
hostdata
->
chip
=
C_WD33C93A
;
}
else
}
else
hostdata
->
chip
=
C_WD33C93
;
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"
);
printk
(
"hardware_ver=%02x chip=%s microcode=%02x
\n
"
,
hrev
,
(
hostdata
->
chip
==
C_WD33C93
)
?
"WD33c93"
:
(
hostdata
->
chip
==
C_WD33C93A
)
?
"WD33c93A"
:
(
hostdata
->
chip
==
C_WD33C93B
)
?
"WD33c93B"
:
"unknown"
,
hostdata
->
microcode
);
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"
);
printk
(
"hardware_ver=%02x chip=%s microcode=%02x
\n
"
,
hrev
,
(
hostdata
->
chip
==
C_WD33C93
)
?
"WD33c93"
:
(
hostdata
->
chip
==
C_WD33C93A
)
?
"WD33c93A"
:
(
hostdata
->
chip
==
C_WD33C93B
)
?
"WD33c93B"
:
"unknown"
,
hostdata
->
microcode
);
#ifdef DEBUGGING_ON
printk
(
"setup_args = "
);
for
(
x
=
0
;
x
<
MAX_SETUP_ARGS
;
x
++
)
printk
(
"%s,"
,
setup_args
[
x
]);
for
(
x
=
0
;
x
<
MAX_SETUP_ARGS
;
x
++
)
printk
(
"%s,"
,
setup_args
[
x
]);
printk
(
"
\n
"
);
#endif
if
(
hostdata
->
sync_off
==
0xff
)
printk
(
"Sync-transfer DISABLED on all devices: ENABLE from command-line
\n
"
);
printk
(
"IN2000 driver version %s - %s
\n
"
,
IN2000_VERSION
,
IN2000_DATE
);
printk
(
"IN2000 driver version %s - %s
\n
"
,
IN2000_VERSION
,
IN2000_DATE
);
}
return
detect_count
;
...
...
@@ -2163,17 +2119,14 @@ static int in2000_release(struct Scsi_Host *shost)
return
0
;
}
/* NOTE: I lifted this function straight out of the old driver,
* and have not tested it. Presumably it does what it's
* supposed to do...
*/
static
int
in2000_biosparam
(
struct
scsi_device
*
sdev
,
struct
block_device
*
bdev
,
sector_t
capacity
,
int
*
iinfo
)
static
int
in2000_biosparam
(
struct
scsi_device
*
sdev
,
struct
block_device
*
bdev
,
sector_t
capacity
,
int
*
iinfo
)
{
int
size
;
int
size
;
size
=
capacity
;
iinfo
[
0
]
=
64
;
...
...
@@ -2187,17 +2140,17 @@ int size;
if
(
iinfo
[
2
]
>
1024
)
{
iinfo
[
0
]
=
64
;
iinfo
[
1
]
=
63
;
iinfo
[
2
]
=
(
unsigned
long
)
capacity
/
(
iinfo
[
0
]
*
iinfo
[
1
]);
iinfo
[
2
]
=
(
unsigned
long
)
capacity
/
(
iinfo
[
0
]
*
iinfo
[
1
]);
}
if
(
iinfo
[
2
]
>
1024
)
{
iinfo
[
0
]
=
128
;
iinfo
[
1
]
=
63
;
iinfo
[
2
]
=
(
unsigned
long
)
capacity
/
(
iinfo
[
0
]
*
iinfo
[
1
]);
iinfo
[
2
]
=
(
unsigned
long
)
capacity
/
(
iinfo
[
0
]
*
iinfo
[
1
]);
}
if
(
iinfo
[
2
]
>
1024
)
{
iinfo
[
0
]
=
255
;
iinfo
[
1
]
=
63
;
iinfo
[
2
]
=
(
unsigned
long
)
capacity
/
(
iinfo
[
0
]
*
iinfo
[
1
]);
iinfo
[
2
]
=
(
unsigned
long
)
capacity
/
(
iinfo
[
0
]
*
iinfo
[
1
]);
}
return
0
;
}
...
...
@@ -2208,21 +2161,21 @@ static int in2000_proc_info(char *buf, char **start, off_t off, int len, int hn,
#ifdef PROC_INTERFACE
char
*
bp
;
char
tbuf
[
128
];
unsigned
long
flags
;
struct
Scsi_Host
*
instance
;
struct
IN2000_hostdata
*
hd
;
Scsi_Cmnd
*
cmd
;
int
x
,
i
;
static
int
stop
=
0
;
char
*
bp
;
char
tbuf
[
128
];
unsigned
long
flags
;
struct
Scsi_Host
*
instance
;
struct
IN2000_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
IN2000_hostdata
*
)
instance
->
hostdata
;
hd
=
(
struct
IN2000_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):
...
...
@@ -2236,36 +2189,31 @@ 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
,
"level2:"
,
7
))
{
hd
->
proc
=
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
;
}
...
...
@@ -2274,81 +2222,74 @@ static int stop = 0;
bp
=
buf
;
*
bp
=
'\0'
;
if
(
hd
->
proc
&
PR_VERSION
)
{
sprintf
(
tbuf
,
"
\n
Version %s - %s. Compiled %s %s"
,
IN2000_VERSION
,
IN2000_DATE
,
__DATE__
,
__TIME__
);
strcat
(
bp
,
tbuf
);
sprintf
(
tbuf
,
"
\n
Version %s - %s. Compiled %s %s"
,
IN2000_VERSION
,
IN2000_DATE
,
__DATE__
,
__TIME__
);
strcat
(
bp
,
tbuf
);
}
if
(
hd
->
proc
&
PR_INFO
)
{
sprintf
(
tbuf
,
"
\n
dip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s"
,
(
hd
->
dip_switch
&
0x7f
),
instance
->
irq
,
hd
->
io_base
,
(
hd
->
dip_switch
&
0x40
)
?
"Yes"
:
"No"
,
(
hd
->
dip_switch
&
0x20
)
?
"Yes"
:
"No"
);
strcat
(
bp
,
tbuf
);
strcat
(
bp
,
"
\n
sync_xfer[] = "
);
for
(
x
=
0
;
x
<
7
;
x
++
)
{
sprintf
(
tbuf
,
"
\t
%02x"
,
hd
->
sync_xfer
[
x
]);
strcat
(
bp
,
tbuf
);
}
strcat
(
bp
,
"
\n
sync_stat[] = "
);
for
(
x
=
0
;
x
<
7
;
x
++
)
{
sprintf
(
tbuf
,
"
\t
%02x"
,
hd
->
sync_stat
[
x
]);
strcat
(
bp
,
tbuf
);
sprintf
(
tbuf
,
"
\n
dip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s"
,
(
hd
->
dip_switch
&
0x7f
),
instance
->
irq
,
hd
->
io_base
,
(
hd
->
dip_switch
&
0x40
)
?
"Yes"
:
"No"
,
(
hd
->
dip_switch
&
0x20
)
?
"Yes"
:
"No"
);
strcat
(
bp
,
tbuf
);
strcat
(
bp
,
"
\n
sync_xfer[] = "
);
for
(
x
=
0
;
x
<
7
;
x
++
)
{
sprintf
(
tbuf
,
"
\t
%02x"
,
hd
->
sync_xfer
[
x
]);
strcat
(
bp
,
tbuf
);
}
strcat
(
bp
,
"
\n
sync_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
,
"
\n
commands issued: "
);
for
(
x
=
0
;
x
<
7
;
x
++
)
{
sprintf
(
tbuf
,
"
\t
%ld"
,
hd
->
cmd_cnt
[
x
]);
strcat
(
bp
,
tbuf
);
strcat
(
bp
,
"
\n
commands issued: "
);
for
(
x
=
0
;
x
<
7
;
x
++
)
{
sprintf
(
tbuf
,
"
\t
%ld"
,
hd
->
cmd_cnt
[
x
]);
strcat
(
bp
,
tbuf
);
}
strcat
(
bp
,
"
\n
disconnects allowed:"
);
for
(
x
=
0
;
x
<
7
;
x
++
)
{
sprintf
(
tbuf
,
"
\t
%ld"
,
hd
->
disc_allowed_cnt
[
x
]);
strcat
(
bp
,
tbuf
);
strcat
(
bp
,
"
\n
disconnects allowed:"
);
for
(
x
=
0
;
x
<
7
;
x
++
)
{
sprintf
(
tbuf
,
"
\t
%ld"
,
hd
->
disc_allowed_cnt
[
x
]);
strcat
(
bp
,
tbuf
);
}
strcat
(
bp
,
"
\n
disconnects done: "
);
for
(
x
=
0
;
x
<
7
;
x
++
)
{
sprintf
(
tbuf
,
"
\t
%ld"
,
hd
->
disc_done_cnt
[
x
]);
strcat
(
bp
,
tbuf
);
strcat
(
bp
,
"
\n
disconnects done: "
);
for
(
x
=
0
;
x
<
7
;
x
++
)
{
sprintf
(
tbuf
,
"
\t
%ld"
,
hd
->
disc_done_cnt
[
x
]);
strcat
(
bp
,
tbuf
);
}
sprintf
(
tbuf
,
"
\n
interrupts:
\t
%ld"
,
hd
->
int_cnt
);
strcat
(
bp
,
tbuf
);
sprintf
(
tbuf
,
"
\n
interrupts:
\t
%ld"
,
hd
->
int_cnt
);
strcat
(
bp
,
tbuf
);
}
#endif
if
(
hd
->
proc
&
PR_CONNECTED
)
{
strcat
(
bp
,
"
\n
connected: "
);
strcat
(
bp
,
"
\n
connected: "
);
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
->
target
,
cmd
->
lun
,
cmd
->
cmnd
[
0
]);
strcat
(
bp
,
tbuf
);
}
}
if
(
hd
->
proc
&
PR_INPUTQ
)
{
strcat
(
bp
,
"
\n
input_Q: "
);
cmd
=
(
Scsi_Cmnd
*
)
hd
->
input_Q
;
strcat
(
bp
,
"
\n
input_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
->
target
,
cmd
->
lun
,
cmd
->
cmnd
[
0
]);
strcat
(
bp
,
tbuf
);
cmd
=
(
Scsi_Cmnd
*
)
cmd
->
host_scribble
;
}
}
if
(
hd
->
proc
&
PR_DISCQ
)
{
strcat
(
bp
,
"
\n
disconnected_Q:"
);
cmd
=
(
Scsi_Cmnd
*
)
hd
->
disconnected_Q
;
strcat
(
bp
,
"
\n
disconnected_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
->
target
,
cmd
->
lun
,
cmd
->
cmnd
[
0
]);
strcat
(
bp
,
tbuf
);
cmd
=
(
Scsi_Cmnd
*
)
cmd
->
host_scribble
;
}
}
if
(
hd
->
proc
&
PR_TEST
)
{
;
/* insert your own custom function here */
}
strcat
(
bp
,
"
\n
"
);
strcat
(
bp
,
"
\n
"
);
spin_unlock_irqrestore
(
instance
->
host_lock
,
flags
);
*
start
=
buf
;
if
(
stop
)
{
...
...
@@ -2374,4 +2315,3 @@ MODULE_LICENSE("GPL");
static
Scsi_Host_Template
driver_template
=
IN2000
;
#include "scsi_module.c"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment