 PAGE *** PACE LOGICAL FLOPPY DRIVER ***
 IF IODRIVERBODY
PSILFNBPS EQU 128 ; 128 BYTES PER SECTOR (TRANSFER)
PSILFNSPT EQU 26 NUMBER OF SECTORS PER TRACK
PSILFNTPC EQU 1 NUMBER OF TRACKS PER CYLINDER
PSILFNCYL EQU 77 NUMBER OF CYLINDERS

* PACE LOGICAL FLOPPY DISK CONTROLLER DCB DEFINITIONS
*
:: SET *
 ORG DSKINFO:SIZE TACKS ON TO BOTTOM OF DISK INFO TABLE
PSILFMAPALGORITHM RMB 2 MAP ALGORITHM CURRENTLY IN USE
PSILFDRIVE RMB 1 DRIVE NUMBER
PSILFSIZE EQU *
 PAGE
 ORG ::
PSILFDRIVER FDB PSILFRESET ; PACE LOGICAL FLOPPY INIT CODE
 FDB PSILFREAD ; PACE LOGICAL FLOPPY READ
 FDB PSILFWRITE ; PACE LOGICAL FLOPPY WRITE
 FDB PSILFWAITDONE ; PACE LOGICAL FLOPPY WAIT FOR DONE
 FDB PSILFSTATUS ; PACE LOGICAL FLOPPY STATUS READ
 FDB PSILFCONTROL ; PACE LOGICAL FLOPPY CONTROL OPERATION

PSILFINIT CLR PSILFIIOSTS ;ISSUE RESET TO LOGICAL FLOPPY
 LDAA PSILFIDISKIN RESET "I'VE GOT DATA FOR YOU" BIT
 LDAA #PSILFICTLRESET TAKE AWAY THE RESET PULSE
 STAA PSILFIIOSTS
 LDX #0
PSILFINITL LDAA PSILFIIOSTS WAIT FOR RESPONSE
 BMI PSILFINITL1
 DEX
 BNE PSILFINITL
 JSR SDOS+SDOS:ERROR
 FDB ERR:DEVICETIMEDOUT
PSILFINITL1 LDAA PSILFIDISKIN ACK DISK READY
* MUST SET ALGORITHM HERE
PSILFINITRTS OKRTS

PSILFFORMAT LDX #PSILFINTERFACE GRAB INTERFACE
 JSR ALLOCATERESOURCE
 LDX #PSILFIFORMAT
PSILFDOIO BSR PSILFSTARTIO TRIGGER THE I/O
PSILFWAITDONE LDX DCBPOINTER WAIT FOR I/O DONE
 LDAA DCB:DONEFLAG,X ALREADY DONE?
 BNE PSILFWAITDONE1 B/ YES
 JSR SDOS+SDOS:WAITEVENT
PSILFWAITDONE1 LDX DCBPOINTER
 LDX DCB:LASTERROR,X CHECK ERROR RESULT
 BEQ PSILFINITRTS B/ NO ERROR
 JMP ERRETX SIGNAL USER

PSILFSTARTIO STX TEMPX SAVE I/O STARTING LOCATION
 LDX SDOS+SDOS:IOBLOCKPTR
 STX PSILFSYSCALLBLKPTR TELL DRIVER WHERE SYSCALL BLOCK IS
 LDX DCBPOINTER
 STX PSILFDCBPOINTER MAKE LOCATION OF DCB FOR DRIVER POSSIBLE
 CLR DCB:DONEFLAG,X MARK DCB AS BUSY
 CLR DCB:LASTERROR,X CLEAR THE ERROR CODE
 CLR DCB:LASTERROR+1,X
 LDX TEMPX
 JMP SDOS+SDOS:STARTIO AND TRIGGER THE I/O
 PAGE
PSILFLOADNX LDX #PSILFINTERFACE GRAB INTERFACE
 JSR ALLOCATERESOURCE
 LDX #PSILFILOADNX
 BRA PSILFDOIO

PSILFCONTROL CMPA #CC:DISMOUNTDISK
 BEQ PSILFDISMT
 CMPA #CC:LOADNX
 BEQ PSILFLOADNX
 CMPA #CC:FORMAT
 BEQ PSILFFORMAT ; FORMAT OPERATION
PSILFILLOP JMP ILLDEVICEOP

PSILFDISMT LDX #PSILFINTERFACE
 JSR ALLOCATERESOURCE
 LDX #PSILFIDISMOUNT
 BSR PSILFDOIO START THE DISMOUNT OPERATION
 LDX DCBPOINTER NOW CLEAR THE ERROR SUMMARY DATA
 LDAA #(DSKINFO:OPSCOUNT+2-DSKINFO:SEEKERRCNT+1)
