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
1fbcea01
Commit
1fbcea01
authored
Oct 08, 2002
by
Alan Cox
Committed by
Linus Torvalds
Oct 08, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] first pass at seagate st-02 for 2.5
parent
147f09f5
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
359 additions
and
467 deletions
+359
-467
drivers/scsi/seagate.c
drivers/scsi/seagate.c
+338
-446
drivers/scsi/seagate.h
drivers/scsi/seagate.h
+21
-21
No files found.
drivers/scsi/seagate.c
View file @
1fbcea01
...
...
@@ -265,16 +265,14 @@ MODULE_LICENSE("GPL");
#define WRITE_CONTROL(d) { isa_writeb((d), st0x_cr_sr); }
#define WRITE_DATA(d) { isa_writeb((d), st0x_dr); }
void
st0x_setup
(
char
*
str
,
int
*
ints
)
static
void
st0x_setup
(
char
*
str
,
int
*
ints
)
{
controller_type
=
SEAGATE
;
base_address
=
ints
[
1
];
irq
=
ints
[
2
];
}
void
tmc8xx_setup
(
char
*
str
,
int
*
ints
)
static
void
tmc8xx_setup
(
char
*
str
,
int
*
ints
)
{
controller_type
=
FD
;
base_address
=
ints
[
1
];
...
...
@@ -389,8 +387,14 @@ static void __init borken_init (void)
{
register
int
count
=
0
,
start
=
jiffies
+
1
,
stop
=
start
+
25
;
while
(
time_before
(
jiffies
,
start
))
;
for
(;
time_before
(
jiffies
,
stop
);
++
count
)
;
/* FIXME: There may be a better approach, this is a straight port for
now */
preempt_disable
();
while
(
time_before
(
jiffies
,
start
))
cpu_relax
();
for
(;
time_before
(
jiffies
,
stop
);
++
count
)
cpu_relax
();
preempt_enable
();
/*
* Ok, we now have a count for .25 seconds. Convert to a
...
...
@@ -406,8 +410,9 @@ static inline void borken_wait (void)
{
register
int
count
;
for
(
count
=
borken_calibration
;
count
&&
(
STATUS
&
STAT_REQ
);
--
count
)
;
for
(
count
=
borken_calibration
;
count
&&
(
STATUS
&
STAT_REQ
);
--
count
)
cpu_relax
();
#if (DEBUG & DEBUG_BORKEN)
if
(
count
)
printk
(
"scsi%d : borken timeout
\n
"
,
hostno
);
...
...
@@ -431,7 +436,7 @@ int __init seagate_st0x_detect (Scsi_Host_Template * tpnt)
tpnt
->
proc_name
=
"seagate"
;
/*
*
First, we try for the manual override.
*
First, we try for the manual override.
*/
DANY
(
"Autodetecting ST0x / TMC-8xx
\n
"
);
...
...
@@ -462,14 +467,9 @@ int __init seagate_st0x_detect (Scsi_Host_Template * tpnt)
* space for the on-board RAM instead.
*/
for
(
i
=
0
;
i
<
(
sizeof
(
seagate_bases
)
/
sizeof
(
unsigned
int
));
++
i
)
for
(
i
=
0
;
i
<
(
sizeof
(
seagate_bases
)
/
sizeof
(
unsigned
int
));
++
i
)
for
(
j
=
0
;
!
base_address
&&
j
<
NUM_SIGNATURES
;
++
j
)
if
(
isa_check_signature
(
seagate_bases
[
i
]
+
signatures
[
j
].
offset
,
signatures
[
j
].
signature
,
signatures
[
j
].
length
))
{
if
(
isa_check_signature
(
seagate_bases
[
i
]
+
signatures
[
j
].
offset
,
signatures
[
j
].
signature
,
signatures
[
j
].
length
))
{
base_address
=
seagate_bases
[
i
];
controller_type
=
signatures
[
j
].
type
;
}
...
...
@@ -480,40 +480,36 @@ int __init seagate_st0x_detect (Scsi_Host_Template * tpnt)
tpnt
->
name
=
(
controller_type
==
SEAGATE
)
?
ST0X_ID_STR
:
FD_ID_STR
;
if
(
!
base_address
)
{
DANY
(
"ST0x /
TMC-8xx not detected.
\n
"
);
printk
(
KERN_INFO
"seagate: ST0x/
TMC-8xx not detected.
\n
"
);
return
0
;
}
st0x_cr_sr
=
base_address
+
(
controller_type
==
SEAGATE
?
0x1a00
:
0x1c00
);
st0x_cr_sr
=
base_address
+
(
controller_type
==
SEAGATE
?
0x1a00
:
0x1c00
);
st0x_dr
=
st0x_cr_sr
+
0x200
;
DANY
(
"%s detected. Base address = %x, cr = %x, dr = %x
\n
"
,
DANY
(
"%s detected. Base address = %x, cr = %x, dr = %x
\n
"
,
tpnt
->
name
,
base_address
,
st0x_cr_sr
,
st0x_dr
);
/*
* At all times, we will use IRQ 5. Should also check for IRQ3 if we
*
loose our first interrupt.
*/
/*
* At all times, we will use IRQ 5. Should also check for IRQ3
* if we
loose our first interrupt.
*/
instance
=
scsi_register
(
tpnt
,
0
);
if
(
instance
==
NULL
)
return
0
;
hostno
=
instance
->
host_no
;
if
(
request_irq
(
irq
,
do_seagate_reconnect_intr
,
SA_INTERRUPT
,
(
controller_type
==
SEAGATE
)
?
"seagate"
:
"tmc-8xx"
,
instance
))
{
printk
(
"scsi%d : unable to allocate IRQ%d
\n
"
,
hostno
,
irq
);
if
(
request_irq
(
irq
,
do_seagate_reconnect_intr
,
SA_INTERRUPT
,
(
controller_type
==
SEAGATE
)
?
"seagate"
:
"tmc-8xx"
,
instance
))
{
printk
(
KERN_ERR
"scsi%d : unable to allocate IRQ%d
\n
"
,
hostno
,
irq
);
return
0
;
}
instance
->
irq
=
irq
;
instance
->
io_port
=
base_address
;
#ifdef SLOW_RATE
printk
(
KERN_INFO
"Calibrating borken timer... "
);
borken_init
();
printk
(
" %d cycles per transfer
\n
"
,
borken_calibration
);
printk
(
KERN_INFO
"Calibrating borken timer... "
);
borken_init
();
printk
(
" %d cycles per transfer
\n
"
,
borken_calibration
);
#endif
printk
(
KERN_INFO
"This is one second... "
);
{
int
clock
;
...
...
@@ -559,12 +555,11 @@ int __init seagate_st0x_detect (Scsi_Host_Template * tpnt)
return
1
;
}
const
char
*
seagate_st0x_info
(
struct
Scsi_Host
*
shpnt
)
static
const
char
*
seagate_st0x_info
(
struct
Scsi_Host
*
shpnt
)
{
static
char
buffer
[
64
];
s
printf
(
buffer
,
"%s at irq %d, address 0x%05X"
,
s
nprintf
(
buffer
,
64
,
"%s at irq %d, address 0x%05X"
,
(
controller_type
==
SEAGATE
)
?
ST0X_ID_STR
:
FD_ID_STR
,
irq
,
base_address
);
return
buffer
;
...
...
@@ -640,36 +635,29 @@ static void seagate_reconnect_intr (int irq, void *dev_id, struct pt_regs *regs)
int
temp
;
Scsi_Cmnd
*
SCtmp
;
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : seagate_reconnect_intr() called
\n
"
,
hostno
);
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : seagate_reconnect_intr() called
\n
"
,
hostno
);
if
(
!
should_reconnect
)
printk
(
"scsi%d: unexpected interrupt.
\n
"
,
hostno
);
printk
(
KERN_WARNING
"scsi%d: unexpected interrupt.
\n
"
,
hostno
);
else
{
should_reconnect
=
0
;
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : internal_command("
"%d, %08x, %08x, RECONNECT_NOW
\n
"
,
hostno
,
current_target
,
current_data
,
current_bufflen
);
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : internal_command(%d, %08x, %08x, RECONNECT_NOW
\n
"
,
hostno
,
current_target
,
current_data
,
current_bufflen
);
temp
=
internal_command
(
current_target
,
current_lun
,
current_cmnd
,
current_data
,
current_bufflen
,
RECONNECT_NOW
);
temp
=
internal_command
(
current_target
,
current_lun
,
current_cmnd
,
current_data
,
current_bufflen
,
RECONNECT_NOW
);
if
(
msg_byte
(
temp
)
!=
DISCONNECT
)
{
if
(
msg_byte
(
temp
)
!=
DISCONNECT
)
{
if
(
done_fn
)
{
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : done_fn(%d,%08x)"
,
hostno
,
hostno
,
temp
);
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : done_fn(%d,%08x)"
,
hostno
,
hostno
,
temp
);
if
(
!
SCint
)
panic
(
"SCint == NULL in seagate"
);
SCtmp
=
SCint
;
SCint
=
NULL
;
SCtmp
->
result
=
temp
;
done_fn
(
SCtmp
);
done_fn
(
SCtmp
);
}
else
printk
(
"done_fn() not defined.
\n
"
);
printk
(
KERN_ERR
"done_fn() not defined.
\n
"
);
}
}
}
...
...
@@ -687,7 +675,7 @@ static void seagate_reconnect_intr (int irq, void *dev_id, struct pt_regs *regs)
static
int
recursion_depth
=
0
;
int
seagate_st0x_queue_command
(
Scsi_Cmnd
*
SCpnt
,
void
(
*
done
)
(
Scsi_Cmnd
*
))
static
int
seagate_st0x_queue_command
(
Scsi_Cmnd
*
SCpnt
,
void
(
*
done
)
(
Scsi_Cmnd
*
))
{
int
result
,
reconnect
;
Scsi_Cmnd
*
SCtmp
;
...
...
@@ -696,53 +684,49 @@ int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
done_fn
=
done
;
current_target
=
SCpnt
->
target
;
current_lun
=
SCpnt
->
lun
;
(
const
void
*
)
current_cmnd
=
SCpnt
->
cmnd
;
current_cmnd
=
SCpnt
->
cmnd
;
current_data
=
(
unsigned
char
*
)
SCpnt
->
request_buffer
;
current_bufflen
=
SCpnt
->
request_bufflen
;
SCint
=
SCpnt
;
if
(
recursion_depth
)
return
0
;
return
1
;
recursion_depth
++
;
do
{
#ifdef LINKED
/*
* Set linked command bit in control field of SCSI command.
*/
/*
* Set linked command bit in control field of SCSI command.
*/
current_cmnd
[
SCpnt
->
cmd_len
]
|=
0x01
;
if
(
linked_connected
)
{
DPRINTK
(
DEBUG_LINKED
,
"scsi%d : using linked commands, current I_T_L nexus is "
,
hostno
);
if
((
linked_target
==
current_target
)
&&
(
linked_lun
==
current_lun
))
{
DPRINTK
(
DEBUG_LINKED
,
"correct
\n
"
);
DPRINTK
(
DEBUG_LINKED
,
"scsi%d : using linked commands, current I_T_L nexus is "
,
hostno
);
if
(
linked_target
==
current_target
&&
linked_lun
==
current_lun
)
{
DPRINTK
(
DEBUG_LINKED
,
"correct
\n
"
);
reconnect
=
LINKED_RIGHT
;
}
else
{
DPRINTK
(
DEBUG_LINKED
,
"incorrect
\n
"
);
DPRINTK
(
DEBUG_LINKED
,
"incorrect
\n
"
);
reconnect
=
LINKED_WRONG
;
}
}
else
#endif
/* LINKED */
reconnect
=
CAN_RECONNECT
;
result
=
internal_command
(
SCint
->
target
,
SCint
->
lun
,
SCint
->
cmnd
,
SCint
->
request_buffer
,
SCint
->
request_bufflen
,
reconnect
);
if
(
msg_byte
(
result
)
==
DISCONNECT
)
result
=
internal_command
(
SCint
->
target
,
SCint
->
lun
,
SCint
->
cmnd
,
SCint
->
request_buffer
,
SCint
->
request_bufflen
,
reconnect
);
if
(
msg_byte
(
result
)
==
DISCONNECT
)
break
;
SCtmp
=
SCint
;
SCint
=
NULL
;
SCtmp
->
result
=
result
;
done_fn
(
SCtmp
);
done_fn
(
SCtmp
);
}
while
(
SCint
);
recursion_depth
--
;
return
0
;
}
int
seagate_st0x_command
(
Scsi_Cmnd
*
SCpnt
)
static
int
seagate_st0x_command
(
Scsi_Cmnd
*
SCpnt
)
{
return
internal_command
(
SCpnt
->
target
,
SCpnt
->
lun
,
SCpnt
->
cmnd
,
SCpnt
->
request_buffer
,
SCpnt
->
request_bufflen
,
...
...
@@ -755,17 +739,12 @@ static int internal_command (unsigned char target, unsigned char lun,
unsigned
char
*
data
=
NULL
;
struct
scatterlist
*
buffer
=
NULL
;
int
clock
,
temp
,
nobuffs
=
0
,
done
=
0
,
len
=
0
;
unsigned
long
flags
;
#ifdef DEBUG
int
transfered
=
0
,
phase
=
0
,
newphase
;
#endif
register
unsigned
char
status_read
;
unsigned
char
tmp_data
,
tmp_control
,
status
=
0
,
message
=
0
;
unsigned
transfersize
=
0
,
underflow
=
0
;
#ifdef SLOW_RATE
int
borken
=
(
int
)
SCint
->
device
->
borken
;
/* Does the current target require
Very Slow I/O ? */
...
...
@@ -775,84 +754,76 @@ static int internal_command (unsigned char target, unsigned char lun,
st0x_aborted
=
0
;
#if (DEBUG & PRINT_COMMAND)
printk
(
"scsi%d : target = %d, command = "
,
hostno
,
target
);
print_command
((
unsigned
char
*
)
cmnd
);
printk
(
"scsi%d : target = %d, command = "
,
hostno
,
target
);
print_command
((
unsigned
char
*
)
cmnd
);
#endif
#if (DEBUG & PHASE_RESELECT)
switch
(
reselect
)
{
case
RECONNECT_NOW
:
printk
(
"scsi%d : reconnecting
\n
"
,
hostno
);
printk
(
"scsi%d : reconnecting
\n
"
,
hostno
);
break
;
#ifdef LINKED
case
LINKED_RIGHT
:
printk
(
"scsi%d : connected, can reconnect
\n
"
,
hostno
);
printk
(
"scsi%d : connected, can reconnect
\n
"
,
hostno
);
break
;
case
LINKED_WRONG
:
printk
(
"scsi%d : connected to wrong target, can reconnect
\n
"
,
printk
(
"scsi%d : connected to wrong target, can reconnect
\n
"
,
hostno
);
break
;
#endif
case
CAN_RECONNECT
:
printk
(
"scsi%d : allowed to reconnect
\n
"
,
hostno
);
printk
(
"scsi%d : allowed to reconnect
\n
"
,
hostno
);
break
;
default:
printk
(
"scsi%d : not allowed to reconnect
\n
"
,
hostno
);
printk
(
"scsi%d : not allowed to reconnect
\n
"
,
hostno
);
}
#endif
if
(
target
==
(
controller_type
==
SEAGATE
?
7
:
6
))
return
DID_BAD_TARGET
;
/*
* We work it differently depending on if this is is "the first time,"
* or a reconnect. If this is a reselect phase, then SEL will
* be asserted, and we must skip selection / arbitration phases.
*/
/*
* We work it differently depending on if this is is "the first time,"
* or a reconnect. If this is a reselect phase, then SEL will
* be asserted, and we must skip selection / arbitration phases.
*/
switch
(
reselect
)
{
case
RECONNECT_NOW
:
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : phase RESELECT
\n
"
,
hostno
);
/*
* At this point, we should find the logical or of our ID and the original
* target's ID on the BUS, with BSY, SEL, and I/O signals asserted.
*
* After ARBITRATION phase is completed, only SEL, BSY, and the
* target ID are asserted. A valid initiator ID is not on the bus
* until IO is asserted, so we must wait for that.
*/
/*
* At this point, we should find the logical or of our ID
* and the original target's ID on the BUS, with BSY, SEL,
* and I/O signals asserted.
*
* After ARBITRATION phase is completed, only SEL, BSY,
* and the target ID are asserted. A valid initiator ID
* is not on the bus until IO is asserted, so we must wait
* for that.
*/
ULOOP
(
100
*
1000
)
{
temp
=
STATUS
;
if
((
temp
&
STAT_IO
)
&&
!
(
temp
&
STAT_BSY
))
break
;
if
(
TIMEOUT
)
{
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : RESELECT timed out while waiting for IO .
\n
"
,
hostno
);
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : RESELECT timed out while waiting for IO .
\n
"
,
hostno
);
return
(
DID_BAD_INTR
<<
16
);
}
}
/*
* After I/O is asserted by the target, we can read our ID and its
*
ID off of the BUS.
*/
/*
* After I/O is asserted by the target, we can read our ID
* and its
ID off of the BUS.
*/
if
(
!
((
temp
=
DATA
)
&
(
controller_type
==
SEAGATE
?
0x80
:
0x40
)))
{
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : detected reconnect request to different target.
\n
"
"
\t
Data bus = %d
\n
"
,
hostno
,
temp
);
if
(
!
((
temp
=
DATA
)
&
(
controller_type
==
SEAGATE
?
0x80
:
0x40
)))
{
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : detected reconnect request to different target.
\n\t
Data bus = %d
\n
"
,
hostno
,
temp
);
return
(
DID_BAD_INTR
<<
16
);
}
if
(
!
(
temp
&
(
1
<<
current_target
)))
{
printk
(
"scsi%d : Unexpected reselect interrupt. Data bus = %d
\n
"
,
hostno
,
temp
);
printk
(
KERN_WARNING
"scsi%d : Unexpected reselect interrupt. Data bus = %d
\n
"
,
hostno
,
temp
);
return
(
DID_BAD_INTR
<<
16
);
}
...
...
@@ -862,10 +833,11 @@ static int internal_command (unsigned char target, unsigned char lun,
len
=
current_bufflen
;
/* WDE add */
nobuffs
=
current_nobuffs
;
/*
* We have determined that we have been selected. At this point,
* we must respond to the reselection by asserting BSY ourselves
*/
/*
* We have determined that we have been selected. At this
* point, we must respond to the reselection by asserting
* BSY ourselves
*/
#if 1
WRITE_CONTROL
(
BASE_CMD
|
CMD_DRVR_ENABLE
|
CMD_BSY
);
...
...
@@ -873,93 +845,80 @@ static int internal_command (unsigned char target, unsigned char lun,
WRITE_CONTROL
(
BASE_CMD
|
CMD_BSY
);
#endif
/*
* The target will drop SEL, and raise BSY, at which time we must drop
*
BSY.
*/
/*
* The target will drop SEL, and raise BSY, at which time
* we must drop
BSY.
*/
ULOOP
(
100
*
1000
)
{
if
(
!
(
STATUS
&
STAT_SEL
))
break
;
if
(
TIMEOUT
)
{
WRITE_CONTROL
(
BASE_CMD
|
CMD_INTR
);
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : RESELECT timed out while waiting for SEL.
\n
"
,
hostno
);
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : RESELECT timed out while waiting for SEL.
\n
"
,
hostno
);
return
(
DID_BAD_INTR
<<
16
);
}
}
WRITE_CONTROL
(
BASE_CMD
);
/*
* At this point, we have connected with the target and can get
* on with our lives.
*/
/*
* At this point, we have connected with the target
* and can get on with our lives.
*/
break
;
case
CAN_RECONNECT
:
#ifdef LINKED
/*
* This is a bletcherous hack, just as bad as the Unix #! interpreter stuff.
* If it turns out we are using the wrong I_T_L nexus, the easiest way to deal
* with it is to go into our INFORMATION TRANSFER PHASE code, send a ABORT
* message on MESSAGE OUT phase, and then loop back to here.
*/
connect_loop:
/*
* This is a bletcherous hack, just as bad as the Unix #!
* interpreter stuff. If it turns out we are using the wrong
* I_T_L nexus, the easiest way to deal with it is to go into
* our INFORMATION TRANSFER PHASE code, send a ABORT
* message on MESSAGE OUT phase, and then loop back to here.
*/
connect_loop:
#endif
DPRINTK
(
PHASE_BUS_FREE
,
"scsi%d : phase = BUS FREE
\n
"
,
hostno
);
DPRINTK
(
PHASE_BUS_FREE
,
"scsi%d : phase = BUS FREE
\n
"
,
hostno
);
/*
* BUS FREE PHASE
*
* On entry, we make sure that the BUS is in a BUS FREE
* phase, by insuring that both BSY and SEL are low for
* at least one bus settle delay. Several reads help
* eliminate wire glitch.
*/
/*
* BUS FREE PHASE
*
* On entry, we make sure that the BUS is in a BUS FREE
* phase, by insuring that both BSY and SEL are low for
* at least one bus settle delay. Several reads help
* eliminate wire glitch.
*/
#ifndef ARBITRATE
#error FIXME: this is broken: we may not use jiffies here - we are under cli(). It will hardlock.
clock
=
jiffies
+
ST0X_BUS_FREE_DELAY
;
while
(((
STATUS
|
STATUS
|
STATUS
)
&
(
STAT_BSY
|
STAT_SEL
))
&&
(
!
st0x_aborted
)
&&
time_before
(
jiffies
,
clock
))
;
while
(((
STATUS
|
STATUS
|
STATUS
)
&
(
STAT_BSY
|
STAT_SEL
))
&&
(
!
st0x_aborted
)
&&
time_before
(
jiffies
,
clock
))
cpu_relax
();
if
(
time_after
(
jiffies
,
clock
))
return
retcode
(
DID_BUS_BUSY
);
else
if
(
st0x_aborted
)
return
retcode
(
st0x_aborted
);
#endif
DPRINTK
(
PHASE_SELECTION
,
"scsi%d : phase = SELECTION
\n
"
,
hostno
);
DPRINTK
(
PHASE_SELECTION
,
"scsi%d : phase = SELECTION
\n
"
,
hostno
);
clock
=
jiffies
+
ST0X_SELECTION_DELAY
;
/*
* Arbitration/selection procedure :
* 1. Disable drivers
* 2. Write HOST adapter address bit
* 3. Set start arbitration.
* 4. We get either ARBITRATION COMPLETE or SELECT at this
* point.
* 5. OR our ID and targets on bus.
* 6. Enable SCSI drivers and asserted SEL and ATTN
*/
/*
* Arbitration/selection procedure :
* 1. Disable drivers
* 2. Write HOST adapter address bit
* 3. Set start arbitration.
* 4. We get either ARBITRATION COMPLETE or SELECT at this
* point.
* 5. OR our ID and targets on bus.
* 6. Enable SCSI drivers and asserted SEL and ATTN
*/
#ifdef ARBITRATE
save_flags
(
flags
);
cli
();
WRITE_CONTROL
(
0
);
WRITE_DATA
((
controller_type
==
SEAGATE
)
?
0x80
:
0x40
);
WRITE_CONTROL
(
CMD_START_ARB
);
restore_flags
(
flags
);
/* FIXME: verify host lock is always held here */
WRITE_CONTROL
(
0
);
WRITE_DATA
((
controller_type
==
SEAGATE
)
?
0x80
:
0x40
);
WRITE_CONTROL
(
CMD_START_ARB
);
ULOOP
(
ST0X_SELECTION_DELAY
*
10000
)
{
status_read
=
STATUS
;
...
...
@@ -968,40 +927,31 @@ static int internal_command (unsigned char target, unsigned char lun,
if
(
st0x_aborted
)
/* FIXME: What? We are going to do something even after abort? */
break
;
if
(
TIMEOUT
||
(
status_read
&
STAT_SEL
))
{
printk
(
"scsi%d : arbitration lost or timeout.
\n
"
,
hostno
);
printk
(
KERN_WARNING
"scsi%d : arbitration lost or timeout.
\n
"
,
hostno
);
WRITE_CONTROL
(
BASE_CMD
);
return
retcode
(
DID_NO_CONNECT
);
}
}
DPRINTK
(
PHASE_SELECTION
,
"scsi%d : arbitration complete
\n
"
,
hostno
);
DPRINTK
(
PHASE_SELECTION
,
"scsi%d : arbitration complete
\n
"
,
hostno
);
#endif
/*
* When the SCSI device decides that we're gawking at it, it will
* respond by asserting BUSY on the bus.
*
* Note : the Seagate ST-01/02 product manual says that we should
* twiddle the DATA register before the control register. However,
* this does not work reliably so we do it the other way around.
*
* Probably could be a problem with arbitration too, we really should
* try this with a SCSI protocol or logic analyzer to see what is
* going on.
*/
tmp_data
=
(
unsigned
char
)
((
1
<<
target
)
|
(
controller_type
==
SEAGATE
?
0x80
:
0x40
));
tmp_control
=
BASE_CMD
|
CMD_DRVR_ENABLE
|
CMD_SEL
|
(
reselect
?
CMD_ATTN
:
0
);
save_flags
(
flags
);
cli
();
/*
* When the SCSI device decides that we're gawking at it,
* it will respond by asserting BUSY on the bus.
*
* Note : the Seagate ST-01/02 product manual says that we
* should twiddle the DATA register before the control
* register. However, this does not work reliably so we do
* it the other way around.
*
* Probably could be a problem with arbitration too, we
* really should try this with a SCSI protocol or logic
* analyzer to see what is going on.
*/
tmp_data
=
(
unsigned
char
)
((
1
<<
target
)
|
(
controller_type
==
SEAGATE
?
0x80
:
0x40
));
tmp_control
=
BASE_CMD
|
CMD_DRVR_ENABLE
|
CMD_SEL
|
(
reselect
?
CMD_ATTN
:
0
);
/* FIXME: verify host lock is always held here */
#ifdef OLDCNTDATASCEME
#ifdef SWAPCNTDATA
WRITE_CONTROL
(
tmp_control
);
...
...
@@ -1018,22 +968,20 @@ static int internal_command (unsigned char target, unsigned char lun,
WRITE_CONTROL
(
tmp_control
);
/* -- pavel@ucw.cz */
#endif
restore_flags
(
flags
);
ULOOP
(
250
*
1000
)
{
if
(
st0x_aborted
)
{
/*
* If we have been aborted, and we have a command in progress, IE the
* target still has BSY asserted, then we will reset the bus, and
* notify the midlevel driver to expect sense.
*/
/*
* If we have been aborted, and we have a
* command in progress, IE the target
* still has BSY asserted, then we will
* reset the bus, and notify the midlevel
* driver to expect sense.
*/
WRITE_CONTROL
(
BASE_CMD
);
if
(
STATUS
&
STAT_BSY
)
{
printk
(
"scsi%d : BST asserted after we've been aborted.
\n
"
,
hostno
);
seagate_st0x_reset
(
NULL
,
0
);
printk
(
KERN_WARNING
"scsi%d : BST asserted after we've been aborted.
\n
"
,
hostno
);
seagate_st0x_bus_reset
(
NULL
);
return
retcode
(
DID_RESET
);
}
return
retcode
(
st0x_aborted
);
...
...
@@ -1041,26 +989,20 @@ static int internal_command (unsigned char target, unsigned char lun,
if
(
STATUS
&
STAT_BSY
)
break
;
if
(
TIMEOUT
)
{
DPRINTK
(
PHASE_SELECTION
,
"scsi%d : NO CONNECT with target %d, stat = %x
\n
"
,
hostno
,
target
,
STATUS
);
DPRINTK
(
PHASE_SELECTION
,
"scsi%d : NO CONNECT with target %d, stat = %x
\n
"
,
hostno
,
target
,
STATUS
);
return
retcode
(
DID_NO_CONNECT
);
}
}
/* Establish current pointers. Take into account scatter / gather */
/* Establish current pointers. Take into account scatter / gather */
if
((
nobuffs
=
SCint
->
use_sg
))
{
#if (DEBUG & DEBUG_SG)
{
int
i
;
printk
(
"scsi%d : scatter gather requested, using %d buffers.
\n
"
,
hostno
,
nobuffs
);
printk
(
"scsi%d : scatter gather requested, using %d buffers.
\n
"
,
hostno
,
nobuffs
);
for
(
i
=
0
;
i
<
nobuffs
;
++
i
)
printk
(
"scsi%d : buffer %d address = %p length = %d
\n
"
,
printk
(
"scsi%d : buffer %d address = %p length = %d
\n
"
,
hostno
,
i
,
page_address
(
buffer
[
i
].
page
)
+
buffer
[
i
].
offset
,
buffer
[
i
].
length
);
...
...
@@ -1069,11 +1011,9 @@ static int internal_command (unsigned char target, unsigned char lun,
buffer
=
(
struct
scatterlist
*
)
SCint
->
buffer
;
len
=
buffer
->
length
;
data
=
(
unsigned
char
*
)
buffer
->
address
;
data
=
page_address
(
buffer
->
page
)
+
buffer
->
offset
;
}
else
{
DPRINTK
(
DEBUG_SG
,
"scsi%d : scatter gather not requested.
\n
"
,
hostno
);
DPRINTK
(
DEBUG_SG
,
"scsi%d : scatter gather not requested.
\n
"
,
hostno
);
buffer
=
NULL
;
len
=
SCint
->
request_bufflen
;
data
=
(
unsigned
char
*
)
SCint
->
request_buffer
;
...
...
@@ -1091,38 +1031,34 @@ static int internal_command (unsigned char target, unsigned char lun,
#endif
}
/* end of switch(reselect) */
/*
* There are several conditions under which we wish to send a message :
* 1. When we are allowing disconnect / reconnect, and need to establish
* the I_T_L nexus via an IDENTIFY with the DiscPriv bit set.
*
* 2. When we are doing linked commands, are have the wrong I_T_L nexus
* established and want to send an ABORT message.
*/
/* GCC does not like an ifdef inside a macro, so do it the hard way. */
/*
* There are several conditions under which we wish to send a message :
* 1. When we are allowing disconnect / reconnect, and need to
* establish the I_T_L nexus via an IDENTIFY with the DiscPriv bit
* set.
*
* 2. When we are doing linked commands, are have the wrong I_T_L
* nexus established and want to send an ABORT message.
*/
/* GCC does not like an ifdef inside a macro, so do it the hard way. */
#ifdef LINKED
WRITE_CONTROL
(
BASE_CMD
|
CMD_DRVR_ENABLE
|
(((
reselect
==
CAN_RECONNECT
)
||
(
reselect
==
LINKED_WRONG
)
)
?
CMD_ATTN
:
0
));
WRITE_CONTROL
(
BASE_CMD
|
CMD_DRVR_ENABLE
|
(((
reselect
==
CAN_RECONNECT
)
||
(
reselect
==
LINKED_WRONG
))
?
CMD_ATTN
:
0
));
#else
WRITE_CONTROL
(
BASE_CMD
|
CMD_DRVR_ENABLE
|
(((
reselect
==
CAN_RECONNECT
)
)
?
CMD_ATTN
:
0
));
WRITE_CONTROL
(
BASE_CMD
|
CMD_DRVR_ENABLE
|
(((
reselect
==
CAN_RECONNECT
))
?
CMD_ATTN
:
0
));
#endif
/*
* INFORMATION TRANSFER PHASE
*
* The nasty looking read / write inline assembler loops we use for
* DATAIN and DATAOUT phases are approximately 4-5 times as fast as
* the 'C' versions - since we're moving 1024 bytes of data, this
* really adds up.
*
* SJT: The nasty-looking assembler is gone, so it's slower.
*
*/
/*
* INFORMATION TRANSFER PHASE
*
* The nasty looking read / write inline assembler loops we use for
* DATAIN and DATAOUT phases are approximately 4-5 times as fast as
* the 'C' versions - since we're moving 1024 bytes of data, this
* really adds up.
*
* SJT: The nasty-looking assembler is gone, so it's slower.
*
*/
DPRINTK
(
PHASE_ETC
,
"scsi%d : phase = INFORMATION TRANSFER
\n
"
,
hostno
);
...
...
@@ -1130,72 +1066,63 @@ static int internal_command (unsigned char target, unsigned char lun,
transfersize
=
SCint
->
transfersize
;
underflow
=
SCint
->
underflow
;
/*
* Now, we poll the device for status information,
* and handle any requests it makes. Note that since we are unsure of
* how much data will be flowing across the system, etc and cannot
* make reasonable timeouts, that we will instead have the midlevel
*
driver handle any timeouts that occur in this phase.
*/
/*
* Now, we poll the device for status information,
* and handle any requests it makes. Note that since we are unsure
* of how much data will be flowing across the system, etc and
* cannot make reasonable timeouts, that we will instead have the
* midlevel
driver handle any timeouts that occur in this phase.
*/
while
(((
status_read
=
STATUS
)
&
STAT_BSY
)
&&
!
st0x_aborted
&&
!
done
)
{
#ifdef PARITY
if
(
status_read
&
STAT_PARITY
)
{
printk
(
"scsi%d : got parity error
\n
"
,
hostno
);
printk
(
KERN_ERR
"scsi%d : got parity error
\n
"
,
hostno
);
st0x_aborted
=
DID_PARITY
;
}
#endif
if
(
status_read
&
STAT_REQ
)
{
#if ((DEBUG & PHASE_ETC) == PHASE_ETC)
if
((
newphase
=
(
status_read
&
REQ_MASK
))
!=
phase
)
{
phase
=
newphase
;
switch
(
phase
)
{
case
REQ_DATAOUT
:
printk
(
"scsi%d : phase = DATA OUT
\n
"
,
hostno
);
printk
(
"scsi%d : phase = DATA OUT
\n
"
,
hostno
);
break
;
case
REQ_DATAIN
:
printk
(
"scsi%d : phase = DATA IN
\n
"
,
hostno
);
printk
(
"scsi%d : phase = DATA IN
\n
"
,
hostno
);
break
;
case
REQ_CMDOUT
:
printk
(
"scsi%d : phase = COMMAND OUT
\n
"
,
hostno
);
(
"scsi%d : phase = COMMAND OUT
\n
"
,
hostno
);
break
;
case
REQ_STATIN
:
printk
(
"scsi%d : phase = STATUS IN
\n
"
,
hostno
);
printk
(
"scsi%d : phase = STATUS IN
\n
"
,
hostno
);
break
;
case
REQ_MSGOUT
:
printk
(
"scsi%d : phase = MESSAGE OUT
\n
"
,
hostno
);
(
"scsi%d : phase = MESSAGE OUT
\n
"
,
hostno
);
break
;
case
REQ_MSGIN
:
printk
(
"scsi%d : phase = MESSAGE IN
\n
"
,
hostno
);
printk
(
"scsi%d : phase = MESSAGE IN
\n
"
,
hostno
);
break
;
default:
printk
(
"scsi%d : phase = UNKNOWN
\n
"
,
hostno
);
printk
(
"scsi%d : phase = UNKNOWN
\n
"
,
hostno
);
st0x_aborted
=
DID_ERROR
;
}
}
#endif
switch
(
status_read
&
REQ_MASK
)
{
case
REQ_DATAOUT
:
/*
* If we are in fast mode, then we simply splat the data out
* in word-sized chunks as fast as we can.
*/
/*
* If we are in fast mode, then we simply splat
* the data out in word-sized chunks as fast as
* we can.
*/
if
(
!
len
)
{
#if 0
printk
("scsi%d: underflow to target %d lun %d \n",
hostno, target, lun);
printk("scsi%d: underflow to target %d lun %d \n", hostno, target, lun);
st0x_aborted = DID_ERROR;
fast = 0;
#endif
...
...
@@ -1216,7 +1143,7 @@ static int internal_command (unsigned char target, unsigned char lun,
SCint
->
transfersize
,
len
,
data
);
/* SJT: Start. Fast Write */
/* SJT: Start. Fast Write */
#ifdef SEAGATE_USE_ASM
__asm__
(
"cld
\n\t
"
#ifdef FAST32
...
...
@@ -1241,14 +1168,11 @@ static int internal_command (unsigned char target, unsigned char lun,
#else
/* SEAGATE_USE_ASM */
{
#ifdef FAST32
unsigned
int
*
iop
=
phys_to_virt
(
st0x_dr
);
const
unsigned
int
*
dp
=
(
unsigned
int
*
)
data
;
unsigned
int
*
iop
=
phys_to_virt
(
st0x_dr
);
const
unsigned
int
*
dp
=
(
unsigned
int
*
)
data
;
int
xferlen
=
transfersize
>>
2
;
#else
unsigned
char
*
iop
=
phys_to_virt
(
st0x_dr
);
unsigned
char
*
iop
=
phys_to_virt
(
st0x_dr
);
const
unsigned
char
*
dp
=
data
;
int
xferlen
=
transfersize
;
#endif
...
...
@@ -1259,14 +1183,13 @@ static int internal_command (unsigned char target, unsigned char lun,
/* SJT: End */
len
-=
transfersize
;
data
+=
transfersize
;
DPRINTK
(
DEBUG_FAST
,
"scsi%d : FAST transfer complete len = %d data = %08x
\n
"
,
hostno
,
len
,
data
);
DPRINTK
(
DEBUG_FAST
,
"scsi%d : FAST transfer complete len = %d data = %08x
\n
"
,
hostno
,
len
,
data
);
}
else
{
/*
* We loop as long as we are in a data out phase, there is data to send,
* and BSY is still active.
*/
/*
* We loop as long as we are in a
* data out phase, there is data to
* send, and BSY is still active.
*/
/* SJT: Start. Slow Write. */
#ifdef SEAGATE_USE_ASM
...
...
@@ -1335,8 +1258,7 @@ static int internal_command (unsigned char target, unsigned char lun,
--
nobuffs
;
++
buffer
;
len
=
buffer
->
length
;
data
=
(
unsigned
char
*
)
buffer
->
address
;
data
=
page_address
(
buffer
->
page
)
+
buffer
->
offset
;
DPRINTK
(
DEBUG_SG
,
"scsi%d : next scatter-gather buffer len = %d address = %08x
\n
"
,
hostno
,
len
,
data
);
...
...
@@ -1349,13 +1271,9 @@ static int internal_command (unsigned char target, unsigned char lun,
#if (DEBUG & (PHASE_DATAIN))
transfered
+=
len
;
#endif
for
(;
len
&&
(
STATUS
&
(
REQ_MASK
|
STAT_REQ
))
==
(
REQ_DATAIN
|
STAT_REQ
);
--
len
)
{
for
(;
len
&&
(
STATUS
&
(
REQ_MASK
|
STAT_REQ
))
==
(
REQ_DATAIN
|
STAT_REQ
);
--
len
)
{
*
data
++
=
DATA
;
borken_wait
();
borken_wait
();
}
#if (DEBUG & (PHASE_DATAIN))
transfered
-=
len
;
...
...
@@ -1421,19 +1339,15 @@ static int internal_command (unsigned char target, unsigned char lun,
len
-=
transfersize
;
data
+=
transfersize
;
#if (DEBUG & PHASE_DATAIN)
printk
(
"scsi%d: transfered += %d
\n
"
,
hostno
,
transfersize
);
printk
(
"scsi%d: transfered += %d
\n
"
,
hostno
,
transfersize
);
transfered
+=
transfersize
;
#endif
DPRINTK
(
DEBUG_FAST
,
"scsi%d : FAST transfer complete len = %d data = %08x
\n
"
,
hostno
,
len
,
data
);
DPRINTK
(
DEBUG_FAST
,
"scsi%d : FAST transfer complete len = %d data = %08x
\n
"
,
hostno
,
len
,
data
);
}
else
{
#if (DEBUG & PHASE_DATAIN)
printk
(
"scsi%d: transfered += %d
\n
"
,
hostno
,
len
);
printk
(
"scsi%d: transfered += %d
\n
"
,
hostno
,
len
);
transfered
+=
len
;
/* Assume we'll transfer it all, then
subtract what we *didn't* transfer */
#endif
...
...
@@ -1508,8 +1422,7 @@ static int internal_command (unsigned char target, unsigned char lun,
#endif
/* SEAGATE_USE_ASM */
/* SJT: End. */
#if (DEBUG & PHASE_DATAIN)
printk
(
"scsi%d: transfered -= %d
\n
"
,
hostno
,
len
);
printk
(
"scsi%d: transfered -= %d
\n
"
,
hostno
,
len
);
transfered
-=
len
;
/* Since we assumed all of Len got *
transfered, correct our mistake */
#endif
...
...
@@ -1519,26 +1432,17 @@ static int internal_command (unsigned char target, unsigned char lun,
--
nobuffs
;
++
buffer
;
len
=
buffer
->
length
;
data
=
(
unsigned
char
*
)
buffer
->
address
;
DPRINTK
(
DEBUG_SG
,
"scsi%d : next scatter-gather buffer len = %d address = %08x
\n
"
,
hostno
,
len
,
data
);
data
=
page_address
(
buffer
->
page
)
+
buffer
->
offset
;
DPRINTK
(
DEBUG_SG
,
"scsi%d : next scatter-gather buffer len = %d address = %08x
\n
"
,
hostno
,
len
,
data
);
}
break
;
case
REQ_CMDOUT
:
while
(((
status_read
=
STATUS
)
&
STAT_BSY
)
&&
((
status_read
&
REQ_MASK
)
==
REQ_CMDOUT
))
if
(
status_read
&
STAT_REQ
)
{
WRITE_DATA
(
*
(
const
unsigned
char
*
)
cmnd
);
cmnd
=
1
+
(
const
unsigned
char
*
)
cmnd
;
WRITE_DATA
(
*
(
const
unsigned
char
*
)
cmnd
);
cmnd
=
1
+
(
const
unsigned
char
*
)
cmnd
;
#ifdef SLOW_RATE
if
(
borken
)
borken_wait
();
...
...
@@ -1551,23 +1455,21 @@ static int internal_command (unsigned char target, unsigned char lun,
break
;
case
REQ_MSGOUT
:
/*
* We can only have sent a MSG OUT if we requested to do this
* by raising ATTN. So, we must drop
ATTN.
*/
/*
* We can only have sent a MSG OUT if we
* requested to do this by raising
ATTN.
* So, we must drop ATTN.
*/
WRITE_CONTROL
(
BASE_CMD
|
CMD_DRVR_ENABLE
);
/*
* If we are reconnecting, then we must send an IDENTIFY message in
* response to MSGOUT.
*/
/*
* If we are reconnecting, then we must
* send an IDENTIFY message in response
* to MSGOUT.
*/
switch
(
reselect
)
{
case
CAN_RECONNECT
:
WRITE_DATA
(
IDENTIFY
(
1
,
lun
));
DPRINTK
(
PHASE_RESELECT
|
PHASE_MSGOUT
,
"scsi%d : sent IDENTIFY message.
\n
"
,
hostno
);
DPRINTK
(
PHASE_RESELECT
|
PHASE_MSGOUT
,
"scsi%d : sent IDENTIFY message.
\n
"
,
hostno
);
break
;
#ifdef LINKED
case
LINKED_WRONG
:
...
...
@@ -1575,23 +1477,19 @@ static int internal_command (unsigned char target, unsigned char lun,
linked_connected
=
0
;
reselect
=
CAN_RECONNECT
;
goto
connect_loop
;
DPRINTK
(
PHASE_MSGOUT
|
DEBUG_LINKED
,
"scsi%d : sent ABORT message to cancel incorrect I_T_L nexus.
\n
"
,
hostno
);
#endif
/* LINKED */
DPRINTK
(
PHASE_MSGOUT
|
DEBUG_LINKED
,
"scsi%d : sent ABORT message to cancel incorrect I_T_L nexus.
\n
"
,
hostno
);
#endif
/* LINKED */
DPRINTK
(
DEBUG_LINKED
,
"correct
\n
"
);
default:
WRITE_DATA
(
NOP
);
printk
(
"scsi%d : target %d requested MSGOUT, sent NOP message.
\n
"
,
hostno
,
target
);
printk
(
"scsi%d : target %d requested MSGOUT, sent NOP message.
\n
"
,
hostno
,
target
);
}
break
;
case
REQ_MSGIN
:
switch
(
message
=
DATA
)
{
case
DISCONNECT
:
DANY
(
"seagate: deciding to disconnect
\n
"
);
DANY
(
"seagate: deciding to disconnect
\n
"
);
should_reconnect
=
1
;
current_data
=
data
;
/* WDE add */
current_buffer
=
buffer
;
...
...
@@ -1601,9 +1499,7 @@ static int internal_command (unsigned char target, unsigned char lun,
linked_connected
=
0
;
#endif
done
=
1
;
DPRINTK
((
PHASE_RESELECT
|
PHASE_MSGIN
),
"scsi%d : disconnected.
\n
"
,
hostno
);
DPRINTK
((
PHASE_RESELECT
|
PHASE_MSGIN
),
"scsi%d : disconnected.
\n
"
,
hostno
);
break
;
#ifdef LINKED
...
...
@@ -1611,18 +1507,14 @@ static int internal_command (unsigned char target, unsigned char lun,
case
LINKED_FLG_CMD_COMPLETE
:
#endif
case
COMMAND_COMPLETE
:
/*
* Note : we should check for underflow here.
*/
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : command complete.
\n
"
,
hostno
);
/*
* Note : we should check for underflow here.
*/
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : command complete.
\n
"
,
hostno
);
done
=
1
;
break
;
case
ABORT
:
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : abort message.
\n
"
,
hostno
);
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : abort message.
\n
"
,
hostno
);
done
=
1
;
break
;
case
SAVE_POINTERS
:
...
...
@@ -1630,9 +1522,7 @@ static int internal_command (unsigned char target, unsigned char lun,
current_bufflen
=
len
;
/* WDE add */
current_data
=
data
;
/* WDE mod */
current_nobuffs
=
nobuffs
;
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : pointers saved.
\n
"
,
hostno
);
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : pointers saved.
\n
"
,
hostno
);
break
;
case
RESTORE_POINTERS
:
buffer
=
current_buffer
;
...
...
@@ -1640,91 +1530,87 @@ static int internal_command (unsigned char target, unsigned char lun,
data
=
current_data
;
/* WDE mod */
len
=
current_bufflen
;
nobuffs
=
current_nobuffs
;
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : pointers restored.
\n
"
,
hostno
);
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : pointers restored.
\n
"
,
hostno
);
break
;
default:
/*
* IDENTIFY distinguishes itself from the other messages by setting the
* high byte. [FIXME: should not this read "the high bit"? - pavel@ucw.cz]
*
* Note : we need to handle at least one outstanding command per LUN,
* and need to hash the SCSI command for that I_T_L nexus based on the
* known ID (at this point) and LUN.
*/
/*
* IDENTIFY distinguishes itself
* from the other messages by
* setting the high bit.
*
* Note : we need to handle at
* least one outstanding command
* per LUN, and need to hash the
* SCSI command for that I_T_L
* nexus based on the known ID
* (at this point) and LUN.
*/
if
(
message
&
0x80
)
{
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : IDENTIFY message received from id %d, lun %d.
\n
"
,
hostno
,
target
,
message
&
7
);
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : IDENTIFY message received from id %d, lun %d.
\n
"
,
hostno
,
target
,
message
&
7
);
}
else
{
/*
* We should go into a MESSAGE OUT phase, and send a MESSAGE_REJECT
* if we run into a message that we don't like. The seagate driver
* needs some serious restructuring first though.
*/
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : unknown message %d from target %d.
\n
"
,
hostno
,
message
,
target
);
/*
* We should go into a
* MESSAGE OUT phase, and
* send a MESSAGE_REJECT
* if we run into a message
* that we don't like. The
* seagate driver needs
* some serious
* restructuring first
* though.
*/
DPRINTK
(
PHASE_MSGIN
,
"scsi%d : unknown message %d from target %d.
\n
"
,
hostno
,
message
,
target
);
}
}
break
;
default:
printk
(
"scsi%d : unknown phase.
\n
"
,
hostno
);
printk
(
KERN_ERR
"scsi%d : unknown phase.
\n
"
,
hostno
);
st0x_aborted
=
DID_ERROR
;
}
/* end of switch (status_read &
REQ_MASK) */
}
/* end of switch (status_read & REQ_MASK) */
#ifdef SLOW_RATE
/*
* I really don't care to deal with borken devices in each single
* byte transfer case (ie, message in, message out, status), so
* I'll do the wait here if necessary.
*/
if
(
borken
)
borken_wait
();
/*
* I really don't care to deal with borken devices in
* each single byte transfer case (ie, message in,
* message out, status), so I'll do the wait here if
* necessary.
*/
if
(
borken
)
borken_wait
();
#endif
}
/* if(status_read & STAT_REQ) ends */
}
/* while(((status_read = STATUS)...)
ends */
}
/* while(((status_read = STATUS)...) ends */
DPRINTK
(
PHASE_DATAIN
|
PHASE_DATAOUT
|
PHASE_EXIT
,
"scsi%d : Transfered %d bytes
\n
"
,
hostno
,
transfered
);
DPRINTK
(
PHASE_DATAIN
|
PHASE_DATAOUT
|
PHASE_EXIT
,
"scsi%d : Transfered %d bytes
\n
"
,
hostno
,
transfered
);
#if (DEBUG & PHASE_EXIT)
#if 0 /* Doesn't work for scatter/gather */
printk
("Buffer : \n");
for
(i = 0; i < 20; ++i)
printk
("%02x ", ((unsigned char *) data)[i]); /* WDE mod */
printk
("\n");
printk("Buffer : \n");
for(i = 0; i < 20; ++i)
printk("%02x ", ((unsigned char *) data)[i]); /* WDE mod */
printk("\n");
#endif
printk
(
"scsi%d : status = "
,
hostno
);
print_status
(
status
);
printk
(
" message = %02x
\n
"
,
message
);
printk
(
"scsi%d : status = "
,
hostno
);
print_status
(
status
);
printk
(
" message = %02x
\n
"
,
message
);
#endif
/* We shouldn't reach this until *after* BSY has been deasserted */
/* We shouldn't reach this until *after* BSY has been deasserted */
#ifdef LINKED
else
{
/*
* Fix the message byte so that unsuspecting high level drivers don't
* puke when they see a LINKED COMMAND message in place of the COMMAND
* COMPLETE they may be expecting. Shouldn't be necessary, but it's
*
better to be on the safe side.
*
* A non LINKED* message byte will indicate that the command completed,
*
and we are now disconnected.
*/
/*
* Fix the message byte so that unsuspecting high level drivers
* don't puke when they see a LINKED COMMAND message in place of
* the COMMAND COMPLETE they may be expecting. Shouldn't be
* necessary, but it's
better to be on the safe side.
*
* A non LINKED* message byte will indicate that the command
* completed,
and we are now disconnected.
*/
switch
(
message
)
{
case
LINKED_CMD_COMPLETE
:
...
...
@@ -1733,33 +1619,27 @@ static int internal_command (unsigned char target, unsigned char lun,
linked_target
=
current_target
;
linked_lun
=
current_lun
;
linked_connected
=
1
;
DPRINTK
(
DEBUG_LINKED
,
"scsi%d : keeping I_T_L nexus established"
"for linked command.
\n
"
,
hostno
);
DPRINTK
(
DEBUG_LINKED
,
"scsi%d : keeping I_T_L nexus established for linked command.
\n
"
,
hostno
);
/* We also will need to adjust status to accommodate intermediate
conditions. */
if
((
status
==
INTERMEDIATE_GOOD
)
||
(
status
==
INTERMEDIATE_C_GOOD
))
if
((
status
==
INTERMEDIATE_GOOD
)
||
(
status
==
INTERMEDIATE_C_GOOD
))
status
=
GOOD
;
break
;
/*
* We should also handle what are "normal" termination messages
* here (ABORT, BUS_DEVICE_RESET?, and COMMAND_COMPLETE individually,
* and flake if things aren't right.
*/
/*
* We should also handle what are "normal" termination
* messages here (ABORT, BUS_DEVICE_RESET?, and
* COMMAND_COMPLETE individually, and flake if things
* aren't right.
*/
default:
DPRINTK
(
DEBUG_LINKED
,
"scsi%d : closing I_T_L nexus.
\n
"
,
hostno
);
DPRINTK
(
DEBUG_LINKED
,
"scsi%d : closing I_T_L nexus.
\n
"
,
hostno
);
linked_connected
=
0
;
}
}
#endif
/* LINKED */
#endif
/* LINKED */
if
(
should_reconnect
)
{
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : exiting seagate_st0x_queue_command()"
"with reconnect enabled.
\n
"
,
hostno
);
DPRINTK
(
PHASE_RESELECT
,
"scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.
\n
"
,
hostno
);
WRITE_CONTROL
(
BASE_CMD
|
CMD_INTR
);
}
else
WRITE_CONTROL
(
BASE_CMD
);
...
...
@@ -1770,7 +1650,7 @@ static int internal_command (unsigned char target, unsigned char lun,
static
int
seagate_st0x_abort
(
Scsi_Cmnd
*
SCpnt
)
{
st0x_aborted
=
DID_ABORT
;
return
S
CSI_ABORT_PENDING
;
return
S
UCCESS
;
}
#undef ULOOP
...
...
@@ -1778,14 +1658,16 @@ static int seagate_st0x_abort (Scsi_Cmnd * SCpnt)
/*
* the seagate_st0x_reset function resets the SCSI bus
*
* May be called with SCpnt = NULL
*/
static
int
seagate_st0x_
reset
(
Scsi_Cmnd
*
SCpnt
,
unsigned
int
reset_flags
)
static
int
seagate_st0x_
bus_reset
(
Scsi_Cmnd
*
SCpnt
)
{
/* No timeouts - this command is going to fail because it was reset. */
/* No timeouts - this command is going to fail because it was reset. */
DANY
(
"scsi%d: Reseting bus... "
,
hostno
);
/* assert RESET signal on SCSI bus. */
/* assert RESET signal on SCSI bus. */
WRITE_CONTROL
(
BASE_CMD
|
CMD_RST
);
udelay
(
20
*
1000
);
...
...
@@ -1794,7 +1676,17 @@ static int seagate_st0x_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags)
st0x_aborted
=
DID_RESET
;
DANY
(
"done.
\n
"
);
return
SCSI_RESET_WAKEUP
;
return
SUCCESS
;
}
static
int
seagate_st0x_host_reset
(
Scsi_Cmnd
*
SCpnt
)
{
return
FAILED
;
}
static
int
seagate_st0x_device_reset
(
Scsi_Cmnd
*
SCpnt
)
{
return
FAILED
;
}
/* Eventually this will go into an include file, but this will be later */
...
...
drivers/scsi/seagate.h
View file @
1fbcea01
...
...
@@ -7,30 +7,30 @@
*/
#ifndef _SEAGATE_H
#define SEAGATE_H
/*
$Header
*/
#ifndef ASM
int
seagate_st0x_detect
(
Scsi_Host_Template
*
);
int
seagate_st0x_command
(
Scsi_Cmnd
*
);
int
seagate_st0x_queue_command
(
Scsi_Cmnd
*
,
void
(
*
done
)(
Scsi_Cmnd
*
));
#define SEAGATE_H
static
int
seagate_st0x_detect
(
Scsi_Host_Template
*
);
static
int
seagate_st0x_command
(
Scsi_Cmnd
*
);
static
int
seagate_st0x_queue_command
(
Scsi_Cmnd
*
,
void
(
*
done
)(
Scsi_Cmnd
*
));
static
int
seagate_st0x_abort
(
Scsi_Cmnd
*
);
const
char
*
seagate_st0x_info
(
struct
Scsi_Host
*
);
static
int
seagate_st0x_reset
(
Scsi_Cmnd
*
,
unsigned
int
);
static
const
char
*
seagate_st0x_info
(
struct
Scsi_Host
*
);
static
int
seagate_st0x_bus_reset
(
Scsi_Cmnd
*
);
static
int
seagate_st0x_device_reset
(
Scsi_Cmnd
*
);
static
int
seagate_st0x_host_reset
(
Scsi_Cmnd
*
);
#define SEAGATE_ST0X { detect: seagate_st0x_detect, \
info: seagate_st0x_info, \
command: seagate_st0x_command, \
queuecommand: seagate_st0x_queue_command, \
abort: seagate_st0x_abort, \
reset: seagate_st0x_reset, \
can_queue: 1, \
this_id: 7, \
sg_tablesize: SG_ALL, \
cmd_per_lun: 1, \
#define SEAGATE_ST0X { detect: seagate_st0x_detect, \
info: seagate_st0x_info, \
command: seagate_st0x_command, \
queuecommand: seagate_st0x_queue_command, \
eh_abort_handler: seagate_st0x_abort, \
eh_bus_reset_handler: seagate_st0x_bus_reset, \
eh_host_reset_handler: seagate_st0x_host_reset, \
eh_device_reset_handler:seagate_st0x_device_reset, \
can_queue: 1, \
this_id: 7, \
sg_tablesize: SG_ALL, \
cmd_per_lun: 1, \
use_clustering: DISABLE_CLUSTERING}
#endif
/* ASM */
#endif
/* _SEAGATE_H */
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