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.
414 lines
9.2 KiB
414 lines
9.2 KiB
;
|
|
;==================================================================================================
|
|
; MD DISK DRIVER (MEMORY DISK)
|
|
;==================================================================================================
|
|
;
|
|
; MD DEVICE CONFIGURATION
|
|
;
|
|
MD_DEVCNT .EQU 2 ; NUMBER OF MD DEVICES SUPPORTED
|
|
MD_CFGSIZ .EQU 6 ; SIZE OF CFG TBL ENTRIES
|
|
;
|
|
MD_DEV .EQU 0 ; OFFSET OF DEVICE NUMBER (BYTE)
|
|
MD_STAT .EQU 1 ; OFFSET OF STATUS (BYTE)
|
|
MD_LBA .EQU 2 ; OFFSET OF LBA (DWORD)
|
|
;
|
|
; DEVICE CONFIG TABLE (RAM DEVICE FIRST TO MAKE IT ALWAYS FIRST DRIVE)
|
|
;
|
|
MD_CFGTBL:
|
|
; DEVICE 1 (RAM)
|
|
.DB 1 ; DRIVER DEVICE NUMBER
|
|
.DB 0 ; DEVICE STATUS
|
|
.DW 0,0 ; CURRENT LBA
|
|
; DEVICE 0 (ROM)
|
|
.DB 0 ; DEVICE NUMBER
|
|
.DB 0 ; DEVICE STATUS
|
|
.DW 0,0 ; CURRENT LBA
|
|
;
|
|
#IF ($ - MD_CFGTBL) != (MD_DEVCNT * MD_CFGSIZ)
|
|
.ECHO "*** INVALID MD CONFIG TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
.DB $FF ; END MARKER
|
|
;
|
|
;
|
|
;
|
|
MD_INIT:
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("MD: UNITS=2 $")
|
|
PRTS("ROMDISK=$")
|
|
LD HL,ROMSIZE - 128
|
|
CALL PRTDEC
|
|
PRTS("KB RAMDISK=$")
|
|
LD HL,RAMSIZE - 128
|
|
CALL PRTDEC
|
|
PRTS("KB$")
|
|
;
|
|
; SETUP THE DIO TABLE ENTRIES
|
|
;
|
|
LD BC,MD_FNTBL
|
|
LD DE,MD_CFGTBL
|
|
PUSH BC
|
|
CALL DIO_ADDENT
|
|
POP BC
|
|
LD DE,MD_CFGTBL + MD_CFGSIZ
|
|
CALL DIO_ADDENT
|
|
;
|
|
XOR A ; INIT SUCCEEDED
|
|
RET ; RETURN
|
|
;
|
|
;
|
|
;
|
|
MD_FNTBL:
|
|
.DW MD_STATUS
|
|
.DW MD_RESET
|
|
.DW MD_SEEK
|
|
.DW MD_READ
|
|
.DW MD_WRITE
|
|
.DW MD_VERIFY
|
|
.DW MD_FORMAT
|
|
.DW MD_DEVICE
|
|
.DW MD_MEDIA
|
|
.DW MD_DEFMED
|
|
.DW MD_CAP
|
|
.DW MD_GEOM
|
|
#IF (($ - MD_FNTBL) != (DIO_FNCNT * 2))
|
|
.ECHO "*** INVALID MD FUNCTION TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
;
|
|
;
|
|
MD_VERIFY:
|
|
MD_FORMAT:
|
|
MD_DEFMED:
|
|
CALL PANIC ; INVALID SUB-FUNCTION
|
|
;
|
|
;
|
|
;
|
|
MD_STATUS:
|
|
XOR A ; ALWAYS OK
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
MD_RESET:
|
|
XOR A ; ALWAYS OK
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
MD_CAP:
|
|
LD A,(IY+MD_DEV) ; GET DEVICE NUMBER
|
|
OR A ; SET FLAGS
|
|
JR Z,MD_CAP0 ; UNIT 0
|
|
DEC A ; TRY UNIT 1
|
|
JR Z,MD_CAP1 ; UNIT 1
|
|
CALL PANIC ; PANIC ON INVALID UNIT
|
|
MD_CAP0:
|
|
LD A,(HCB + HCB_ROMBANKS) ; POINT TO ROM BANK COUNT
|
|
JR MD_CAP2
|
|
MD_CAP1:
|
|
LD A,(HCB + HCB_RAMBANKS) ; POINT TO RAM BANK COUNT
|
|
MD_CAP2:
|
|
SUB 4 ; SUBTRACT OUT RESERVED BANKS
|
|
LD H,A ; H := # BANKS
|
|
LD E,64 ; # 512 BYTE BLOCKS / BANK
|
|
CALL MULT8 ; HL := TOTAL # 512 BYTE BLOCKS
|
|
LD DE,0 ; NEVER EXCEEDS 64K, ZERO HIGH WORD
|
|
XOR A
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
MD_GEOM:
|
|
; RAM/ROM DISKS ALLOW CHS STYLE ACCESS BY EMULATING
|
|
; A DISK DEVICE WITH 1 HEAD AND 16 SECTORS / TRACK.
|
|
CALL MD_CAP ; HL := CAPACITY IN BLOCKS
|
|
LD D,1 | $80 ; HEADS / CYL := 1 BY DEFINITION, SET LBA CAPABILITY BIT
|
|
LD E,16 ; SECTORS / TRACK := 16 BY DEFINTION
|
|
LD B,4 ; PREPARE TO DIVIDE BY 16
|
|
MD_GEOM1:
|
|
SRL H ; SHIFT H
|
|
RR L ; SHIFT L
|
|
DJNZ MD_GEOM1 ; DO 4 BITS TO DIVIDE BY 16
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
;
|
|
;
|
|
MD_DEVICE:
|
|
LD D,DIODEV_MD ; D := DEVICE TYPE
|
|
LD A,(IY+MD_DEV) ; GET DEVICE NUMBER
|
|
LD E,A ; PUT IN E FOR RETURN
|
|
OR A ; SET FLAGS
|
|
LD C,%00100000 ; ASSUME ROM DISK ATTRIBUTES
|
|
JR Z,MD_DEVICE1 ; IF ZERO, IT IS ROM DISK, DONE
|
|
LD C,%00101000 ; USE RAM DISK ATTRIBUTES
|
|
MD_DEVICE1:
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
MD_MEDIA:
|
|
LD A,(IY+MD_DEV) ; GET DEVICE NUM
|
|
ADD A,MID_MDROM ; OFFSET BY MD ROM
|
|
LD E,A ; RESULTANT MEDIA ID TO E
|
|
LD D,0 ; D:0=0 MEANS NO MEDIA CHANGE
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
MD_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 (IY+MD_LBA+0),L ; SAVE NEW LBA
|
|
LD (IY+MD_LBA+1),H ; ...
|
|
LD (IY+MD_LBA+2),E ; ...
|
|
LD (IY+MD_LBA+3),D ; ...
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
|
|
;
|
|
;
|
|
;
|
|
MD_READ:
|
|
LD BC,MD_RDSEC ; GET ADR OF SECTOR READ FUNC
|
|
LD (MD_RWFNADR),BC ; SAVE IT AS PENDING IO FUNC
|
|
JR MD_RW ; CONTINUE TO GENERIC R/W ROUTINE
|
|
|
|
;
|
|
;
|
|
;
|
|
MD_WRITE:
|
|
LD BC,MD_WRSEC ; GET ADR OF SECTOR WRITE FUNC
|
|
LD (MD_RWFNADR),BC ; SAVE IT AS PENDING IO FUNC
|
|
LD A,(IY+MD_DEV) ; GET DEVICE NUMBER
|
|
OR A ; SET FLAGS TO TEST FOR ROM (UNIT 0)
|
|
JR NZ,MD_RW ; NOT ROM, SO OK TO WRITE, CONTINUE
|
|
LD E,0 ; UNIT IS READ ONLY, ZERO SECTORS WRITTEN
|
|
OR $FF ; SIGNAL ERROR
|
|
RET ; AND DONE
|
|
;
|
|
;
|
|
;
|
|
MD_RW:
|
|
LD (MD_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
|
LD A,E ; BLOCK COUNT TO A
|
|
OR A ; SET FLAGS
|
|
RET Z ; ZERO SECTOR I/O, RETURN W/ E=0 & A=0
|
|
LD B,A ; INIT SECTOR DOWNCOUNTER
|
|
LD C,0 ; INIT SECTOR READ/WRITE COUNT
|
|
MD_RW1:
|
|
PUSH BC ; SAVE COUNTERS
|
|
LD HL,(MD_RWFNADR) ; GET PENDING IO FUNCTION ADDRESS
|
|
CALL JPHL ; ... AND CALL IT
|
|
JR NZ,MD_RW2 ; IF ERROR, SKIP INCREMENT
|
|
; INCREMENT LBA
|
|
LD A,MD_LBA ; LBA OFFSET IN CFG ENTRY
|
|
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
|
CALL INC32HL ; INCREMENT THE VALUE
|
|
; INCREMENT DMA
|
|
LD HL,MD_DSKBUF+1 ; POINT TO MSB OF BUFFER ADR
|
|
INC (HL) ; BUMP DMA BY
|
|
INC (HL) ; ... 512 BYTES
|
|
XOR A ; SIGNAL SUCCESS
|
|
MD_RW2:
|
|
POP BC ; RECOVER COUNTERS
|
|
JR NZ,MD_RW3 ; IF ERROR, BAIL OUT
|
|
INC C ; BUMP COUNT OF SECTORS READ
|
|
DJNZ MD_RW1 ; LOOP AS NEEDED
|
|
MD_RW3:
|
|
LD E,C ; SECTOR READ COUNT TO E
|
|
LD HL,(MD_DSKBUF) ; CURRENT DMA TO HL
|
|
OR A ; SET FLAGS BASED ON RETURN CODE
|
|
RET ; AND RETURN, A HAS RETURN CODE
|
|
;
|
|
;
|
|
;
|
|
MD_RDSEC:
|
|
CALL MD_IOSETUP ; SETUP FOR MEMORY COPY
|
|
#IF (MDTRACE >= 2)
|
|
LD (MD_SRC),HL
|
|
LD (MD_DST),DE
|
|
LD (MD_LEN),BC
|
|
#ENDIF
|
|
PUSH BC
|
|
LD C,A ; SOURCE BANK
|
|
LD B,BID_BIOS ; DESTINATION BANK IS RAM BANK 1 (HBIOS)
|
|
#IF (MDTRACE >= 2)
|
|
LD (MD_SRCBNK),BC
|
|
CALL MD_PRT
|
|
#ENDIF
|
|
LD A,C ; GET SOURCE BANK
|
|
LD (HB_SRCBNK),A ; SET IT
|
|
LD A,B ; GET DESTINATION BANK
|
|
LD (HB_DSTBNK),A ; SET IT
|
|
POP BC
|
|
#IF (INTMODE == 1)
|
|
DI
|
|
#ENDIF
|
|
CALL HB_BNKCPY ; DO THE INTERBANK COPY
|
|
#IF (INTMODE == 1)
|
|
EI
|
|
#ENDIF
|
|
XOR A
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
MD_WRSEC:
|
|
CALL MD_IOSETUP ; SETUP FOR MEMORY COPY
|
|
EX DE,HL ; SWAP SRC/DEST FOR WRITE
|
|
#IF (MDTRACE >= 2)
|
|
LD (MD_SRC),HL
|
|
LD (MD_DST),DE
|
|
LD (MD_LEN),BC
|
|
#ENDIF
|
|
PUSH BC
|
|
LD C,BID_BIOS ; SOURCE BANK IS RAM BANK 1 (HBIOS)
|
|
LD B,A ; DESTINATION BANK
|
|
#IF (MDTRACE >= 2)
|
|
LD (MD_SRCBNK),BC
|
|
CALL MD_PRT
|
|
#ENDIF
|
|
LD A,C ; GET SOURCE BANK
|
|
LD (HB_SRCBNK),A ; SET IT
|
|
LD A,B ; GET DESTINATION BANK
|
|
LD (HB_DSTBNK),A ; SET IT
|
|
POP BC
|
|
#IF (INTMODE == 1)
|
|
DI
|
|
#ENDIF
|
|
CALL HB_BNKCPY ; DO THE INTERBANK COPY
|
|
#IF (INTMODE == 1)
|
|
EI
|
|
#ENDIF
|
|
XOR A
|
|
RET
|
|
;
|
|
; SETUP FOR MEMORY COPY
|
|
; A=BANK SELECT
|
|
; BC=COPY SIZE
|
|
; DE=DESTINATION
|
|
; HL=SOURCE
|
|
;
|
|
; ASSUMES A "READ" OPERATION. HL AND DE CAN BE SWAPPED
|
|
; AFTERWARDS TO ACHIEVE A WRITE OPERATION
|
|
;
|
|
; ON INPUT, WE HAVE LBA ADDRESSING IN HSTLBAHI:HSTLBALO
|
|
; BUT WE NEVER HAVE MORE THAN $FFFF BLOCKS IN A RAM/ROM DISK,
|
|
; SO THE HIGH WORD (HSTLBAHI) IS IGNORED
|
|
;
|
|
; EACH RAM/ROM BANK IS 32K BY DEFINITION AND EACH SECTOR IS 512
|
|
; BYTES BY DEFINITION. SO, EACH RAM/ROM BANK CONTAINS 64 SECTORS
|
|
; (32,768 / 512 = 64). THEREFORE, YOU CAN THINK OF LBA AS
|
|
; 00000BBB:BBOOOOOO IS WHERE THE 'B' BITS REPRESENT THE BANK NUMBER
|
|
; AND THE 'O' BITS REPRESENT THE SECTOR NUMBER WITHIN THE BANK.
|
|
;
|
|
; TO EXTRACT THE BANK NUMBER, WE CAN LEFT SHIFT TWICE TO GIVE US:
|
|
; 000BBBBB:OOOOOOOO. FROM THIS WE CAN EXTRACT THE MSB
|
|
; TO USE AS THE BANK NUMBER. NOTE THAT THE "RAW" BANK NUMBER MUST THEN
|
|
; BE OFFSET TO THE START OF THE ROM/RAM BANKS.
|
|
; ALSO NOTE THAT THE HIGH BIT OF THE BANK NUMBER REPRESENTS "RAM" SO THIS
|
|
; BIT MUST ALSO BE SET ACCORDING TO THE UNIT BEING ADDRESSED.
|
|
;
|
|
; TO GET THE BYTE OFFSET, WE THEN RIGHT SHIFT THE LSB BY 1 TO GIVE US:
|
|
; 0OOOOOOO AND EXTRACT THE LSB TO REPRESENT THE MSB OF
|
|
; THE BYTE OFFSET. THE LSB OF THE BYTE OFFSET IS ALWAYS 0 SINCE WE ARE
|
|
; DEALING WITH 512 BYTE BOUNDARIES.
|
|
;
|
|
MD_IOSETUP:
|
|
LD L,(IY+MD_LBA+0) ; HL := LOW WORD OF LBA
|
|
LD H,(IY+MD_LBA+1) ; ...
|
|
; ALIGN BITS TO EXTRACT BANK NUMBER FROM H
|
|
SLA L ; LEFT SHIFT ONE BIT
|
|
RL H ; FULL WORD
|
|
SLA L ; LEFT SHIFT ONE BIT
|
|
RL H ; FULL WORD
|
|
LD C,H ; BANK NUMBER FROM H TO C
|
|
; GET BANK NUM TO A AND SET FLAG Z=ROM, NZ=RAM
|
|
LD A,(IY+MD_DEV) ; DEVICE TO A
|
|
AND $01 ; ISOLATE LOW BIT, SET ZF
|
|
LD A,C ; BANK VALUE INTO A
|
|
PUSH AF ; SAVE IT FOR NOW
|
|
; ADJUST L TO HAVE MSB OF OFFSET
|
|
SRL L ; ADJUST L TO BE MSB OF BYTE OFFSET
|
|
LD H,L ; MOVE MSB TO H WHERE IT BELONGS
|
|
LD L,0 ; AND ZERO L SO HL IS NOW BYTE OFFSET
|
|
; LOAD DESTINATION AND COUNT
|
|
LD DE,(MD_DSKBUF) ; DMA ADDRESS IS DESTINATION
|
|
LD BC,512 ; ALWAYS COPY ONE SECTOR
|
|
; FINISH UP
|
|
POP AF ; GET BANK AND FLAGS BACK
|
|
JR Z,MD_IOSETUP2 ; DO ROM DRIVE, ELSE FALL THRU FOR RAM DRIVE
|
|
;
|
|
MD_IOSETUP1: ; RAM
|
|
ADD A,BID_RAMD0
|
|
RET
|
|
;
|
|
MD_IOSETUP2: ; ROM
|
|
ADD A,BID_ROMD0
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
MD_PRT:
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
|
|
CALL NEWLINE
|
|
|
|
LD DE,MDSTR_PREFIX
|
|
CALL WRITESTR
|
|
|
|
CALL PC_SPACE
|
|
LD DE,MDSTR_SRC
|
|
CALL WRITESTR
|
|
LD A,(MD_SRCBNK)
|
|
CALL PRTHEXBYTE
|
|
CALL PC_COLON
|
|
LD BC,(MD_SRC)
|
|
CALL PRTHEXWORD
|
|
|
|
CALL PC_SPACE
|
|
LD DE,MDSTR_DST
|
|
CALL WRITESTR
|
|
LD A,(MD_DSTBNK)
|
|
CALL PRTHEXBYTE
|
|
CALL PC_COLON
|
|
LD BC,(MD_DST)
|
|
CALL PRTHEXWORD
|
|
|
|
CALL PC_SPACE
|
|
LD DE,MDSTR_LEN
|
|
CALL WRITESTR
|
|
LD BC,(MD_LEN)
|
|
CALL PRTHEXWORD
|
|
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
POP AF
|
|
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
MD_RWFNADR .DW 0
|
|
;
|
|
MD_DSKBUF .DW 0
|
|
;
|
|
MD_SRCBNK .DB 0
|
|
MD_DSTBNK .DB 0
|
|
MD_SRC .DW 0
|
|
MD_DST .DW 0
|
|
MD_LEN .DW 0
|
|
;
|
|
MDSTR_PREFIX .TEXT "MD:$"
|
|
MDSTR_SRC .TEXT "SRC=$"
|
|
MDSTR_DST .TEXT "DEST=$"
|
|
MDSTR_LEN .TEXT "LEN=$"
|