PSILFZLP CLR DSKINFO:SEEKERRCNT,X ; ZERO LOCATION
 INX
 DECA
 BNE PSILFZLP
 LDAA #$FF
 STAA DSKINFO:SEEKERRCNT,X * SET ERRLSN TO -1
 INX
 STAA DSKINFO:SEEKERRCNT,X
 INX
 STAA DSKINFO:SEEKERRCNT,X
 JMP PSILFWAITDONE

 PAGE
PSILFSTATUS CMPA #SC:ERRORSTATUS
 BEQ PSILFERSTAT
 JMP ILLDEVICEOP ; NO SUCH STATUS AVAILABLE

PSILFERSTAT LDX DCBPOINTER
 STX PSILFSTATX
 JSR SDOS+SDOS:CHECKRDLEN
 FDB DSKINFO:ERRLSN+2-DSKINFO:SEEKERRCNT+1
 LDX SCBLK:RDBUF,X
 STX PSILFRDBUFX
 LDAB #(DSKINFO:ERRLSN+2-DSKINFO:SEEKERRCNT+1)
PSILFSTATUSLP LDX PSILFSTATX
 LDAA DSKINFO:SEEKERRCNT,X
 INX
 STX PSILFSTATX
 LDX PSILFRDBUFX
 STAA 0,X
 INX
 STX PSILFRDBUFX
 DECB
 BNE PSILFSTATUSLP
 OKRTS

PSILFSTATX FDB 0
PSILFRDBUFX FDB 0
 PAGE
PSILFWRITE LDAA #PACEWRITEV
 BRA PSILFOPSET
PSILFREAD LDAA #PACEREAD
PSILFOPSET PSHA  SAVE THE COMMAND
 LDX DCBPOINTER
 LDX DSKINFO:SECTORDB,X
 LDAA RDSI:LSN+1,X
 LDAB RDSI:LSN+2,X
 LDX DCBPOINTER
 SUBB DSKINFO:NLSN+2,X
 SBCA DSKINFO:NLSN+1,X
 BCS PSILFSETUP1
 INS  THROW AWAY THE COMMAND
 JSR SDOS+SDOS:ERROR
 FDB ERR:ILLLSN
PSILFSETUP1 LDX #PSILFINTERFACE ; WAIT FOR INTERFACE FREE
 JSR ALLOCATERESOURCE
 LDX DCBPOINTER
 PULA  GET THE COMMAND TYPE BACK
 STAA PSILFREADWRITE ; SET THE OPERATION
 LDAA DSKINFO:MAPALGORITHM,X NEW MAP ALGORITHM...
 LDAB DSKINFO:MAPALGORITHM+1,X
 CMPB PSILFMAPALGORITHM+1,X = SAME AS OLD?
 BNE PSILFSETUP2 B/ NO, SET THE MAP ALGORITHM
 CMPA PSILFMAPALGORITHM,X
 BEQ PSILFSETUP3 B/ YEP
PSILFSETUP2 LDX #PSILFISETMAP
 JSR PSILFDOIO  CAUSE THE MAP TO GET SET
 LDX #PSILFINTERFACE ALLOCATE THE INTERFACE AGAIN
 JSR ALLOCATERESOURCE
PSILFSETUP3 EQU *
 LDX #PSILFCMDFEED
 JSR PSILFSTARTIO ; ENTER INTERRUPT SERVICE CODE
 OKRTS
 PAGE PACE LOGICAL FLOPPY DRIVER -- INTERRUPT CODE
PACENOP EQU 0 NO OPERATION
PACEREAD EQU 2 LOGICAL FLOPPY READ COMMAND
PACEWRITEV EQU 4 LOGICAL FLOPPY WRITE WITH VERIFY
PACELOADNX EQU 6 LOGICAL FLOPPY LOAD AND EXECUTE DIAGNOSTIC
PACESETMAP EQU 8 SET MAP ALGORITHM
PACEDISMOUNT EQU 10 DISMOUNT DRIVE
PACEGETERROR EQU $E GET ERROR SUMMARY
CC:LOADNX EQU $0A CONTROLER LOADS AND EXECUTES PROGRAM


PSILFIDISKOUT EQU $FAD8 DISK OUTPUT REGISTER
PSILFIDISKIN EQU $FAD9 DISK INPUT REGISTER
PSILFIDSKNOTRDY EQU %10000000 "NOT READY"
PSILFIWRITEPROT EQU %01000000 WRITE PROTECT
PSILFIWRITEFAULT EQU %00100000 WRITE FAULT
PSILFISERNF EQU %00010000 SEEK ERROR/ID NOT FOUND
PSILFICRCERR EQU %00001000 CRC ERROR
PSILFIVERFERR EQU %00000100 VERIFY ERROR
PSILFIINVLLSN EQU %00000010 INVALID LSN
PSILFICHIPFAIL EQU %00000001 FDC FAILURE

