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

;
;==================================================================================================
; 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