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

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