PSILFIIOSTS EQU $FADA REGISTER FULL STATUS
PSILFIDISKINRDY EQU %10000000 DISK INPUT DATA READY
PSILFIDISKOUTBUSY EQU %01000000 DISK OUTPUT DATA BUSY
PSILFICONTROL EQU $FADA FLOPPY CONTROL REGISTER
PSILFICTLENIRQ EQU %10000000 ENABLE "DISKIN FULL" IRQ
PSILFICTLRESET EQU %00010000 "DISABLE RESET"

PSILFIINTERRUPT EQU * GET HERE IF DISK INTERRUPT
 LDAA #PSILFICTLRESET KILL THE INTERRUPT REQUEST
 STAA PSILFICONTROL
 LDAA PSILFINTPC GRAB ADDRESS OF PLACE THAT WE LEFT OFF
 LDAB PSILFINTPC+1
 PSHB  SET UP SO WE CAN "RTS" THERE
 PSHA
 CLI  OK TO ALLOW INTERRUPTS AGAIN
 LDX #0 KILL THE TIMEOUT
 STX PSILFTIMEOUTCOUNT
 LDX PSILFDCBPOINTER PICK UP THE DCB POINTER
 LDAA PSILFIDISKIN GET THE DISK STATUS
 RTS  CONTINUE WHERE WE LEFT OFF
 PAGE
PSILFCMDFEED EQU * START HERE WHEN ISSUING READ/WRITE COMMANDS
 CLI  OK TO ALLOW INTERRUPTS HERE
 LDAA PSILFIDISKIN CLEAR 'DISKIN READY' IF LAST
*   OPERATION CAUSED 'RESET'
 LDX PSILFDCBPOINTER GET DCB POINTER
 INC DSKINFO:OPSCOUNT+2,X COUNT # I/O REQUESTS ISSUED
 BNE PSILFI1
 INC DSKINFO:OPSCOUNT+1,X
 BNE PSILFI1
 INC DSKINFO:OPSCOUNT,X
PSILFI1 LDAA PSILFREADWRITE ASSERT: READ OR WRITE COMMAND
 STAA PSILFIDISKOUT TELL FLOPPY WHAT TO DO...
 JSR PSILFIWAITFORINTERRUPT WAIT FOR COMMAND ECHO
 LDAA PSILFDRIVE,X OUTPUT UNIT # TO PACE FLOPPY
 JSR PSILFISENDBYTE
 LDX DSKINFO:SECTORDB,X GET LSN TO (A)
 LDAA RDSI:LSN+1,X
 JSR PSILFISENDBYTE SEND MSB OF LSN
 LDX PSILFDCBPOINTER
 LDX DSKINFO:SECTORDB,X SEND LSB OF LSN
 LDAA RDSI:LSN+2,X
 JSR PSILFISENDBYTE SEND TO PACE FLOPPY
 LDAA PSILFREADWRITE IS THIS A READ?
 CMPA #PACEWRITEV
 BEQ PSILFIWRITE B/ NO, GO STUFF BYTES
 JSR PSILFIWAITFORINTERRUPT YES, WAIT FOR RESULTS
 BITA #PSILFIDSKNOTRDY!PSILFISERNF!PSILFICRCERR!PSILFIINVLLSN!PSILFICHIPFAIL
 BEQ PSILFI2 B/ NO ERROR BITS!
 JMP PSILFIRERROR
PSILFI2 LDX DSKINFO:SECTORDB,X
 LDX RDSI:SECTORBASE,X
 STX PSILFIWRBUFEND SAVE CURRENT POINTER FOR LATER UPDATE
 PAGE
