mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 14:11:48 -06:00
- The DSKY(ng) can display disk I/O activity as the system runs. This capability was implemented very erratically. This update overhauls the mechanism, makes it consistent, and implements it across all disk drivers.
351 lines
8.2 KiB
NASM
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:
|
|
CALL SYSCHK ; INVALID SUB-FUNCTION
|
|
LD A,ERR_NOTIMPL
|
|
OR A
|
|
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,%00110000 ; 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)
|
|
LD A,RF_LBA
|
|
CALL LDHLIYA
|
|
CALL HB_DSKACT ; SHOW ACTIVITY
|
|
#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
|