mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
383 lines
7.8 KiB
383 lines
7.8 KiB
;
|
|
;==================================================================================================
|
|
; HDSK DISK DRIVER
|
|
;==================================================================================================
|
|
;
|
|
HDSK_UNITCNT .EQU 2 ; TWO VIRTUAL HARD DISKS
|
|
;
|
|
; IO PORT ADDRESSES
|
|
;
|
|
HDSK_IO .EQU $FD
|
|
;
|
|
HDSK_CMDNONE .EQU 0
|
|
HDSK_CMDRESET .EQU 1
|
|
HDSK_CMDREAD .EQU 2
|
|
HDSK_CMDWRITE .EQU 3
|
|
HDSK_CMDPARAM .EQU 4
|
|
;
|
|
; STATUS
|
|
;
|
|
HDSKRC_OK .EQU 0
|
|
;
|
|
;
|
|
;
|
|
HDSK_INIT:
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("HDSK: UNITS=$")
|
|
LD A,HDSK_UNITCNT
|
|
CALL PRTDECB
|
|
;
|
|
; SETUP THE DISPATCH TABLE ENTRIES
|
|
;
|
|
LD B,HDSK_UNITCNT ; LOOP CONTROL
|
|
LD C,0 ; PHYSICAL UNIT INDEX
|
|
HDSK_INIT0:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
LD B,C ; PHYSICAL UNIT
|
|
LD C,DIODEV_HDSK ; DEVICE TYPE
|
|
LD DE,0 ; UNIT DATA BLOB ADDRESS
|
|
CALL DIO_ADDENT ; ADD ENTRY, BC IS NOT DESTROYED
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
INC C ; NEXT PHYSICAL UNIT
|
|
DJNZ HDSK_INIT0 ; LOOP UNTIL DONE
|
|
;
|
|
XOR A
|
|
DEC A ; INITIAL STATUS IS NOT READY $FF
|
|
LD (HDSK_STAT),A ; SAVE IT
|
|
XOR A ; INIT SUCCEEDED
|
|
RET ; RETURN
|
|
;
|
|
;
|
|
;
|
|
HDSK_DISPATCH:
|
|
; SAVE THE TARGET DEVICE/UNIT LOCALLY IN DRIVER
|
|
LD A,C ; DEVICE/UNIT FROM C
|
|
AND $0F ; ISOLATE UNIT NUM
|
|
CP 2 ; CHECK FOR MAX UNIT EXCEEDED
|
|
LD (HDSK_UNIT),A ; SAVE IT
|
|
CALL NC,PANIC ; PANIC IF TOO HIGH
|
|
;
|
|
; DISPATCH ACCORDING TO DISK SUB-FUNCTION
|
|
LD A,B ; GET REQUESTED FUNCTION
|
|
AND $0F ; ISOLATE SUB-FUNCTION
|
|
JP Z,HDSK_STATUS ; SUB-FUNC 0: STATUS
|
|
DEC A
|
|
JP Z,HDSK_RESET ; SUB-FUNC 1: RESET
|
|
DEC A
|
|
JP Z,HDSK_SEEK ; SUB-FUNC 2: SEEK
|
|
DEC A
|
|
JP Z,HDSK_READ ; SUB-FUNC 3: READ SECTORS
|
|
DEC A
|
|
JP Z,HDSK_WRITE ; SUB-FUNC 4: WRITE SECTORS
|
|
DEC A
|
|
JP Z,HDSK_VERIFY ; SUB-FUNC 5: VERIFY SECTORS
|
|
DEC A
|
|
JP Z,HDSK_FORMAT ; SUB-FUNC 6: FORMAT TRACK
|
|
DEC A
|
|
JP Z,HDSK_DEVICE ; SUB-FUNC 7: DEVICE REPORT
|
|
DEC A
|
|
JP Z,HDSK_MEDIA ; SUB-FUNC 8: MEDIA REPORT
|
|
DEC A
|
|
JP Z,HDSK_DEFMED ; SUB-FUNC 9: DEFINE MEDIA
|
|
DEC A
|
|
JP Z,HDSK_CAP ; SUB-FUNC 10: REPORT CAPACITY
|
|
DEC A
|
|
JP Z,HDSK_GEOM ; SUB-FUNC 11: REPORT GEOMETRY
|
|
;
|
|
HDSK_VERIFY:
|
|
HDSK_FORMAT:
|
|
HDSK_DEFMED:
|
|
CALL PANIC ; INVALID SUB-FUNCTION
|
|
;
|
|
;
|
|
;
|
|
HDSK_STATUS:
|
|
LD A,(HDSK_STAT) ; LOAD STATUS
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
HDSK_RESET:
|
|
XOR A ; ALWAYS OK
|
|
RET
|
|
;
|
|
; GET DISK CAPACITY
|
|
; RETURN DE:HL=BLOCK COUNT, BC=BLOCK SIZE
|
|
; SLICE C/H/S = 65/16/16 OR 16,640 TOTAL SECTORS
|
|
; ASSUME 8 SLICES, SO 16640 X 8 = 133,120 TOTAL SECTORS
|
|
;
|
|
HDSK_CAP:
|
|
LD DE,133120 >> 16 ; BLOCK COUNT MSW
|
|
LD HL,133120 & $FFFF ; BLOCK COUNT LSW
|
|
LD BC,512 ; 512 BYTE SECTOR
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
HDSK_GEOM:
|
|
; FOR LBA, WE SIMULATE CHS ACCESS USING 16 HEADS AND 16 SECTORS
|
|
; RETURN HS:CC -> DE:HL, SET HIGH BIT OF D TO INDICATE LBA CAPABLE
|
|
CALL HDSK_CAP ; GET TOTAL BLOCKS IN DE:HL, BLOCK SIZE TO BC
|
|
LD L,H ; DIVIDE BY 256 FOR # TRACKS
|
|
LD H,E ; ... HIGH BYTE DISCARDED, RESULT IN HL
|
|
LD D,$80 | 16 ; HEADS / CYL = 16, SET LBA BIT
|
|
LD E,16 ; SECTORS / TRACK = 16
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
HDSK_DEVICE:
|
|
LD D,DIODEV_HDSK ; D := DEVICE TYPE
|
|
LD E,C ; E := PHYSICAL UNIT
|
|
LD C,%00000000 ; C := ATTRIBUTES, NON-REMOVABLE HARD DISK
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
HDSK_MEDIA:
|
|
LD E,MID_HD ; HARD DISK MEDIA
|
|
LD D,0 ; D:0=0 MEANS NO MEDIA CHANGE
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
HDSK_SEEK:
|
|
BIT 7,D ; CHECK FOR LBA FLAG
|
|
CALL Z,HB_CHS2LBA ; CLEAR MEANS CHS, CONVERT TO LBA
|
|
RES 7,D ; CLEAR FLAG REGARDLESS (DOES NO HARM IF ALREADY LBA)
|
|
LD BC,HSTLBA ; POINT TO LBA STORAGE
|
|
CALL ST32 ; SAVE LBA ADDRESS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
HDSK_READ:
|
|
LD (HDSK_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
|
LD A,HDSK_CMDREAD
|
|
JR HDSK_RW
|
|
;
|
|
;
|
|
;
|
|
HDSK_WRITE:
|
|
LD (HDSK_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
|
LD A,HDSK_CMDWRITE
|
|
JR HDSK_RW
|
|
;
|
|
;
|
|
;
|
|
HDSK_RW:
|
|
LD (HDSK_CMD),A
|
|
|
|
; CLEAR RESULTS
|
|
XOR A ; A = 0
|
|
LD (HDSK_RC),A ; CLEAR RETURN CODE
|
|
|
|
; INIT IF NEEDED
|
|
LD A,(HDSK_STAT) ; GET CURRENT STATUS
|
|
OR A ; SET FLAGS
|
|
CALL NZ,HDSK_DSKRESET ; RESET IF NOT READY
|
|
|
|
; SET DEVICE
|
|
LD A,(HDSK_UNIT)
|
|
;AND $0F
|
|
LD (HDSK_DEV),A
|
|
|
|
; ; INCOMING TRK:SEC ACTUALLY REPRESENTS 32 BIT LBA
|
|
; ; MAP TRK:SEC TO HDSK DRIVER AS TTSS:SS
|
|
;
|
|
; LD A,(HSTTRK) ; LSB OF TRACK
|
|
; LD (HDSK_TRK + 1),A ; MAPS TO MSB OF HDSK TRK
|
|
; LD A,(HSTSEC + 1) ; MSB OF SECTOR
|
|
; LD (HDSK_TRK),A ; MAPS TO LSB OF HDSK TRK
|
|
; LD A,(HSTSEC) ; LSB OF SECTOR
|
|
; LD (HDSK_SEC),A ; MAPS TO LSB OF HDSK SEC
|
|
|
|
; INCOMING ADDRESS IS LBA
|
|
; MAP HHHH:LLLL TO HDSK DRIVER AS HHLL:LL
|
|
|
|
LD A,(HSTLBAHI) ; LSB OF LBA HIGH
|
|
LD (HDSK_TRK + 1),A ; MAPS TO MSB OF HDSK TRK
|
|
LD A,(HSTLBALO + 1) ; MSB OF LBA LOW
|
|
LD (HDSK_TRK),A ; MAPS TO LSB OF HDSK TRK
|
|
LD A,(HSTLBALO) ; LSB OF LBA LOW
|
|
LD (HDSK_SEC),A ; MAPS TO LSB OF HDSK SEC
|
|
|
|
; SET TRANSFER ADDRESS
|
|
LD BC,(HDSK_DSKBUF)
|
|
LD (HDSK_DMA),BC
|
|
|
|
; EXECUTE COMMAND
|
|
LD B,7 ; SIZE OF PARAMETER BLOCK
|
|
LD HL,HDSK_PARMBLK ; START ADDRESS OF PARAMETER BLOCK
|
|
HDSK_RW1:
|
|
LD A,(HL) ; GET BYTE OF PARAMETER BLOCK
|
|
OUT ($FD),A ; SEND IT TO PORT
|
|
INC HL ; POINT TO NEXT BYTE
|
|
DJNZ HDSK_RW1
|
|
|
|
IN A,($FD) ; GET RESULT CODE
|
|
LD (HDSK_RC),A
|
|
OR A
|
|
JR Z,HDSK_OK
|
|
JR HDSK_ERR
|
|
|
|
HDSK_ERR:
|
|
XOR A
|
|
DEC A ; A=$FF TO SIGNAL ERROR
|
|
LD (HDSK_STAT),A ; SAVE IT
|
|
#IF (HDSKTRACE >= 1)
|
|
PUSH AF
|
|
CALL HDSK_PRT
|
|
POP AF
|
|
#ENDIF
|
|
RET
|
|
|
|
HDSK_OK:
|
|
#IF (HDSKTRACE >= 2)
|
|
CALL HDSK_PRT
|
|
#ENDIF
|
|
XOR A
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
HDSK_DSKRESET:
|
|
LD B,32
|
|
LD A,HDSK_CMDRESET
|
|
HDSK_DSKRESET1:
|
|
OUT ($FD),A
|
|
DJNZ HDSK_DSKRESET1
|
|
|
|
XOR A ; STATUS = OK
|
|
LD (HDSK_STAT),A ; SAVE IT
|
|
|
|
#IF (HDSKTRACE >= 2)
|
|
CALL NEWLINE
|
|
LD DE,HDSKSTR_PREFIX
|
|
CALL WRITESTR
|
|
CALL PC_SPACE
|
|
LD DE,HDSKSTR_RESET
|
|
CALL WRITESTR
|
|
#ENDIF
|
|
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
HDSK_PRT:
|
|
CALL NEWLINE
|
|
|
|
LD DE,HDSKSTR_PREFIX
|
|
CALL WRITESTR
|
|
|
|
CALL PC_SPACE
|
|
LD DE,HDSKSTR_CMD
|
|
CALL WRITESTR
|
|
LD A,(HDSK_CMD)
|
|
CALL PRTHEXBYTE
|
|
|
|
CALL PC_SPACE
|
|
CALL PC_LBKT
|
|
LD A,(HDSK_CMD)
|
|
LD DE,HDSKSTR_NONE
|
|
CP HDSK_CMDNONE
|
|
JP Z,HDSK_PRTCMD
|
|
LD DE,HDSKSTR_RESET
|
|
CP HDSK_CMDRESET
|
|
JP Z,HDSK_PRTCMD
|
|
LD DE,HDSKSTR_READ
|
|
CP HDSK_CMDREAD
|
|
JP Z,HDSK_PRTCMD
|
|
LD DE,HDSKSTR_WRITE
|
|
CP HDSK_CMDWRITE
|
|
JP Z,HDSK_PRTCMD
|
|
LD DE,HDSKSTR_PARAM
|
|
CP HDSK_CMDPARAM
|
|
JP Z,HDSK_PRTCMD
|
|
LD DE,HDSKSTR_UNKCMD
|
|
HDSK_PRTCMD:
|
|
CALL WRITESTR
|
|
CALL PC_RBKT
|
|
|
|
LD A,(HDSK_CMD)
|
|
CP HDSK_CMDREAD
|
|
JR Z,HDSK_PRTRW
|
|
CP HDSK_CMDWRITE
|
|
JR Z,HDSK_PRTRW
|
|
RET
|
|
|
|
HDSK_PRTRW:
|
|
CALL PC_SPACE
|
|
LD A,(HDSK_DEV)
|
|
CALL PRTHEXBYTE
|
|
CALL PC_SPACE
|
|
LD BC,(HDSK_TRK)
|
|
CALL PRTHEXWORD
|
|
CALL PC_SPACE
|
|
LD A,(HDSK_SEC)
|
|
CALL PRTHEXBYTE
|
|
CALL PC_SPACE
|
|
LD BC,(HDSK_DSKBUF)
|
|
CALL PRTHEXWORD
|
|
|
|
CALL PC_SPACE
|
|
LD DE,HDSKSTR_ARROW
|
|
CALL WRITESTR
|
|
|
|
CALL PC_SPACE
|
|
LD DE,HDSKSTR_RC
|
|
CALL WRITESTR
|
|
LD A,(HDSK_RC)
|
|
CALL PRTHEXBYTE
|
|
|
|
CALL PC_SPACE
|
|
CALL PC_LBKT
|
|
LD A,(HDSK_RC)
|
|
LD DE,HDSKSTR_RCOK
|
|
CP HDSKRC_OK
|
|
JP Z,HDSK_PRTRC
|
|
LD DE,HDSKSTR_RCUNK
|
|
|
|
HDSK_PRTRC:
|
|
CALL WRITESTR
|
|
CALL PC_RBKT
|
|
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
HDSKSTR_PREFIX .TEXT "HDSK:$"
|
|
HDSKSTR_CMD .TEXT "CMD=$"
|
|
HDSKSTR_RC .TEXT "RC=$"
|
|
HDSKSTR_ARROW .TEXT "-->$"
|
|
HDSKSTR_NONE .TEXT "NONE$"
|
|
HDSKSTR_RESET .TEXT "RESET$"
|
|
HDSKSTR_READ .TEXT "READ$"
|
|
HDSKSTR_WRITE .TEXT "WRITE$"
|
|
HDSKSTR_PARAM .TEXT "PARAM$"
|
|
HDSKSTR_UNKCMD .TEXT "UNKCMD$"
|
|
HDSKSTR_RCOK .TEXT "OK$"
|
|
HDSKSTR_RCUNK .TEXT "UNKNOWN ERROR$"
|
|
;
|
|
;==================================================================================================
|
|
; HDSK DISK DRIVER - DATA
|
|
;==================================================================================================
|
|
;
|
|
HDSK_STAT .DB 0
|
|
HDSK_RC .DB 0
|
|
;
|
|
HDSK_UNIT .DB 0
|
|
HDSK_DSKBUF .DW 0
|
|
;
|
|
HDSK_PARMBLK:
|
|
HDSK_CMD .DB 0 ; COMMAND (HDSK_READ, HDSK_WRITE, ...)
|
|
HDSK_DEV .DB 0 ; 0..7, HARD DISK UNIT
|
|
HDSK_SEC .DB 0 ; 0..255 SECTOR
|
|
HDSK_TRK .DW 0 ; 0..2047 TRACK
|
|
HDSK_DMA .DW 0 ; DEFINES WHERE RESULT IS PLACED IN MEMORY
|
|
|