PSILFIREADLOOP EQU * READ LOOP, OPTIMIZED FOR SPEED!
 LDAA PSILFIIOSTS WAIT FOR DISK INPUT DATA
 BPL *-3 B/ NOT ARRIVED YET
 LDAA PSILFIDISKIN GET DATA FROM PACE
 STAA 0,X STUFF INTO BUFFER
 LDAA PSILFIIOSTS WAIT FOR DISK INPUT DATA
 BPL *-3 B/ NOT ARRIVED YET
 LDAA PSILFIDISKIN GET DATA FROM PACE
 STAA 1,X STUFF INTO BUFFER
 LDAA PSILFIIOSTS WAIT FOR DISK INPUT DATA
 BPL *-3 B/ NOT ARRIVED YET
 LDAA PSILFIDISKIN GET DATA FROM PACE
 STAA 2,X STUFF INTO BUFFER
 LDAA PSILFIIOSTS WAIT FOR DISK INPUT DATA
 BPL *-3 B/ NOT ARRIVED YET
 LDAA PSILFIDISKIN GET DATA FROM PACE
 STAA 3,X STUFF INTO BUFFER
 LDAA PSILFIIOSTS WAIT FOR DISK INPUT DATA
 BPL *-3 B/ NOT ARRIVED YET
 LDAA PSILFIDISKIN GET DATA FROM PACE
 STAA 4,X STUFF INTO BUFFER
 LDAA PSILFIIOSTS WAIT FOR DISK INPUT DATA
 BPL *-3 B/ NOT ARRIVED YET
 LDAA PSILFIDISKIN GET DATA FROM PACE
 STAA 5,X STUFF INTO BUFFER
 LDAA PSILFIIOSTS WAIT FOR DISK INPUT DATA
 BPL *-3 B/ NOT ARRIVED YET
 LDAA PSILFIDISKIN GET DATA FROM PACE
 STAA 6,X STUFF INTO BUFFER
 LDAA PSILFIIOSTS WAIT FOR DISK INPUT DATA
 BPL *-3 B/ NOT ARRIVED YET
 LDAA PSILFIDISKIN GET DATA FROM PACE
 STAA 7,X STUFF INTO BUFFER
 LDAB PSILFIWRBUFEND+1 BUMP ADDRESS BY 8
 ADDB #8
 STAB PSILFIWRBUFEND+1
 LDX PSILFIWRBUFEND
 BITB #%01111111 COPIED 128 BYTES YET ?
 BNE PSILFIREADLOOP B/ MORE BYTES TO GET
PSILFIDONE EQU *
 LDX PSILFDCBPOINTER
 INC DCB:DONEFLAG,X SIGNAL "DISK DONE"
 INC PSILFINTERFACE MARK INTERFACE AS "AVAILABLE RESOURCE"
 JMP SDOS+SDOS:RESCHEDULE
 PAGE
PSILFIWRITE EQU *
 LDX PSILFDCBPOINTER
 LDX DSKINFO:SECTORDB,X
 LDX RDSI:SECTORBASE,X
 LDAB #PSILFNBPS
PSILFIWRITELOOP EQU * WRITE LOOP, OK IF A LITTLE SLOW
 LDAA PSILFIIOSTS WAIT FOR DISK OUTPUT REGISTER=EMPTY
 ROLA
 BMI PSILFIWRITELOOP B/ NOT EMPTY YET
 LDAA 0,X STUFF DATA OUT TO PACE
 STAA PSILFIDISKOUT
 INX  ADVANCE BUFFER POINTER
 DECB
 BNE PSILFIWRITELOOP
 JSR PSILFIWAITFORINTERRUPT WAIT FOR WRITE STATUS
 BEQ PSILFIDONE B/ WRITE IS OK
PSILFIRERROR EQU *
 BITA #PSILFIDSKNOTRDY DISK NOT READY ?
 BNE PSILFIERRNOTRDY B/ YEP.
 BITA #PSILFIWRITEPROT DISK WRITE PROTECTED ?
 BNE PSILFIERRWRTPROT B/ YEP.
* MUST BE WORSE THAN THESE, SAVE IT.
 LDAB PSILFREADWRITE CHECK COMMAND
 CMPB #PACEWRITEV WRITE?
 BEQ PSILFIWERROR
 CMPB #PACEREAD
 BEQ PSILFIRERROR1
PSILFIERRTEST BITA #(PSILFIWRITEFAULT!PSILFIVERFERR) WRITE ERROR?
 BNE PSILFIERRWRT
 BITA #PSILFIINVLLSN BAD LSN?
 BNE PSILFIERRLSN
 BITA PSILFISERNF SEEK ERROR?
 BNE PSILFIERRSEEK
 BITA #PSILFICHIPFAIL FDC CHIP FAIL?
 BNE PSILFIBADCHIP
 LDAA #ERR:DISKREAD/256
 LDAB #ERR:DISKREAD&$FF
PSILFIERROR LDX PSILFDCBPOINTER
 STAA DCB:LASTERROR,X
 STAB DCB:LASTERROR+1,X
 BRA PSILFIDONE

PSILFIWERROR STAA DSKINFO:WRITEERRSTS+1,X SAVE WRITE ERROR STATUS
 INC DSKINFO:WRITEERRCNT+1,X
 BNE PSILFIERRTEST
 INC DSKINFO:WRITEERRCNT,X
 BRA PSILFIERRTEST

