Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
RiscOS
S
Sources
H
HWSupport
CD
ATAPI
Commits
62541235
Commit
62541235
authored
Nov 29, 1996
by
Neil Turton
Browse files
NCOS 1.06 Imported from Zip drive
parent
ecf41001
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
20 additions
and
353 deletions
+20
-353
s/ATAPIStuff
s/ATAPIStuff
+20
-353
No files found.
s/ATAPIStuff
View file @
62541235
...
...
@@ -16,8 +16,7 @@
;
; ATAPIStuff.s
;
; Author: Mark Watson (EESOX)
; Largely rewritten by: Christopher Partington (Cambridge Systems Design)
; Author: Mark Watson (EESOX)
;
; Description
; ===========
...
...
@@ -82,40 +81,16 @@
; NOTE: some reads of regs are byte, others word - this should be sorted
; out.
;
; 06-Apr-95 17:45 cpartington (Cambridge Systems Design)
; * Added debugging code so caller can detect how many bytes were not
; transferred.
;
; 12-Jun-95 11:33 cpartington (Cambridge Systems Design)
; * Added conditional code to use TIMEOUT__COMMAND_COMPLETE instead of
; literal when calling WaitForIRQ to wait for command completion. Should
; always have used constant rather than literal but this change forced by
; trying to adjust timeout values to try to cope with slow Sony CDU50E.
;
; 13-Jun-95 16:09 cpartington (Cambridge Systems Design)
; * Conditionally disable poll for !BSY before selecting drive to try to
; cope with Sony master drive with no slave connected.
;
; 19-Jun-95 16:36 cpartington (Cambridge Systems Design)
; * Change ATAPI_Reset to use constant for timeout rather than literal.
;
; 06-Jul-95 10:37 cpartington (Cambridge Systems Design)
; * Added code conditional on bodge_50e_sole_drive and full_drive_detection
; including new routine ATAPI_CheckForDrive and mechanism to call it via
; ATAPI_Control) to try to address SONY CDU50E sole drive problem.
;
;*end of change record*
; Routines in thisfile
; ATAPI_Control
; ATAPI_LockUnlockIDE
; ATAPI_Op
; WaitForIRQ
; ATAPI_Reset
; ATAPI_CheckForDrive
; DoMicroDelay
; ATAPI_LockUnlockIDE
;
; ONLY EVER USE THE ATAPI_Control function with reason codes.
; NEVER call the functions directly
...
...
@@ -167,9 +142,6 @@ ATAPI_Control ROUT
ATAPIC_StartOfJumpTable
B
ATAPI_Op
B
ATAPI_Reset
[
full_drive_detection
B
ATAPI_CheckForDrive
]
ATAPIC_EndOfJumpTable
ATAPIC_UnknownReason
...
...
@@ -235,10 +207,11 @@ ATAPI_Op ROUT
STASH
"r0-r10,r14"
[
cdebug
CDebug_Time
CDebug_StrReg8
": Op "
,
r0
,
cc
;;;; CDebug_StrReg8 ", addr ",r3,cc
CDebug_StrReg8
"DoOp "
,
r0
,
cc
CDebug_StrReg8
", addr "
,
r3
,
cc
CDebug_StrReg8
", len "
,
r4
,
cc
LDRB
r6
,[
r2
]
CDebug_StrReg2
", PCmd "
,
r6
MOV
r1
,#
12
00
LDRB
r0
,[
r2
],#
1
...
...
@@ -281,8 +254,6 @@ AO_GotDrive
SWI
XOS_ReadMonotonicTime
ADD
r5
,
r0
,#
TIMEOUT__SELECTION_PHASE
; r5 = time to give up
LDR
r1
,
TBA
; r1 -> IDE
[
:LNOT:
bodge_sony_selection
01
LDR
r0
,[
r1
,#
TASKFILE__R_ALTERNATE_STATUS
]
TSTS
r0
,#
STATUSFLAGS__BSY
...
...
@@ -293,7 +264,6 @@ AO_GotDrive
B
%F04
; give up
;;;;;;;;;;;;;;;;;
]
02
; drive is no longer busy - select it and check status again
...
...
@@ -343,25 +313,9 @@ AO_GotDrive
05
; drive is ready
; r1 -> registers
[
Version
<
125
LDR
r1
,
TBA
]
[
bodge_50e_sole_drive
; Enable IRQ in digital output (device control) register so can poll for it
; in IOC - this is OK as the IRQ is not enabled. Ideally, would
; enable/disable it around each access but this will now upset ADFS which
; assumes it is always enabled
MOV
r0
,#
2_1000
; -SRST IEN
STRB
r0
,[
r1
,#
TASKFILE__W_DIGITAL_OUTPUT
]
]
; send command to drive via task file registers
LDR
r1
,
TBA
MOV
r0
,#
FEATUREBITS__PIO
STRB
r0
,[
r1
,#
TASKFILE__W_FEATURES
]
...
...
@@ -399,16 +353,6 @@ AO_GotDrive
MOV
r0
,#
1
*
2
; 1/2 us units
BL
DoMicroDelay
[
faster_startup
; if IDENTIFY device, skip wait for !BSY and DRQ and go straight to command
; complete. Normal code should do this, not just faster_startup but only
; faster_startup code shows problem because its timeouts are shorter
TSTS
r6
,#
ATAPIOP__IDENTIFY_DEVICE
BNE
ACOD_WaitForCommandComplete
; branch if IDENTIFY
]
; need to send CDB to drive so wait for it to be not busy
SWI
XOS_ReadMonotonicTime
...
...
@@ -436,16 +380,10 @@ AO_GotDrive
MOV
r0
,#
1
*
2
; 1/2 us units
BL
DoMicroDelay
[
:LNOT:
faster_startup
; if IDENTIFY, move straight onto waiting for command complete (no CDB)
; See comments above to see why this code is not necessary if faster_startup
; is enabled
TSTS
r6
,#
ATAPIOP__IDENTIFY_DEVICE
; identify?
BNE
ACOD_WaitForCommandComplete
; branch if IDENTIFY
]
13
; check if drive is "Interrupt DRQ" type and wait for IRQ if so
; "Accelerated DRQ" drives do not provide an IRQ at this point
...
...
@@ -526,11 +464,7 @@ ACOD_SendLoop
ACOD_WaitForCommandComplete
SWI
XOS_ReadMonotonicTime
[
long_command_timeout
ADD
r5
,
r0
,#
TIMEOUT__COMMAND_COMPLETE
|
ADD
r5
,
r0
,#
512
; MEW says NEC needs this long
]
LDR
r1
,
TBA
BL
WaitForIRQ
; (r1,r5->r0,r2,r3,Z)
[
cdebug
...
...
@@ -630,14 +564,9 @@ ACOD_WaitForCommandComplete
CMPS
r5
,
r10
MOVGT
r5
,
r10
[
cdebug
[
cdebug
2
CDebug_StrReg4
"copy "
,
r5
]
[
cdebug
LDR
r0
,
inbytes
ADD
r0
,
r0
,
r5
STR
r0
,
inbytes
]
; fall through
...
...
@@ -764,12 +693,6 @@ ACOD_AnyMoreData
; r5 = bytes in drive - buffer size = bytes to discard
[
cdebug
BLE
%F00
CDebug_StrReg8
"Discard "
,
r5
00
]
40
; be careful only to read drive if necessary; in particular watch out for
; odd transfer lengths e.g. drive wants 512 bytes read, caller only wants
...
...
@@ -812,18 +735,12 @@ ACOD_ExitError
; r0 = Internal error number
[
cdebug
CDebug_Time
CDebug_StrReg8
": #err "
,
r0
,
cc
CDebug_StrReg8
"#err "
,
r0
,
cc
LDR
r14
,[
sp
]
; get original r0
CDebug_StrReg8
", op="
,
r14
,
cc
LDR
r2
,[
sp
,#
2
*
4
]
; get original r2
MOV
r1
,#
12
00
LDRB
r14
,[
r2
],#
1
CDebug_StrReg2
" "
,
r14
,
cc
SUBS
r1
,
r1
,#
1
BNE
%B00
CDebug_NewLine
LDR
r14
,[
sp
,#
2
*
4
]
; get original r2
LDR
r14
,[
r14
]
CDebug_StrReg8
", cmd="
,
r14
]
; Does the error signal a disc change ?
...
...
@@ -848,18 +765,9 @@ change_of_disc
; r6 = r0 on entry + bit 0 = drive 0 or 1
[
cdebug
CDebug_StrReg8
"change of disc? "
,
r0
,
cc
LDR
r14
,[
sp
]
; get original r0
CDebug_StrReg8
", op="
,
r14
,
cc
LDR
r2
,[
sp
,#
2
*
4
]
; get original r2
MOV
r1
,#
12
00
LDRB
r14
,[
r2
],#
1
CDebug_StrReg2
" "
,
r14
,
cc
SUBS
r1
,
r1
,#
1
BNE
%B00
CDebug_NewLine
CDebug_StrReg8
"change of disc? "
,
r0
]
[
fix_slow_when_no_drives
; if IDENTIFY, don't retry as drive probably not there
...
...
@@ -939,8 +847,8 @@ AR_WriteDataToDrive ROUT
; r5 = amount to send to the drive (can corrupt)
; r9 -> start of transfer
[
cdebug
CDebug_WriteS
"
data out
"
,
cc
[
cdebug
2
CDebug_WriteS
"
send
"
,
cc
]
10
...
...
@@ -949,13 +857,13 @@ AR_WriteDataToDrive ROUT
ORR
r0
,
r0
,
r2
,
LSL
#
8
ORR
r0
,
r0
,
r0
,
LSL
#
16
STR
r0
,[
r1
]
[
cdebug
[
cdebug
2
CDebug_StrReg4
" "
,
r0
,
cc
]
SUBS
r5
,
r5
,#
2
BGT
%B10
[
cdebug
[
cdebug
2
CDebug_NewLine
]
...
...
@@ -994,8 +902,7 @@ WaitForIRQ ROUT
BLO
%B20
; branch if no
[
cdebug
CDebug_Time
CDebug_WriteS
": No IRQ"
CDebug_WriteS
"No IRQ"
]
; no IRQ before timeout
...
...
@@ -1055,12 +962,6 @@ WaitForIRQ ROUT
LDMFD
sp
!,{
r14
}
BICS
pc
,
r14
,#
Zero_Flag
; return NE
;------------------------------------------------------------------------------
[
Version
>
124
LTORG
]
;------------------------------------------------------------------------------
; ATAPI_Reset
;
...
...
@@ -1080,8 +981,7 @@ WaitForIRQ ROUT
ATAPI_Reset
ROUT
[
cdebug
CDebug_Time
CDebug_WriteS
": Reset.."
CDebug_WriteS
"Reset.."
]
STASH
"r0-r2,r14"
...
...
@@ -1112,11 +1012,7 @@ ATAPI_Reset ROUT
; wait for up to 10 seconds for drive to be not BSY
SWI
XOS_ReadMonotonicTime
[
Version
>=
124
ADD
r2
,
r0
,#
TIMEOUT__RESET_RECOVERY
; r2 = finish time
|
ADD
r2
,
r0
,#
10
*
100
; r2 = finish time
]
20
LDRB
r0
,[
r1
,#
TASKFILE__R_STATUS
]
; get status
...
...
@@ -1133,235 +1029,6 @@ ATAPI_Reset ROUT
GRAB
"r0-r2,r14"
BICS
pc
,
r14
,#
Overflow_Flag
;------------------------------------------------------------------------------
[
full_drive_detection
; ATAPI_CheckForDrive
;
; This routine checks to see if a particular drive is an ATAPI drive by
; looking for the special signature in the cylinder/byte_count registers.
; NOTE: this also enables the IRQ output from the drive.
;
; Entry:
; r0 = b0 = ATA drive number
; r12 -> workspace
; r13 -> stack
;
; Exit:
; VC => this drive is an ATAPI drive
; VS => this drive is NOT an ATAPI drive or we couldn't do the stuff
; necessary to determine it
; Would like to have used Z flag but calling sequence only passes V
; back to caller
; Other flags undefined
; All registers preserved
;
;------------------------------------------------------------------------------
ATAPI_CheckForDrive
ROUT
[
cdebug2
CDebug_StrReg2
"CheckForDrive "
,
r0
]
STASH
"r0-r2,r5,r14"
LDR
r1
,
TBA
; r1 -> IDE registers
MOV
r2
,
r0
,
LSL
#
4
; put drive bit in place
ORR
r2
,
r2
,#
DRIVESELECT__ALWAYS
; mandatory bits
SWI
XOS_ReadMonotonicTime
ADD
r5
,
r0
,#
TIMEOUT__SELECTION_PHASE
; r5 = time to give up
; r1 -> IDE registers
; r2 = drive selection value
; r5 = time to abandon selection
[
:LNOT:
bodge_sony_selection
; poll for !BSY before selecting drive - ATA requirement
05
LDR
r0
,[
r1
,#
TASKFILE__R_ALTERNATE_STATUS
]
TSTS
r0
,#
STATUSFLAGS__BSY
BEQ
%F08
; branch if not busy
SWI
XOS_ReadMonotonicTime
CMPS
r0
,
r5
; time to stop?
BLO
%B05
; drive stayed busy so give up
[
cdebug
CDebug_WriteS
"Drive busy (1)"
]
GRAB
"r0-r2,r5,r14"
ORRS
pc
,
r14
,#
Overflow_Flag
; return VS
;;;;;;;;;;;;;;;;;
08
]
10
; select drive
; r2 = drive selection value
STRB
r2
,[
r1
,#
TASKFILE__W_DRIVE_SELECT
]
; wait for other status bits (and regs?) to become valid - 400ns
MOV
r0
,#
1
*
2
; 1/2 us units
BL
DoMicroDelay
; have tried to select drive - check status
LDR
r0
,[
r1
,#
TASKFILE__R_ALTERNATE_STATUS
]
; want BSY=0 - ignore DRDY
TSTS
r0
,#
STATUSFLAGS__BSY
BEQ
%F30
SWI
XOS_ReadMonotonicTime
CMPS
r0
,
r5
; time to stop?
BLO
%B10
; branch if not
; timeout - drive is busy
[
cdebug
CDebug_WriteS
"Drive busy (2)"
]
GRAB
"r0-r2,r5,r14"
ORRS
pc
,
r14
,#
Overflow_Flag
; return VS
;;;;;;;;;;;;;;;;;
30
; drive is not busy
; if DRDY=0, check signature in cylinder selection registers
; Spec seems to suggest that even if DRDY=1 we should check signature but
; this could lead to false detection with a hard disc whose last access left
; the cylinder registers containing the signature. Anyway, issuing the
; IDENTIFY should sort things out.
[
cdebug
CDebug_StrReg2
"Status after drive select = "
,
r0
]
TSTS
r0
,#
STATUSFLAGS__DRDY
; if DRDY=1
[
cdebug
BEQ
%F00
CDebug_WriteS
"DRDY=1 so skipping to IDENTIFY"
00
]
BNE
%F35
; ...skip to IDENTIFY
LDRB
r0
,[
r1
,#
TASKFILE__W_BYTE_COUNT_LOW
]
TEQS
r0
,#
ATAPI_Signature
:AND:
&FF
LDREQB
r14
,[
r1
,#
TASKFILE__W_BYTE_COUNT_HIGH
]
TEQEQS
r14
,#
ATAPI_Signature
>>
8
[
cdebug
BNE
%F00
CDebug_WriteS
"Signature found (1)"
00
]
GRAB
"r0-r2,r5,r14"
,
EQ
; if signature found
BICEQS
pc
,
r14
,#
Overflow_Flag
; ...return VC
[
cdebug
CDebug_StrReg2
"Signature not found (1): "
,
r14
,
cc
CDebug_StrReg2
" "
,
r0
]
35
; either DRDY=1 or signature is not present so issue an ATA IDENTIFY to
; cause drive to reset its registers and try again
[
cdebug
CDebug_WriteS
"ATA IDENTIFY"
]
MOV
r0
,#
FEATUREBITS__PIO
STRB
r0
,[
r1
,#
TASKFILE__W_FEATURES
]
; do a quick read of status register to clear any pending IRQ
; shouldn't be necessary but may get us out of trouble later
LDRB
r0
,[
r1
,#
TASKFILE__R_STATUS
]
; now send the command to the drive
MOV
r0
,#
IDE__IDENTIFY
STRB
r0
,[
r1
,#
TASKFILE__W_COMMAND
]
; wait 400ns for BSY to be asserted
MOV
r0
,#
1
*
2
; 1/2 us units
BL
DoMicroDelay
; wait for BSY to be deasserted
SWI
XOS_ReadMonotonicTime
ADD
r5
,
r0
,#
TIMEOUT__COMMAND_COMPLETE
; r5 = time to give up
40
LDR
r0
,[
r1
,#
TASKFILE__R_ALTERNATE_STATUS
]
TSTS
r0
,#
STATUSFLAGS__BSY
BEQ
%F50
SWI
XOS_ReadMonotonicTime
CMPS
r0
,
r5
; time to stop?
BLO
%B40
; branch if not
; drive did not deassert BSY
[
cdebug
CDebug_WriteS
"Drive busy (3)"
]
GRAB
"r0-r2,r5,r14"
ORRS
pc
,
r14
,#
Overflow_Flag
; return VS
;;;;;;;;;;;;;;;;;
50
; drive no longer busy - wait 400ns and then check status
MOV
r0
,#
1
*
2
; 1/2 us units
BL
DoMicroDelay
LDR
r0
,[
r1
,#
TASKFILE__R_STATUS
]
; also clears IRQ
[
cdebug
CDebug_StrReg2
"ATA IDENTIFY status "
,
r0
]
TSTS
r0
,#
STATUSFLAGS__CHECK
; error?
BNE
%F70
; branch if so
; no error - ATAPI devices should cause an error but we don't really care;
; the catch is that we now have to read any data that the drive has returned
TSTS
r0
,#
STATUSFLAGS__DRQ
; data waiting?
BNE
%F70
; branch if not
; OK: read 512 bytes and then move on
MOV
r0
,#
512
60
LDR
r14
,[
r1
,#
TASKFILE__R_DATA
]
; get 16 bits
SUBS
r0
,
r0
,#
2
BNE
%B60
70
; IDENTIFY caused error or there was no data or we've read the data
; Now look for the ATAPI signature again
LDRB
r0
,[
r1
,#
TASKFILE__W_BYTE_COUNT_LOW
]
TEQS
r0
,#
ATAPI_Signature
:AND:
&FF
LDREQB
r14
,[
r1
,#
TASKFILE__W_BYTE_COUNT_HIGH
]
TEQEQS
r14
,#
ATAPI_Signature
>>
8
[
cdebug
BNE
%F00
CDebug_WriteS
"Signature found (2)"
B
%F01
00
CDebug_StrReg2
"Signature not found (2): "
,
r14
,
cc
CDebug_StrReg2
" "
,
r0
01
]
GRAB
"r0-r2,r5,r14"
BICEQS
pc
,
r14
,#
Overflow_Flag
ORRNES
pc
,
r14
,#
Overflow_Flag
]
;------------------------------------------------------------------------------
;
; DoMicroDelay
...
...
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