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.
 
 
 
 
 
 

284 lines
6.4 KiB

;
;==================================================================================================
; RAM FLOPPY DISK DRIVER
;==================================================================================================
;
;
;
RF_U0IO .EQU $A0
RF_U1IO .EQU $A4
;
; IO PORT OFFSETS
;
RF_DAT .EQU 0
RF_AL .EQU 1
RF_AH .EQU 2
RF_ST .EQU 3
;
;
;
RF_INIT:
CALL NEWLINE ; FORMATTING
PRTS("RF: UNITS=$")
LD A,RFCNT
CALL PRTDECB
;
; SETUP THE DISPATCH TABLE ENTRIES
;
;
; SETUP THE DISPATCH TABLE ENTRIES
;
LD B,RFCNT ; LOOP CONTROL
LD C,0 ; PHYSICAL UNIT INDEX
RF_INIT0:
PUSH BC ; SAVE LOOP CONTROL
LD B,C ; PHYSICAL UNIT
LD C,DIODEV_RF ; 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 RF_INIT0 ; LOOP UNTIL DONE
;
XOR A ; INIT SUCCEEDED
RET ; RETURN
;
;
;
RF_DISPATCH:
; VERIFY AND 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 (RF_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,RF_STATUS ; SUB-FUNC 0: STATUS
DEC A
JP Z,RF_RESET ; SUB-FUNC 1: RESET
DEC A
JP Z,RF_SEEK ; SUB-FUNC 2: SEEK
DEC A
JP Z,RF_READ ; SUB-FUNC 3: READ SECTORS
DEC A
JP Z,RF_WRITE ; SUB-FUNC 4: WRITE SECTORS
DEC A
JP Z,RF_VERIFY ; SUB-FUNC 5: VERIFY SECTORS
DEC A
JP Z,RF_FORMAT ; SUB-FUNC 6: FORMAT TRACK
DEC A
JP Z,RF_DEVICE ; SUB-FUNC 7: DEVICE REPORT
DEC A
JP Z,RF_MEDIA ; SUB-FUNC 8: MEDIA REPORT
DEC A
JP Z,RF_DEFMED ; SUB-FUNC 9: DEFINE MEDIA
DEC A
JP Z,RF_CAP ; SUB-FUNC 10: REPORT CAPACITY
DEC A
JP Z,RF_GEOM ; SUB-FUNC 11: REPORT GEOMETRY
;
RF_VERIFY:
RF_FORMAT:
RF_DEFMED:
CALL PANIC ; INVALID SUB-FUNCTION
;
;
;
RF_STATUS:
XOR A ; STATUS ALWAYS OK
RET
;
;
;
RF_RESET:
XOR A ; ALWAYS OK
RET
;
;
;
RF_CAP:
LD A,C ; DEVICE/UNIT IS IN C
AND $0F ; ISOLATE UNIT NUM
CP RFCNT ; CHECK FOR MAX UNIT EXCEEDED
CALL NC,PANIC ; PANIC IF TOO HIGH
;
LD DE,0
LD HL,$2000 ; 8192 BLOCKS OF 512 BYTES
XOR A
RET
;
;
;
RF_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 RF_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,16 | $80 ; HEADS / CYL = 16, SET LBA CAPABILITY BIT
LD E,16 ; SECTORS / TRACK = 16
RET ; DONE, A STILL HAS RF_CAP STATUS
;
;
;
RF_DEVICE:
LD D,DIODEV_RF ; D := DEVICE TYPE
LD E,C ; E := PHYSICAL UNIT
LD C,%00110000 ; C := ATTRIBUTES, NON-REMOVALBE RAM FLOPPY
XOR A ; SIGNAL SUCCESS
RET
;
;
;
RF_MEDIA:
LD E,MID_RF ; RAM FLOPPY MEDIA
LD D,0 ; D:0=0 MEANS NO MEDIA CHANGE
XOR A ; SIGNAL SUCCESS
RET
;
;
;
RF_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
;
;
;
RF_READ:
LD BC,RF_RDSEC ; GET ADR OF SECTOR READ FUNC
LD (RF_RWFNADR),BC ; SAVE IT AS PENDING IO FUNC
JR RF_RW ; CONTINUE TO GENERIC R/W ROUTINE
;
;
;
RF_WRITE:
LD BC,RF_WRSEC ; GET ADR OF SECTOR WRITE FUNC
LD (RF_RWFNADR),BC ; SAVE IT AS PENDING IO FUNC
CALL RF_CHKWP ; WRITE PROTECTED?
JR Z,RF_RW ; IF 0, NOT WP, CONTINUE WITH GENERIC R/W ROUTINE
LD E,0 ; ZERO SECTORS WRITTEN
OR $FF ; SIGNAL ERROR
RET ; AND DONE
;
;
;
RF_RW:
LD (RF_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
CALL RF_SETIO ; SET BASE PORT IO ADR FOR SELECTED UNIT
RF_RW1:
PUSH BC ; SAVE COUNTERS
LD HL,(RF_RWFNADR) ; GET PENDING IO FUNCTION ADDRESS
CALL JPHL ; ... AND CALL IT
JR NZ,RF_RW2 ; IF ERROR, SKIP INCREMENT
LD HL,HSTLBA ; POINT TO 32-BIT CURRENT LBA
PUSH HL ; SAVE POINTER
CALL LD32 ; LOAD 32-BIT LBA INTO DE:HL
CALL INC32 ; INCREMENT LBA FOR NEXT I/O
POP BC ; RECOVER LBA POINTER INTO BC
CALL ST32 ; AND SAVE IT
LD HL,RF_DSKBUF+1 ; POINT TO MSB OF BUFFER ADR
INC (HL) ; BUMP DMA BY
INC (HL) ; ... 512 BYTES
XOR A ; SIGNAL SUCCESS
RF_RW2:
POP BC ; RECOVER COUNTERS
JR NZ,RF_RW3 ; IF ERROR, BAIL OUT
INC C ; BUMP COUNT OF SECTORS READ
DJNZ RF_RW1 ; LOOP AS NEEDED
RF_RW3:
LD E,C ; SECTOR READ COUNT TO E
LD HL,(RF_DSKBUF) ; CURRENT DMA TO HL
OR A ; SET FLAGS BASED ON RETURN CODE
RET ; AND RETURN, A HAS RETURN CODE
;
; READ SECTOR
;
RF_RDSEC:
CALL RF_SETADR ; SEND SECTOR STARTING ADDRESS TO CARD
LD HL,(RF_DSKBUF) ; HL := DISK BUFFER ADDRESS
LD B,0 ; INIT BYTE COUNTER
LD A,(RF_IO) ; GET IO PORT BASE
OR RF_DAT ; OFFSET TO DAT PORT
LD C,A ; PUT IN C FOR PORT IO
INIR ; READ 256 BYTES
INIR ; AND ANOTHER 256 BYTES FOR 512 TOTAL
XOR A ; SIGNAL SUCCESS
RET ; AND DONE
;
; WRITE SECTOR
;
RF_WRSEC:
CALL RF_SETADR ; SEND SECTOR STARTING ADDRESS TO CARD
LD HL,(RF_DSKBUF) ; HL := DISK BUFFER ADDRESS
LD B,0 ; INIT BYTE COUNTER
LD A,(RF_IO) ; GET IO PORT BASE
OR RF_DAT ; OFFSET TO DAT PORT
LD C,A ; PUT IN C FOR PORT IO
OTIR ; WRITE 256 BYTES
OTIR ; AND ANOTHER 256 BYTES FOR 512 TOTAL
XOR A ; SIGNAL SUCCESS
RET ; AND DONE
;
;
;
RF_SETIO:
LD A,(RF_UNIT) ; GET DEVICE/UNIT
AND $0F ; ISOLATE UNIT NUM
JR NZ,RF_SETIO1
LD A,RF_U0IO
JR RF_SETIO3
RF_SETIO1:
DEC A
JR NZ,RF_SETIO2
LD A,RF_U1IO
JR RF_SETIO3
RF_SETIO2:
CALL PANIC ; INVALID UNIT
RF_SETIO3:
LD (RF_IO),A
RET
;
;
;
RF_SETADR:
LD A,(RF_IO)
OR RF_AL
LD C,A
LD A,(HSTLBALO)
OUT (C),A
LD A,(HSTLBALO+1)
INC C
OUT (C),A
RET
;
;
;
RF_CHKWP:
CALL RF_SETIO ; SET BASE PORT IO ADR FOR SELECTED UNIT
LD A,(RF_IO) ; GET IO PORT BASE
OR RF_ST ; OFFSET TO ST PORT
LD C,A ; PUT PORT ADR IN C FOR IO
IN A,(C) ; READ ST PORT
BIT 0,A ; CHECK WRITE PROTECT (BIT 0)
RET ; RET WP STATUS IN ZF, NZ=WP
;
;
;
RF_IO .DB 0
RF_RWFNADR .DW 0
;
RF_UNIT .DB 0
RF_DSKBUF .DW 0