PSILFIRERROR1 STAA DSKINFO:READERRSTS+1,X SAVE READ ERROR STATUS
 INC DSKINFO:READERRCNT+1,X
 BNE PSILFIERRTEST
 INC DSKINFO:READERRCNT,X
 BRA PSILFIERRTEST

PSILFIERRSEEK STAA DSKINFO:SEEKERRSTS+1,X SAVE SEEK ERROR STATUS
 INC DSKINFO:SEEKERRCNT+1,X
 BNE PSILFSP1
 INC DSKINFO:SEEKERRCNT,X
PSILFSP1
 LDAA #ERR:DISKSEEK/256
 LDAB #ERR:DISKSEEK&$FF
 BRA PSILFIERROR

PSILFIERRWRT LDAA #ERR:DISKWRITE/256
 LDAB #ERR:DISKWRITE&$FF
 BRA PSILFIERROR

PSILFIERRNOTRDY LDAA #ERR:DEVICENOTREADY/256
 LDAB #ERR:DEVICENOTREADY&$FF
 BRA PSILFIERROR

PSILFIERRWRTPROT LDAA #ERR:DSKWRTPROT/256
 LDAB #ERR:DSKWRTPROT&$FF
 BRA PSILFIERROR

PSILFIERRLSN LDAA #ERR:ILLLSN/256
 LDAB #ERR:ILLLSN&$FF
 BRA PSILFIERROR

PSILFIBADCHIP LDAA #ERR:DEVICEERRORED/256
 LDAB #ERR:DEVICEERRORED&$FF
 BRA PSILFIERROR
 PAGE
PSILFIWAITFORINTERRUPT EQU * WAIT FOR FLOPPY RESPONSE
 LDAA #PSILFIDISKINRDY WAIT A MOMENT ...
 LDAB #150/(2+4+4+4) TO SEE IF FLOPPY RESPONDS WITHIN 150 uS.
PSILFIWAITFORINTL EQU *
 DECB
 BEQ PSILFIWAITFORINT1 B/ FLOPPY ISN'T GOING TO RESPOND QUICKLY
 BITA PSILFIIOSTS
 BEQ PSILFIWAITFORINTL B/ FLOPPY HASN'T RESPONDED YET
 LDX PSILFDCBPOINTER TO MATCH WHAT PSILFIINTERRUPT DOES
 LDAA PSILFIDISKIN FLOPPY DONE!  GET STATUS AND SET CC BITS
 RTS  AND RETURN

PSILFIWAITFORINT1 PULA  SAVE RETURN ADDRESS
 PULB
 STAA PSILFINTPC I.E., WHERE TO PICK UP WHEN INTERRUPT OCCURS
 STAB PSILFINTPC+1
 LDX #30*TICKSPERSECOND+NTIMEOUTBLOCKS
 STX PSILFTIMEOUTCOUNT
 LDAA #PSILFICTLENIRQ!PSILFICTLRESET ENABLE FLOPPY INTERRUPT
 NOP
 SEI
 STAA PSILFICONTROL
 JMP SDOS+SDOS:RTI
 PAGE
*
* PSILFISENDBYTE -- (A) IS SENT TO FLOPPY
*  WAITS FOR DATA TAKEN BY FLOPPY
*
PSILFISENDBYTE EQU *
 STAA PSILFIDISKOUT
 PSHB
 LDAB #PSILFIDISKOUTBUSY
 CLRA
PSILFISENDBYTEL DECA  DOWN COUNT TIMEOUT
 BEQ PSILFISENDERROR B/ DIDN'T RESPOND!!
 BITB PSILFIIOSTS DID FLOPPY GRAB THE BYTE?
 BNE PSILFISENDBYTEL B/ NOT YET
 PULB  YEP, RESTORE (B)
 RTS  AND GET OUT!

PSILFISENDERROR INS CLEAN OFF THE STACK
 INS
 INS
PSILFITIMEOUT EQU * FLOPPY TIMED OUT!?
 CLR PSILFICONTROL RESET THE FLOPPY
 CLI  ALLOW INTERRUPTS
 LDAA PSILFIDISKIN TO CLEAR 'DISKIN FULL' BIT
 LDAA #PSILFICTLRESET (END RESET PULSE)
 STAA PSILFICONTROL
 LDAA #ERR:DEVICETIMEDOUT/256
 LDAB #ERR:DEVICETIMEDOUT&$FF
 LDX #$0001 "RESET" COMMAND SET MAPALGORITHM IN HARDWARE TO "1"
 STX PSILF0DCB+PSILFMAPALGORITHM MODIFY DCB'S TO MATCH
 STX PSILF1DCB+PSILFMAPALGORITHM
PSILFIERRORJ JMP PSILFIERROR
 PAGE
