Files
Pegasys-RomWBW/Source/HBIOS/rf.asm
Wayne Warthen f8c800e527 Create DSKY Driver Framework
Added a new driver category for DSKY (Display/Keypad) devices.  Existing DSKY devices were converted into drivers ICM and PKD.  These devices were previously DSKY and DSKYNG.

This removes substantial code duplication and recovers significant space in romldr and dbgmon.
2023-06-28 15:06:53 -07:00

351 lines
8.2 KiB
NASM

;
;==================================================================================================
; RAM FLOPPY DISK DRIVER
;==================================================================================================
;
;
;
RF_U0IO .EQU $A0 ; BASED ADDRESS OF RAMFLOPPY 1
RF_U1IO .EQU $A4 ; BASED ADDRESS OF RAMFLOPPY 2
RF_U2IO .EQU $A8 ; BASED ADDRESS OF RAMFLOPPY 3
RF_U3IO .EQU $AC ; BASED ADDRESS OF RAMFLOPPY 4
;
; IO PORT OFFSETS
;
RF_DAT .EQU 0 ; DATA IN/OUT ONLY TO SRAM - R/W
RF_AL .EQU 1 ; ADDRESS LOW FOR RAMF MEMORY - W/O
RF_AH .EQU 2 ; ADDRESS HIGH FOR RAMF MEMORY - W/O
RF_ST .EQU 3 ; STATUS PORT - R/O
;
; RF DEVICE CONFIGURATION
;
RF_DEVCNT .EQU RFCNT ; NUMBER OF RF DEVICES SUPPORTED
RF_CFGSIZ .EQU 8 ; SIZE OF CFG TBL ENTRIES
RF_MAXRF .EQU 4 ; MAXIMUM NUMBERS OF DEVICES SUPPORTED
;
RF_DEV .EQU 0 ; OFFSET OF DEVICE NUMBER (BYTE)
RF_STAT .EQU 1 ; OFFSET OF STATUS (BYTE)
RF_LBA .EQU 2 ; OFFSET OF LBA (DWORD)
RF_IOAD .EQU 7 ; OFFSET OF DEVICE IO ADDRESS
#IF ($RF_DEVCNT > RF_MAXRF)
.ECHO "*** ONLY 4 RAM FLOPPY DEVICES SUPPORTED ***\n"
RF_DEVCNT .SET RF_MAXRF
#ENDIF
;
; DEVICE CONFIG TABLE (RAM DEVICE FIRST TO MAKE IT ALWAYS FIRST DRIVE)
;
RF_CFGTBL:
; DEVICE 0
.DB 0 ; DRIVER DEVICE NUMBER
.DB 0 ; DEVICE STATUS
.DW 0,0 ; CURRENT LBA
.DB 0 ; UNUSED
.DB RF_U0IO ; DEVICE BASE ADDR
#IF (RF_DEVCNT > 1)
; DEVICE 1
.DB 1 ; DEVICE NUMBER
.DB 0 ; DEVICE STATUS
.DW 0,0 ; CURRENT LBA
.DB 0 ; UNUSED
.DB RF_U1IO ; DEVICE BASE ADDR
#ENDIF
#IF (RF_DEVCNT > 2)
; DEVICE 2
.DB 2 ; DRIVER DEVICE NUMBER
.DB 0 ; DEVICE STATUS
.DW 0,0 ; CURRENT LBA
.DB 0 ; UNUSED
.DB RF_U2IO ; DEVICE BASE ADDR
#ENDIF
; ; DEVICE 3
#IF (RF_DEVCNT > 3)
.DB 3 ; DEVICE NUMBER
.DB 0 ; DEVICE STATUS
.DW 0,0 ; CURRENT LBA
.DB 0 ; UNUSED
.DB RF_U3IO ; DEVICE BASE ADDR
#ENDIF
;
#IF ($ - RF_CFGTBL) != (RF_DEVCNT * RF_CFGSIZ)
.ECHO "*** INVALID RF CONFIG TABLE ***\n"
#ENDIF
;
.DB $FF ; END MARKER
;
;
;
RF_INIT:
CALL NEWLINE ; FORMATTING
PRTS("RF:$")
LD B,RF_DEVCNT ; LOOP CONTROL
LD IY,RF_CFGTBL ; START OF CFG TABLE
RF_INIT0:
CALL RF_UNIT
PUSH BC ; SAVE LOOP CONTROL
LD BC,RF_FNTBL ; BC := FUNC TABLE ADR
PUSH IY ; CFG ENTRY POINTER
POP DE ; COPY TO DE
CALL DIO_ADDENT ; ADD ENTRY, BC IS NOT DESTROYED
LD BC,RF_CFGSIZ ; SIZE OF CFG ENTRY
ADD IY,BC ; BUMP IY TO NEXT ENTRY
POP BC ; RESTORE BC
DJNZ RF_INIT0 ; LOOP AS NEEDED
PRTS(" DEVICES=$") ; DISPLAY NUMBER
LD A,RF_DEVCNT ; OF DEVICES
CALL PRTDECB
;
XOR A ; INIT SUCCEEDED
RET ; RETURN
;
RF_UNIT:
PRTS(" IO=0x$") ; DISPLAY
LD A,(IY+RF_IOAD) ; PORT AND
CALL PRTHEXBYTE ; WRITE
PRTS(" WP=$") ; PROTECT
ADD A,RF_ST ; STATUS OF
LD C,A ; THIS DEVICE
IN A,(C)
AND 1
JR Z,RF_NO_WP1
PRTS("ON$")
RET
RF_NO_WP1:
PRTS("OFF$")
RET
;
;
;
RF_FNTBL:
.DW RF_STATUS
.DW RF_RESET
.DW RF_SEEK
.DW RF_READ
.DW RF_WRITE
.DW RF_VERIFY
.DW RF_FORMAT
.DW RF_DEVICE
.DW RF_MEDIA
.DW RF_DEFMED
.DW RF_CAP
.DW RF_GEOM
#IF (($ - RF_FNTBL) != (DIO_FNCNT * 2))
.ECHO "*** INVALID MD FUNCTION TABLE ***\n"
#ENDIF
;
RF_VERIFY:
RF_FORMAT:
RF_DEFMED:
SYSCHKERR(ERR_NOTIMPL) ; INVALID SUB-FUNCTION
RET
;
;
;
RF_STATUS:
XOR A ; STATUS ALWAYS OK
RET
;
;
;
RF_RESET:
XOR A ; ALWAYS OK
RET
;
;
;
RF_CAP:
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,(IY+RF_DEV) ; E := PHYSICAL DEVICE NUMBER
LD C,%00010110 ; C := ATTRIBUTES, NON-REMOVABLE RAM FLOPPY
LD H,0 ; H := 0, DRIVER HAS NO MODES
LD L,(IY+RF_IOAD) ; L := BASE I/O ADDRESS
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 (IY+RF_LBA+0),L ; SAVE NEW LBA
LD (IY+RF_LBA+1),H ; ...
LD (IY+RF_LBA+2),E ; ...
LD (IY+RF_LBA+3),D ; ...
XOR A ; SIGNAL SUCCESS
RET ; AND RETURN
;
;
;
RF_READ:
CALL HB_DSKREAD ; HOOK HBIOS DISK READ SUPERVISOR
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:
CALL HB_DSKWRITE ; HOOK HBIOS DISK WRITE SUPERVISOR
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
LD A,ERR_READONLY ; SIGNAL ERROR
OR A ; SET FLAGS
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
; INCREMENT LBA
LD A,MD_LBA ; OFFSET OF LBA VALUE
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
CALL INC32HL ; INCREMENT THE VALUE
; INCREMENT DMA
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 Z ; RETURN SUCCESS
LD A,ERR_IO ; SIGNAL IO ERROR
OR A ; SET FLAGS
RET ; AND DONE
;
; READ SECTOR
;
RF_RDSEC:
CALL RF_SETADR ; SEND SECTOR STARTING ADDRESS TO CARD
LD HL,(RF_DSKBUF) ; HL := DISK BUFFER ADDRESS
LD A,(RF_IO) ; GET IO PORT BASE
#IF (DMAENABLE & (DMAMODE=DMAMODE_ECB))
LD BC,512-1 ; READ 512 BYTES
CALL DMAINIR ; USING DMA
#ELSE
OR RF_DAT ; OFFSET TO DAT PORT
LD C,A ; PUT IN C FOR PORT IO
LD B,0 ; INIT BYTE COUNTER
INIR ; READ 256 BYTES
INIR ; AND ANOTHER 256 BYTES FOR 512 TOTAL
XOR A ; SIGNAL SUCCESS
#ENDIF
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 A,(RF_IO) ; GET IO PORT BASE
OR RF_DAT ; OFFSET TO DAT PORT
#IF (DMAENABLE & (DMAMODE=DMAMODE_ECB))
LD BC,512-1 ; WRITE 512 BYTES
CALL DMAOTIR ; USING DMA
#ELSE
LD C,A ; PUT IN C FOR PORT IO
LD B,0 ; INIT BYTE COUNTER
OTIR ; WRITE 256 BYTES
OTIR ; AND ANOTHER 256 BYTES FOR 512 TOTAL
XOR A ; SIGNAL SUCCESS
#ENDIF
RET ; AND DONE
;
;
;
RF_SETIO:
LD A,(IY+RF_IOAD) ; GET THE IO PORT
LD (RF_IO),A ; OF THE DEVICE WE
RET ; ARE WORKING ON
;
;
;
RF_SETADR:
;
#IF (DSKYENABLE)
#IF (DSKYDSKACT)
LD A,RF_LBA
CALL LDHLIYA
CALL HB_DSKACT ; SHOW ACTIVITY
#ENDIF
#ENDIF
;
LD A,(RF_IO) ; OUTPUT THE LOGICAL BLOCK
OR RF_AL ; ADDRESS TO THE
LD C,A ; TO THE MSB AND
LD A,(IY+RF_LBA+0) ; LSB SECTRK
OUT (C),A ; REGISTERS.
LD A,(IY+RF_LBA+1) ; BYTE COUNTER
INC C ; IS RESET
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 ; PORT ADDRESS OF ACTIVE DEVICE
RF_RWFNADR .DW 0
;
RF_DSKBUF .DW 0