mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-27 02:14:19 +00:00
Upload
Digital Research
This commit is contained in:
342
CONTRIBUTIONS/cpm-handbook/cpmsrc/FIG9-5.ASM
Normal file
342
CONTRIBUTIONS/cpm-handbook/cpmsrc/FIG9-5.ASM
Normal file
@@ -0,0 +1,342 @@
|
||||
; Figure 9-5
|
||||
;
|
||||
; This shows slightly more user-friendly error processor
|
||||
; for disk errors than that shown in the enhanced BIOS
|
||||
; in Figure 8-10.
|
||||
; This version outputs a recommended course of action
|
||||
; depending on the nature of the error detected.
|
||||
; Code that remains unchanged from Figure 8-10 has been
|
||||
; abbreviated.
|
||||
;
|
||||
; Dummy Equates and data declarations needed to get
|
||||
; an error free assembly of this example.
|
||||
;
|
||||
Floppy$Read$Code EQU 01H ;Read Command for controller
|
||||
Floppy$Write$Code EQU 02H ;Write Command for controller
|
||||
;
|
||||
Disk$Hung$Flag: DB 0 ;Set NZ when Watchdog timer times
|
||||
; out.
|
||||
Disk$Timer EQU 600 ;10 seconds delay (16.66ms tick)
|
||||
;
|
||||
Disk$Status$Block EQU 43H ;Address in memory where controller
|
||||
; returns status
|
||||
;Values from controller command table
|
||||
Floppy$Command: DB 0
|
||||
Floppy$Head: DB 0
|
||||
Floppy$Track: DB 0
|
||||
Floppy$Sector: DB 0
|
||||
|
||||
Deblocking$Required: DB 0 ;Flag set by SELDSK according
|
||||
; to selected disk type
|
||||
|
||||
Disk$Error$Flag: DB 0 ;Error flag returned to BDOS
|
||||
;
|
||||
In$Buffer$Disk: DB 0 ;Logical disk Id. relating to current
|
||||
; disk sector in deblocking buffer
|
||||
;
|
||||
; Equates for Messages
|
||||
;
|
||||
BELL EQU 07H ;Sound terminal Bell
|
||||
CR EQU 0DH ;Carriage Return
|
||||
LF EQU 0AH ;Line Feed
|
||||
;
|
||||
BDOS EQU 5 ;BDOS Entry Point (for system reset)
|
||||
;
|
||||
;
|
||||
;
|
||||
;
|
||||
No$Deblock$Retry:
|
||||
;----------------------------------------------------
|
||||
; Omitted code to setup disk controller command table
|
||||
; and initiate the disk operation
|
||||
;----------------------------------------------------
|
||||
JMP Wait$For$Disk$Complete
|
||||
;
|
||||
;
|
||||
Write$Physical: ;Write contents of Disk Buffer to
|
||||
; correct sector.
|
||||
MVI A,Floppy$Write$Code ;Get Write Function code
|
||||
JMP Common$Physical ;Go to common code
|
||||
Read$Physical: ;Read previously selected Sector
|
||||
; into Disk Buffer.
|
||||
MVI A,Floppy$Read$Code ;Get Read Function code
|
||||
Common$Physical:
|
||||
STA Floppy$Command ;Set command table
|
||||
|
||||
;
|
||||
Deblock$Retry: ;Re-entry point to re-try after error
|
||||
;---------------------------------------------------
|
||||
; Omitted code sets up disk controller command block
|
||||
; and initiates the disk operation
|
||||
;---------------------------------------------------
|
||||
;
|
||||
Wait$For$Disk$Complete: ;Wait until Disk Status Block indicates
|
||||
; operation has completed, then check
|
||||
; if any errors occurred.
|
||||
;On entry HL -> Disk Control byte
|
||||
XRA A ;Ensure hung flag clear
|
||||
STA Disk$Hung$Flag
|
||||
|
||||
LXI H,Disk$Timed$Out ;Setup Watchdog timer
|
||||
LXI B,Disk$Timer ;Time delay
|
||||
CALL Set$Watchdog
|
||||
Disk$Wait$Loop:
|
||||
MOV A,M ;Get control byte
|
||||
ORA A
|
||||
JZ Disk$Complete ;Operation done
|
||||
|
||||
LDA Disk$Hung$Flag ;Also check if timed out
|
||||
ORA A
|
||||
JNZ Disk$Error ;Will be set to 40H
|
||||
|
||||
JMP Disk$Wait$Loop
|
||||
|
||||
Disk$Timed$Out: ;Control arrives here from Watchdog
|
||||
; routine itself - so this is effectively
|
||||
; part of the interrupt service routine.
|
||||
MVI A,40H ;Set Disk Hung error code
|
||||
STA Disk$Hung$Flag ; into error flag to pull
|
||||
; control out of loop
|
||||
RET ;Return to Watchdog routine
|
||||
|
||||
Disk$Complete:
|
||||
LXI B,0 ;Reset Watchdog timer
|
||||
;HL is irrelevant here
|
||||
CALL Set$Watchdog
|
||||
|
||||
LDA Disk$Status$Block ;Complete - now check status
|
||||
CPI 80H ;Check if any errors occurred
|
||||
JC Disk$Error ;Yes
|
||||
;
|
||||
Disk$Error$Ignore:
|
||||
XRA A ;No
|
||||
STA Disk$Error$Flag ;Clear error flag
|
||||
RET
|
||||
|
||||
;
|
||||
; Disk Error Message handling
|
||||
;
|
||||
;
|
||||
Disk$Error$Messages: ;This table is scanned, comparing the
|
||||
; Disk Error Status with those in the
|
||||
; table. Given a match, or even when
|
||||
; then end of the table is reached, the
|
||||
; address following the status value
|
||||
; points to the correct advisory message text.
|
||||
; Following this is the address of an
|
||||
; error description message.
|
||||
DB 40H
|
||||
DW Disk$Advice1,Disk$Msg$40
|
||||
DB 41H
|
||||
DW Disk$Advice2,Disk$Msg$41
|
||||
DB 42H
|
||||
DW Disk$Advice3,Disk$Msg$42
|
||||
DB 21H
|
||||
DW Disk$Advice4,Disk$Msg$21
|
||||
DB 22H
|
||||
DW Disk$Advice5,Disk$Msg$22
|
||||
DB 23H
|
||||
DW Disk$Advice5,Disk$Msg$23
|
||||
DB 24H
|
||||
DW Disk$Advice6,Disk$Msg$24
|
||||
DB 25H
|
||||
DW Disk$Advice6,Disk$Msg$25
|
||||
DB 11H
|
||||
DW Disk$Advice7,Disk$Msg$11
|
||||
DB 12H
|
||||
DW Disk$Advice7,Disk$Msg$12
|
||||
DB 13H
|
||||
DW Disk$Advice7,Disk$Msg$13
|
||||
DB 14H
|
||||
DW Disk$Advice7,Disk$Msg$14
|
||||
DB 15H
|
||||
DW Disk$Advice7,Disk$Msg$15
|
||||
DB 16H
|
||||
DW Disk$Advice7,Disk$Msg$16
|
||||
DB 0 ;<== Terminator
|
||||
DW Disk$Advice7,Disk$Msg$Unknown ;Unmatched code
|
||||
;
|
||||
DEM$Entry$Size EQU 5 ;Entry size in Error Message Table
|
||||
;
|
||||
;
|
||||
; Message Texts
|
||||
;
|
||||
Disk$Msg$40: DB 'Hung',0 ;Timeout message
|
||||
Disk$Msg$41: DB 'Not Ready',0
|
||||
Disk$Msg$42: DB 'Write Protected',0
|
||||
Disk$Msg$21: DB 'Data',0
|
||||
Disk$Msg$22: DB 'Format',0
|
||||
Disk$Msg$23: DB 'Missing Data Mark',0
|
||||
Disk$Msg$24: DB 'Bus Timeout',0
|
||||
Disk$Msg$25: DB 'Controller Timeout',0
|
||||
Disk$Msg$11: DB 'Drive Address',0
|
||||
Disk$Msg$12: DB 'Head Address',0
|
||||
Disk$Msg$13: DB 'Track Address',0
|
||||
Disk$Msg$14: DB 'Sector Address',0
|
||||
Disk$Msg$15: DB 'Bus Address',0
|
||||
Disk$Msg$16: DB 'Illegal Command',0
|
||||
Disk$Msg$Unknown: DB 'Unknown',0
|
||||
;
|
||||
Disk$EM$1: ;Main disk error message - part 1
|
||||
DB BELL,CR,LF
|
||||
DB 'Disk ',0
|
||||
;
|
||||
;Error Text output next
|
||||
;
|
||||
Disk$EM$2: ;Main disk error message - part 2
|
||||
DB ' Error ('
|
||||
Disk$EM$Status: DB 0,0 ;Status code in Hex
|
||||
DB ')',CR,LF,' Drive '
|
||||
Disk$EM$Drive: DB 0 ;Disk Drive code, A,B...
|
||||
DB ', Head '
|
||||
Disk$EM$Head: DB 0 ;Head number
|
||||
DB ', Track '
|
||||
Disk$EM$Track: DB 0,0 ;Track number
|
||||
DB ', Sector '
|
||||
Disk$EM$Sector: DB 0,0 ;Sector number
|
||||
DB ', Operation - '
|
||||
DB 0 ;Terminator
|
||||
;
|
||||
Disk$EM$Read: DB 'Read.',0 ;Operation names
|
||||
Disk$EM$Write: DB 'Write.',0
|
||||
;
|
||||
Disk$Advice0: DB CR,LF,' ',0
|
||||
Disk$Advice1: DB 'Check disk loaded, Retry',0
|
||||
Disk$Advice2: DB 'Possible hardware problem',0
|
||||
Disk$Advice3: DB 'Write enable if correct disk, Retry',0
|
||||
Disk$Advice4: DB 'Retry several times',0
|
||||
Disk$Advice5: DB 'Reformat disk or use another disk',0
|
||||
Disk$Advice6: DB 'Hardware error, Retry',0
|
||||
Disk$Advice7: DB 'Hardware or Software error, Retry',0
|
||||
;
|
||||
Disk$Advice9: DB ', or call for help if error persists',CR,LF
|
||||
;
|
||||
Disk$Action$Confirm:
|
||||
DB 0 ;Set to character entered by user
|
||||
DB CR,LF,0
|
||||
;
|
||||
; Disk Error Processor
|
||||
;
|
||||
; This routine builds and outputs an error message.
|
||||
; The user is then given the opportunity to :
|
||||
;
|
||||
; R - Retry the operation that caused the error.
|
||||
; I - Ignore the error and attempt to continue.
|
||||
; A - Abort the program and return to CP/M.
|
||||
;
|
||||
Disk$Error:
|
||||
PUSH PSW ;Preserve error code from controller
|
||||
LXI H,Disk$EM$Status ;Convert code for message
|
||||
CALL CAH ;Converts A to hex
|
||||
|
||||
LDA In$Buffer$Disk ;Convert disk id. for message
|
||||
ADI 'A' ;Make into letter
|
||||
STA Disk$EM$Drive
|
||||
|
||||
LDA Floppy$Head ;Convert head number
|
||||
ADI '0'
|
||||
STA Disk$EM$Head
|
||||
|
||||
LDA Floppy$Track ;Convert track number
|
||||
LXI H,Disk$EM$Track
|
||||
CALL CAH
|
||||
|
||||
LDA Floppy$Sector ;Convert sector number
|
||||
LXI H,Disk$EM$Sector
|
||||
CALL CAH
|
||||
|
||||
LXI H,Disk$EM$1 ;Output first part of message
|
||||
CALL Output$Error$Message
|
||||
|
||||
POP PSW ;Recover error status code
|
||||
MOV B,A ;For comparisons
|
||||
LXI H,Disk$Error$Messages - DEM$Entry$Size
|
||||
;HL -> Table - one entry
|
||||
LXI D,DEM$Entry$Size ;For loop below
|
||||
Disk$Error$Next$Code:
|
||||
DAD D ;Move to next (or first) entry
|
||||
|
||||
MOV A,M ;Get code number from table
|
||||
ORA A ;Check if end of table
|
||||
JZ Disk$Error$Matched ;Yes - pretend a match occurred
|
||||
CMP B ;Compare to actual code
|
||||
JZ Disk$Error$Matched ;Yes - exit from loop
|
||||
JMP Disk$Error$Next$Code ;Check next code
|
||||
;
|
||||
Disk$Error$Matched:
|
||||
INX H ;HL -> Advisory text address
|
||||
MOV E,M
|
||||
INX H
|
||||
MOV D,M ;DE -> Advisory test
|
||||
PUSH D ;Save for later
|
||||
|
||||
INX H ;HL -> Message text address
|
||||
MOV E,M ;Get Address into DE
|
||||
INX H
|
||||
MOV D,M
|
||||
|
||||
XCHG ;HL -> Text
|
||||
CALL Output$Error$Message ;Display explanatory text
|
||||
|
||||
LXI H,Disk$EM$2 ;Display second part of message
|
||||
CALL Output$Error$Message
|
||||
|
||||
LXI H,Disk$EM$Read ;Choose operation text
|
||||
; (assume a read)
|
||||
LDA Floppy$Command ;Get controller command
|
||||
CPI Floppy$Read$Code
|
||||
JZ Disk$Error$Read ;Yes
|
||||
LXI H,Disk$EM$Write ;No - change address in HL
|
||||
Disk$Error$Read:
|
||||
CALL Output$Error$Message ;Display operation type
|
||||
|
||||
LXI H,Disk$Advice0 ;Display leading blanks
|
||||
CALL Output$Error$Message
|
||||
|
||||
POP H ;Recover Advisory text pointer
|
||||
CALL Output$Error$Message
|
||||
|
||||
LXI H,Disk$Advice9 ;Display trailing component
|
||||
CALL Output$Error$Message
|
||||
;
|
||||
Disk$Error$Request$Action: ;Ask the user what to do next
|
||||
CALL Request$User$Choice ;Display prompt and get single
|
||||
; character response (folded to
|
||||
; upper case)
|
||||
CPI 'R' ;Retry?
|
||||
JZ Disk$Error$Retry
|
||||
CPI 'A' ;Abort
|
||||
JZ System$Reset
|
||||
CPI 'I' ;Ignore
|
||||
JZ Disk$Error$Ignore
|
||||
JMP Disk$Error$Request$Action
|
||||
;
|
||||
Disk$Error$Retry: ;The decision on where to return to
|
||||
; depends on whether the operation
|
||||
; failed on a deblocked or
|
||||
; non-deblocked drive
|
||||
LDA Deblocking$Required
|
||||
ORA A
|
||||
JNZ Deblock$Retry
|
||||
JMP No$Deblock$Retry
|
||||
;
|
||||
System$Reset: ;This is a radical approach, but
|
||||
; it does cause CP/M to restart
|
||||
MVI C,0 ;System Reset
|
||||
CALL BDOS
|
||||
|
||||
;
|
||||
; Omitted subroutines (listed in full in Figure 8-10)
|
||||
;
|
||||
Set$Watchdog: ;Set Watchdog timer (to number of "ticks" in BC, and
|
||||
; to transfer control to (HL) if timer hits zero).
|
||||
CAH: ;Convert A to two ASCII hex characters, storing
|
||||
; the output in (HL) and (HL+1)
|
||||
Output$Error$Message: ;Display the 00-byte terminated error message
|
||||
; pointed to by HL. Output is directed only to
|
||||
; those console devices not being used for list
|
||||
; output as well.
|
||||
Request$User$Choice: ;Display prompt "Enter R, A, I..." and return
|
||||
; single keyboard character (upper case) in A
|
||||
RET ;Dummy
|
||||
|
||||
Reference in New Issue
Block a user