PSILFIDISMOUNT EQU *
 LDAA PSILFIDISKIN ISSUE DISMOUNT COMMAND
 LDAA #PACEDISMOUNT OUTPUT A DISMOUNT COMMAND
 STAA PSILFIDISKOUT OUTPUT "DISMOUNT..."
 JSR PSILFIWAITFORINTERRUPT FROM THE COMMAND BYTE
 LDAA PSILFDRIVE,X TELL WHICH DRIVE
 JSR PSILFISENDBYTE
 JSR PSILFIWAITFORINTERRUPT WAIT FOR RESPONSE
 BNE PSILFIIOERROR B/ DIDN'T GET BACK ERROR-FREE RESPONSE
 LDX PSILFDCBPOINTER OK, NOW MARK MAP ALGORITHM AS '1'
 CLR PSILFMAPALGORITHM,X
 LDAA #1
 STAA PSILFMAPALGORITHM+1,X
 JMP PSILFIDONE
PSILFIIOERROR JMP PSILFIERRTEST
 PAGE
PSILFISETMAP EQU *
 LDAA PSILFIDISKIN
 LDAA #PACESETMAP
 STAA PSILFIDISKOUT SEND THE "SETMAP" COMMAND BYTE
 JSR PSILFIWAITFORINTERRUPT
 LDAA PSILFDRIVE,X SEND DRIVE NUMBER TO FLOPPY
 JSR PSILFISENDBYTE
 LDAA DSKINFO:MAPALGORITHM,X
 JSR PSILFISENDBYTE
 LDAA DSKINFO:MAPALGORITHM+1,X
 JSR PSILFISENDBYTE
 JSR PSILFIWAITFORINTERRUPT
 BNE PSILFIIOERROR
 LDX PSILFDCBPOINTER NOW SAVE CURRENT MAPALGORITHM IN DCB
 LDAA DSKINFO:MAPALGORITHM,X
 LDAB DSKINFO:MAPALGORITHM+1,X
 STAA PSILFMAPALGORITHM,X
 STAB PSILFMAPALGORITHM+1,X
 JMP PSILFIDONE
 PAGE
PSILFILOADNX EQU * LOAD AND EXECUTE DIAGNOSTIC
 CLI  LOAD AND EXECUTE DIAGNOSTIC
 LDAA PSILFIDISKIN
 LDAA #PACELOADNX
 STAA PSILFIDISKOUT SEND COMMAND BYTE TO FLOPPY
 JSR PSILFIWAITFORINTERRUPT
 LDX PSILFSYSCALLBLKPTR
 LDAA SCBLK:END,X SEND LOAD ADDRESS =
 JSR PSILFISENDBYTE VALUE SPECIFIED BY SCBLK EXTENSION
 LDAA SCBLK:END+1,X
 JSR PSILFISENDBYTE
 LDAA SCBLK:WRLEN,X SEND COUNT = SIZE OF WRITE BUFFER
 JSR PSILFISENDBYTE
 LDAA SCBLK:WRLEN+1,X
 JSR PSILFISENDBYTE
 BSR FINDWRBUFEND
PSILFILOADNXL LDAA 0,X
 JSR PSILFISENDBYTE
 INX
 CPX PSILFIWRBUFEND
 BNE PSILFILOADNXL
 JMP PSILFIDONE

FINDWRBUFEND EQU *
 LDAA SCBLK:WRBUF,X
 LDAB SCBLK:WRBUF+1,X
 ADDB SCBLK:WRLEN+1,X
 ADCA SCBLK:WRLEN,X
 STAA PSILFIWRBUFEND
 STAB PSILFIWRBUFEND+1
 LDX SCBLK:WRBUF,X
 RTS
PSILFIWRBUFEND FDB 0 POINTER TO BYTE PAST END OF BUFFER
 PAGE
PSILFIFORMAT EQU * DO FORMAT OPERATION!
 LDX PSILFSYSCALLBLKPTR
 BSR FINDWRBUFEND
 LDAB #PSILFIDISKOUTBUSY
 LDAA 0,X GET FIRST BYTE
 INX  ADVANCE POINTER
 STAA PSILFIDISKOUT SIGNAL 'READY TO FORMAT'
PSILFIFORMAT1 BITB PSILFIIOSTS WAIT FOR DISK READY TO FORMAT
 BNE PSILFIFORMAT1
PSILFIFORMATL EQU *
 STAA PSILFIDISKOUT OUTPUT BYTE TO FLOPPY
 LDAA 0,X GET NEXT BYTE
 INX  ADVANCE BUFFER POINTER
 BITB PSILFIIOSTS READY FOR NEXT BYTE?
 BEQ PSILFIFORMATL B/ YES,GO FEED IT TO IT
 BITB PSILFIIOSTS READY FOR NEXT BYTE?
 BEQ PSILFIFORMATL B/ YES,GO FEED IT TO IT
 BITB PSILFIIOSTS READY FOR NEXT BYTE?
 BEQ PSILFIFORMATL B/ YES,GO FEED IT TO IT
 BITB PSILFIIOSTS READY FOR NEXT BYTE?
 BEQ PSILFIFORMATL B/ YES,GO FEED IT TO IT
 BITB PSILFIIOSTS READY FOR NEXT BYTE?
 BEQ PSILFIFORMATL B/ YES,GO FEED IT TO IT
* NOW AT LEAST 32 uS. HAS ELAPSED. FORMATTING MUST BE COMPLETE
 JSR PSILFIWAITFORINTERRUPT
 JMP PSILFIWRITE
 PAGE
* ALLOCATE RESOURCE -- WAITS FOR OWNERSHIP OF RESOURCE (X)
* (X) POINTS TO RESOURCE AVAILABLE COUNT
* LIMIT OF 127 WAITING TASKS (ALL DOING DEC 0,X SIMULTANEOUSLY)

ALLOCATERESOURCEL INC 0,X RESTORE RESOURCE COUNT TO TRUE VALUE
 LDAA #WAITFORRESOURCE/256 NOW WAIT FOR AVAILABLE RESOURCE
 LDAB #WAITFORRESOURCE&$FF
 JSR SDOS+SDOS:WAITCOND
ALLOCATERESOURCE EQU *
 DEC 0,X ALLOCATE A RESOURCE UNIT
 BMI ALLOCATERESOURCEL B/ NONE AVAILABLE
 RTS

WAITFORRESOURCE EQU * WAIT FOR RESOURCE COUNT >= 1
 LDAA 0,X
 BGT WAITFORRESOURCE1 B/ TASK IS READY!
 CLRA  TASK IS NOT READY
WAITFORRESOURCE1 RTS
*
* FREE RESOURCE -- FREES RESOURCE (X)
* (X) POINTS TO RESOURCE AVAILABLE COUNT
*
FREERESOURCE EQU *
 LDAA 0,X IS RESOURCE COUNT = 0?
 BEQ FREERESOURCE1 B/ YES, MAYBE SOMEONE IS WAITING
 INC 0,X NO, MARK ANOTHER RESOURCE UNIT AS 'FREE'
 RTS

FREERESOURCE1 INC 0,X MARK RESOURCE AS FREE
 LDAA #READY/256 WAIT FOR A COMPLETED EVENT...
 LDAB #READY&$FF TO CAUSE RE-SCHEDULING
 JMP SDOS+SDOS:WAITCOND

READY LDAA #1 THIS WOULD BE MORE EFFICIENT IF
 RTS  IT WAS AIMED AT "EXECUTING"
 FIN IODRIVERBODY
 PAGE
 IF IODRIVERPOLL
 LDAA PSILFIIOSTS
 BITA #8  ;DISK INTERRUPTING?
 BEQ PSILFIPOLLNEXT ;KEEP GOING IF NOT
 JMP PSILFIINTERRUPT
PSILFIPOLLNEXT EQU *
 FIN IODRIVERPOLL

 IF IODRIVERINIT
PSILFRESET LDX #OKRTS
 STX PSILFRESET
 JMP PSILFINIT
 FIN IODRIVERINIT
 IF IODRIVERRAM
PSILFINTERFACE FCB 1 = # INTERFACES AVAILABLE (RESOURCE)
PSILFDCBPOINTER FDB PSILF0DCB ; CURRENT UNIT IN USE
PSILFINTPC FDB 0 ; START UP AFTER TRANSFER DONE INTERRUPT
PSILFREADWRITE RMB 1 READ/WRITE COMMAND
PSILFSYSCALLBLKPTR FDB 0 POINTER TO SYSTEM CALL BLOCK

PSILF3DCB FCB 1 DCB:DONEFLAG
 FDB 0 DCB:LASTERROR
 FDB PSILF3STR
 FDB NEXTDISKDCB DCB:NEXT
 FDB PSILFDRIVER DCB:DRIVER
 FDB PSILFNBPS
 FDB PSILFNSPT DSKINFO:NSPT
 FDB PSILFNTPC DSKINFO:NTPC
 FDB PSILFNCYL DSKINFO:NCYL
 RPT PSILF3DCB+DSKINFO:SIZE-*
 FCB 0
 FDB 1 CURRENT MAP ALGORITHM
 FCB 3 DRIVE SELECT 3
 FDB 0 SEEK ERROR COUNT
 FDB 0 LAST SEEK ERROR STATUS
 FDB 0 WRITE ERROR COUNT
 FDB 0 WRITE ERROR STATUS
 FDB 0 READ ERROR COUNT
 FDB 0 LAST READ ERROR STATUS
 FCB 0 OPERATION COUNT
 FCB 0
 FCB 0
 FCB    $FF,$FF,$FF     LAST SOFT ERR
PSILF3STR FCC 'D3:'
 FCB 0
NEXTDISKDCB  SET  PSILF3DCB
NDISKDCBS  SET NDISKDCBS+1
 PAGE
PSILF2DCB FCB 1 DCB:DONEFLAG
 FDB 0 DCB:LASTERROR
 FDB PSILF2STR
 FDB NEXTDISKDCB DCB:NEXT
 FDB PSILFDRIVER DCB:DRIVER
 FDB PSILFNBPS
 FDB PSILFNSPT DSKINFO:NSPT
 FDB PSILFNTPC DSKINFO:NTPC
 FDB PSILFNCYL DSKINFO:NCYL
 RPT PSILF2DCB+DSKINFO:SIZE-*
 FCB 0
 FDB 1 CURRENT MAP ALGORITHM
 FCB 2 DRIVE SELECT 2
 FDB 0 SEEK ERROR COUNT
 FDB 0 LAST SEEK ERROR STATUS
 FDB 0 WRITE ERROR COUNT
 FDB 0 WRITE ERROR STATUS
 FDB 0 READ ERROR COUNT
 FDB 0 LAST READ ERROR STATUS
 FCB 0 OPERATION COUNT
 FCB 0
 FCB 0
 FCB    $FF,$FF,$FF     LAST SOFT ERR
PSILF2STR FCC 'D2:'
 FCB 0
NEXTDISKDCB  SET  PSILF2DCB
NDISKDCBS  SET NDISKDCBS+1
 PAGE
PSILF1DCB FCB 1 DCB:DONEFLAG
 FDB 0 DCB:LASTERROR
 FDB PSILF1STR
 FDB NEXTDISKDCB DCB:NEXT
 FDB PSILFDRIVER DCB:DRIVER
 FDB PSILFNBPS
 FDB PSILFNSPT DSKINFO:NSPT
 FDB PSILFNTPC DSKINFO:NTPC
 FDB PSILFNCYL DSKINFO:NCYL
 RPT PSILF1DCB+DSKINFO:SIZE-*
 FCB 0
 FDB 1 CURRENT MAP ALGORITHM
 FCB 1 DRIVE SELECT 1
 FDB 0 SEEK ERROR COUNT
 FDB 0 LAST SEEK ERROR STATUS
 FDB 0 WRITE ERROR COUNT
 FDB 0 WRITE ERROR STATUS
 FDB 0 READ ERROR COUNT
 FDB 0 LAST READ ERROR STATUS
 FCB 0 OPERATION COUNT
 FCB 0
 FCB 0
 FCB    $FF,$FF,$FF
PSILF1STR FCC 'D1:'
 FCB 0
NEXTDISKDCB  SET  PSILF1DCB
NDISKDCBS  SET NDISKDCBS+1
 PAGE
PSILF0DCB FCB 1 DCB:DONEFLAG
 FDB 0 DCB:LASTERROR
 FDB PSILF0STR
 FDB NEXTDISKDCB DCB:NEXT
 FDB PSILFDRIVER DCB:DRIVER
 FDB PSILFNBPS
 FDB PSILFNSPT DSKINFO:NSPT
 FDB PSILFNTPC DSKINFO:NTPC
 FDB PSILFNCYL DSKINFO:NCYL
 RPT PSILF0DCB+DSKINFO:SIZE-*
 FCB 0
 FDB 1 MAPALGORITHM (INITZED TO "1" BY RESET)
 FCB 0 DRIVE 0
 FDB 0 SEEK ERROR COUNT
 FDB 0 LAST SEEK ERROR STATUS
 FDB 0 WRITE ERROR COUNT
 FDB 0 WRITE ERROR STATUS
 FDB 0 READ ERROR COUNT
 FDB 0 LAST READ ERROR STATUS
 FCB 0 OPERATION COUNT
 FCB 0
 FCB 0
 FCB    $FF,$FF,$FF
PSILF0STR FCC 'D0:'
 FCB 0
NEXTDISKDCB SET PSILF0DCB
NDISKDCBS SET NDISKDCBS+1

PSILFTIMEOUTBLOCK FDB NEXTTIMEOUT
PSILFTIMEOUTCOUNT FDB 0
 FDB PSILFITIMEOUT

*
NEXTTIMEOUT SET PSILFTIMEOUTBLOCK
NTIMEOUTS SET NTIMEOUTS+1
 FIN IODRIVERRAM
