; DSD-210 HANDLER FOR FLOPPY DISK SYSTEM V2 ; RX01F.MAC 17-MAY-76 .TITLE DSD MULTI-DRIVE FLOPPY DISK HANDLER MAXDRV=2 ; CONFIGURE FOR 2 DRIVES. ; DEFINE = 3 FOR 3 DRIVES ; FLOPPY INTERFACE REGISTERS AND DEFS. RXCS=177170 ; COMMAND AND STATUS REGISTER. ;WRITE ; RO IN X X X X X X RO IE UN UN FN FN FN EX ; READ ;ERR WO X X X X X X TR IE DN WO WO WO WO WO ; RO = READ ONLY ; WO = WRITE ONLY ; ERR= ERROR DET. (CLEARED BY COMMAND INIT ; IN = CONTROLLER INIT. ; TR = TRANSFER REQUEST. ; IE = INTERRUPT ENABLED ON DONE. ; DN = DONE FLAG. ; UN = UNIT SELECT. ; FN = FUNCTION SELECT. ; 0=FILL BUFFER 1=READ BUFFER ; 2=WRITE SECTOR 3=READ SECTOR ; 4=NOT USED 5=READ STATUS ; 6=WRT.DELETED DATA 7=READ ERROR-REG ; EX = EXECUTE. RXDB=177172 ; DATA BUFFER REGISTER. ; CONTEXT CONTROLLED BY COMMAND SEQUENCE. RXVEC= 264 ; INTERRUPT VECTOR ; FORMAT OPTION IS ENTERED BY SPECIFYING A WRITE SECTOR COMMAND ; FOLLOWED BY A SECTOR VALUE OF 152 AND THE DESIRED PHYSICAL ; TRACK # TO BE RE-FORMATTED. ; THE CONTROLLER THEN REQUESTS 26. SECTOR #'S IN THE ; ORDER THAT THEY ARE TO BE WRITTEN. .MCALL .REGDEF .REGDEF ; ERROR CODES GIVEN BY READ ERROR STATUS FUNCT (MODE 5) ; CODE LIGHT # MEANING ; 10 2 DRIVE 0 FAILED TO HOME ON INIT, OR DIDN'T SELECT ; 20 2 DRIVE 1 FAILED TO HOME ON INIT, OR DIDN'T SELECT ; 30 2 FOUND HOME WHEN STEPPING OUT 10 TRACKS FOR INIT. ; 40 2 TRACK GREATER THAN 77. OR UNIT SELECT ERROR. ; 50 2 HOME BEFORE DESIRED TRACK FOUND. ; 70 2 DESIRED SECTOR COULD NOT BE FOUND AFTER 2 REVS. ; ; 100 3 WRITE PROTECT ERROR. ; 110 MORE THAN 40 USEC AND NO SEPERATED CLOCK FOUND. ; 120 0 NO PREAMBLE WAS FOUND ( 24 BITS OF 0'S) ; 130 0 PREAMBLE FOUND BUT NO I;O MARK WITHIN WINDOW. ; 140 0 CRC ERROR ON WHAT APPEARED TO BE HEADER. ; 150 2 HEADER TRACK ADDRESS OF A GOOD HEADER DIDN'T ; MATCH DESIRED TRACK. ; 160 0 TOO MANY TRIES FOR AN I.D. ADDRESS MARK. ; 170 0 DATA ADDRESS MARK NOT FOUND IN ALLOTED TIME. ; 200 0 CRC ERROR ON READING SECTOR FROM DISK. ; RXES STATUS BIT 11 ALSO SET. ; 210 1 PARITY ERROR (INTERFACE <=> CONTROLLER) ; RXES STATUS BIT 10 ALSO SET. ; 220 2 DRIVE 2 FAILED TO HOME ON INIT. ; 230 2 DRIVE 3 FAILED TO HOME ON INIT. ; 240 3 FORMATTER ENABLE ERROR. ; 250 0 EXPECTED HEADER NOT FOUND AFTER TRACK FORMAT. ; 260 0 INDEX MARK NOT FOUND IN EXPECTED RANGE. ; (FORMAT NOT BEGUN) ; 270 0 INDEX MARK NOT FOUND IN EXPECTED RANGE. ; (FORMAT HAS OCCOURED) ; LIGHTS MEANING ; 0 FRONT DATA TYPE ERROR ; 1 FRONT PARITY ERROR BETWEEN CONTROLLER-INTERFACE. ; 2 FRONT SEEK TYPE ERRORS ; 3 FRONT SWITCH CONFLICT ERROR OR CONTROLLER ERROR. ; INCLUDES WRITE PROTECT OR FORMAT INHIBITED TYPE ERRORS. ; BOARD LIGHTS ; 4 UP-LEFT CONTROLLER WAITING FOR BUS INTERFACE READY. ; 5 UP-RGHT INIT IN PROGRESS. ; 6 LW-LEFT READ IN PROGRESS ; 7 LW-RGHT WRITE IN PROGRESS. ; SYSTEM EQUATES PR4=200 PR5=240 PR7=340 SYINPR=PR7 SYSPTR=54 OFFSET=270 ; GLOBALS FOR USE AS SYSTEM DEVICE .GLOBL SYSTAT,SYSIZE,SBLOCK,SY,DXINT,SYINPR .GLOBL RKSYS,RFSYS,DTSYS,DSSYS,DPSYS,DXSYS .GLOBL $INPTR,$INTEN ; RX SYSTEM DEFS DTSYS=0 RFSYS=0 RKSYS=0 DSSYS=0 DPSYS=0 SBLOCK=494. ; 494. = 756(8) BLKS OF 4 SECTORS EACH ; IN TRACKS 1-76 EACH OF 26. SECTORS. SYSTAT=100022 ; CONTROL AND STATUS BITS CSGO=1 ;EXECUTE FUNCTION ; FUNCTIONS (BITS 1-3) CSFBUF= 0*2 ;FILL BUFFER (PRE-WRITE) CSEBUF= 1*2 ;EMPTY BUFFER (POST-READ) CSWRT= 2*2 ;WRITE SECTOR CSRD= 3*2 ;READ SECTOR CSRDST= 5*2 ;READ STATUS CSWRTD= 6*2 ;WRITE SECTOR WITH DELETED DATA CSRDERF= 7*2 ; READ ERROR REG. FUNCTION. CSRDWR= CSRD&CSWRT ;READ OR WRITE BIT .IF EQ MAXDRV-2 MAXUNM= 6 ; MAXUNM = 6 IF ONLY DRIVES 0-1 .IFF MAXUNM= 4 ; ILLEGAL UNIT MASK IF DRIVES 0,1,2 EXIST .ENDC CSUNIT= 20 ;UNIT BIT CSDONE= 40 ;DONE BIT CSINT= 100 ;INTERUPT ENABLE CSTR= 200 ;TRANSFER REQUEST CSINIT= 40000 ;RX11 INITIALIZE CSERR= 100000 ;ERROR DBDD= 100 ;DELETED DATA MARK DBIN= 4 ;RX INIT DONE INDICATOR RETRY=8. ;RETRY COUNT SPFUNC= 100000 ;SPECIAL FUNCTIONS FLAG ; GENERAL COMMENTS: ; ; THIS HANDLER SERVES AS THE STD. RT-11 RX01 DEVICE HNDLR FOR ; BOTH THE SYSTEM DEVICE HNDLR AND NON-SYSTEM HNDLR. IT ALSO ; PROVIDES THREE SPECIAL FUNCTION CAPABILITIES TO ; SUPPORT PHYSICAL I/O ON THE FLOPPY AS A FOREIGN VOLUME. ; THE SPECIAL FUNCTIONS ARE: ; CODE ACTION ; 377 ABSOLUTE SECTOR READ. ; WCNT=TRACK, BLK=SECTOR, BUFFER=65 ; WORD BUFFER OF WHICH WORD 1 IS DELETED DATA FLAG. ; 376 ABSOLUTE SECTOR WRITE. ARGUMENTS SAME AS READ. ; 375 ABSOLUTE SECTOR WRITE WITH DELETED DATA. WORD 1 ; OF 65 WORD BUFFER ALWAYS SET TO 0. ; ; IN STANDARD RT-11 MODE A 2:1 INTERLEAVE IS USED ON A ; SINGLE TRACK AND A 6 SECTOR SKEW IS USED ACROSS TRACKS. ; TRACK 0 IS LEFT ALONE FOR PROPOSED ANSI COMPATABILITY. .CSECT SYSHND RXSTRT: .WORD RXVEC ;VECTOR LOCATION .WORD DXINT-. ;OFFSET TO INTERUPT SERVICE .WORD PR7 ;INTERUPT AT PRIORITY 7 DXSYS: SY: RXLQE: .WORD 0 ;LAST QUEUE ELEMENT POINTER RXCQE: .WORD 0 ;CURRENT QUEUE ELEMENT POINTER ; REQUEST ENTRY POINT CMP -(SP),-(SP) ;RESERVE 2 WORDS ON TO STACK TO USE ;COMMON EXIT SEQUENCE MOV RXCQE,R3 ;GET POINTER TO I/O ELEMENT MOV (R3)+,R5 ;GET BLOCK NUMBER MOV #CSGO+CSRD,R4 ;FORM A GUESS AT RXCS FUNCTION MOVB (R3)+,R1 ;SAVE FUNCTION FOR LATER BITB #MAXUNM, @R3 ; ANY ILLEGAL BITS IN UNIT SELECT? BNE RXERR ;BRANCH IF YES, ERROR .IF EQ MAXDRV-2 BITB #1,(R3)+ ;CHECK FOR ONLY UNIT 0 OR 1? .IFF BITB #1, (R3) ; CHECK IF SELECTED UNIT ODD .IFTF ; ASSEMBLE THIS ALWAYS BEQ .+6 ;BRANCH IF 0 BIS #CSUNIT,R4 ;UPDATE GUESS AT RXCS .IFF BITB #2, (R3)+ ; UNIT 2? BEQ .+6 BIS #2*CSUNIT, R4 ; SET UNIT (2) .ENDC 1$: MOV (R3)+,R0 ;SAVE THE BUFFER ADDRESS MOV @R3,R2 ;GET WORD COUNT BPL 2$ ;TAKE ABSOLUTE VALUE ; BIC #CSEBUF,R4 ;WRITE FUNCTIONS ARE 0,2 SO CLR 1 BIT CMPB -(R4),-(R4) ;EQUIVALENT TO ABOVE BIC NEG R2 ;MAKES IT POSITIVE 2$: ADD PC,R1 ;FORM PIC REFERENCE TO CHGTBL MOVB CHGTBL-.(R1),R3 ;GET FUNCTION MODIFIER ROR R1 ;SET C TO FLAG IF SPECIAL FUNCTION ROR R3 ;SET SIGN TO SPFUNC FLAG (NON-OBVIOUS!) ADD R3,R4 ;MODIFY FUNCTION BASED ON READ/WRITE BMI 3$ ;BRANCH IF SPECIAL FUNCTION REQUEST ASL R5 ;MAKE A LOGICAL SECTOR NUMBER ASL R5 ;BLOCK*4 ASL R2 ;MAKE WORD COUNT UNSIGNED BYTE COUNT BR 4$ ;SKIP SPECIAL FUNCTION INITING 3$: CLR (R0)+ ;CLEAR DELETED DATA FLAG WORD MOV R2,PHYTRK ;SAVE TRACK FOR LATER MOV #128.,R2 ;SET THE BYTE COUNT TO 128 4$: MOV R0,BUFRAD ;SAVE FOR LATER MOV R5,RXLSN ;SAVE FOR LATER MOV R4,RXFUN2 ;SAVE READ OR WRITE RXCS COMMAND MOV R2,BYTCNT ;SAVE FOR LATER MOV #RETRY,(PC)+ ;SET RETRY COUNT RXTRY: .WORD 0 ;RETRY COUNT RXINIT: CLR R3 ;SET THIS IS INITIAL INTERRUPT FLAG BR RXWAIT ;PERFORM A RETURN TO WAIT FOR INTERUPT RXERR: MOV RXCQE,R4 ;R4 -> CURRENT QUEUE ELEMENT BIS #1,@-(R4) ;SET HARD ERROR IN CSW RXDONE: MOV (SP)+,R3 ;RESTORE SOME REGS MOV (SP)+,R2 CLR @RXCSA ;DISABLE FLOPPY INTERRUPTS BR RXEXIT ;SKIP RX INITIALIZE FUNCTION ; RX ABORT ENTRY BR RXABRT ;ABORT OPERATION ; INTERUPT ENTRY DXINT: JSR R5,@$INPTR ;FIX MY PRIORITY .WORD ^C&PR7 ;DROP TO 5 MOV R2,-(SP) ;SAVE SOME REGS MOV R3,-(SP) MOV (PC)+,R4 ;GET ADDRESS OF RX STATUS RXCSA: .WORD RXCS ;ONLY POINTER TO I/O PAGE MOV R4,R5 ;POINT R5 TO RX DATA BUFFER TST (R5)+ ;CHECK FOR ERROR BMI RXERR1 ;BRANCH IF ERROR ; CODE FOR FLOPPY POWER FAIL ; BIT #DBIN,@R5 ;DID INITIALIZE APPEAR IN RXES? ; BNE RXERR1 ;BRANCH IF SO TO RETRY NEG (PC)+ ;IS THIS INITIAL INTERRUPT? C=0 IF YES INTINT: .WORD 0 ;INTERNAL INITIAL INTERUPT FLAG MOV #128.,R3 ;INIT R3 FOR 128 BYTES, USED LATER BIT #CSEBUF,RXFUN2 ;READ OR WRITE INTERUPT? BNE 2$ ;BRANCH IF READ BCC 1$ ;BRANCH TO AVOID UPDATING POINTERS JSR PC,NXTSEC ;SET UP FOR NEXT WRITE 1$: JSR R0,FILEMB ;LOAD THE BUFFER ;FILEMB ARG LIST MOVB (R2)+,@R5 ;MOVB TO BE PLACED IN-LINE IN FILEMB .WORD CSGO+CSFBUF ;FILL BUFFER COMMAND CLRB @R5 ;ZERO FILL SECTOR INSTRUCTION WHICH ;WOULD BE USED FOR SHORT WRITES ; BR 3$ ;SKIP READ FINISHING, (C BIT IS 0) 2$: BCC 3$ ;BRANCH TO AVOID EMPTYING BUFFER TST RXFUN2 ;IS THIS SPECIAL FUNCTION REQUEST? BPL 4$ ;BRANCH IF NOT SPECIAL FUNCTION CALL BIT #DBDD,@R5 ;IS DELETED DATA FLAG PRESENT? BEQ 4$ ;BRANCH IF IT IS NOT MOV BUFRAD,R2 ;GET ADDRESS OF USER BUFFER AREA INC -(R2) ;SET FLAG WORD TO 1 INDICATING DEL DATA 4$: JSR R0,FILEMB ;MOVE THE DATA INTO MEMORY FROM BUFFER ;FILEMB ARG LIST MOVB @R5,(R2)+ ;MOVB TO BE PLACED IN LINE IN FILEMB .WORD CSGO+CSEBUF ;EMPTY BUFFER COMMAND MOVB @R5,R2 ;DATA SLUFFER TO BE USED FOR SHORT READ JSR PC,NXTSEC ;SET UP TO READ NEXT SECTOR 3$: MOV (PC)+,R3 ;GET THE LOGICAL SECTOR # = 4*BLOCK #. RXLSN: .WORD 0 ;LOGICAL SECTOR NUMBER KEPT HERE MOV (PC)+,R2 ;IF SPECIAL FUNCTION R3 GETS SECTOR PHYTRK: .WORD 0 ;ABSOLUTE TRACK FOR SPECIAL FUNCS TST RXFUN2 ;IS THIS SPECIAL FUNCTION? BMI DOFUNC ;BRANCH IF SPECIAL FUNCTIONS ; FLOPPY INTERLEAVE ALGORITHM MOV #8.,R2 ;LOOP COUNT 1$: CMP #6400,R3 ;DOES 26 GO INTO DIVIDEND? BHI 2$ ;BRANCH IF NOT, C CLEAR ADD #171400,R3 ;SUBTRACT 26 FROM DIVIDEND, SETS C 2$: ROL R3 ;SHIFT DIVIDEND AND QUOTIENT DEC R2 ;DEC LOOP COUNT BGT 1$ ;BRANCH TILL DIVIDE DONE MOVB R3,R2 ;COPY TRACK NUMBER CLRB R3 ;REMOVE TRACK NUMBER FROM REMAINDER SWAB R3 ;GET REMAINDER CMP #12.,R3 ;C=1 IF 13<=R3<=25, ELSE C=0 ROL R3 ;DOUBLE FOR 2 TO 1 INTERLEAVE ;C-BIT COMES IN FOR SECTOR GROUP ASL R2 ;ADD TRACK TO TRACK SKEW TO SECTOR ADD R2,R3 ;SKEW BY 2* TRACK ADD R2,R3 ;SKEW BY 4* TRACK ADD R2,R3 ;SKEW BY 6* TRACK ASR R2 ;REFIX TRACK NUMBER INC R2 ;PUT TRACK # IN RANGE 1-76 TO HANDLE ;ANSI FLOPPY, TRACK 0 IS LEFT ALONE 3$: SUB #26.,R3 ;MODULO SECTOR INTO RANGE -26,-1 BGE 3$ ;LOOP TILL REMAINDER GOES NEGATIVE ADD #27.,R3 ;PUT SECTOR IN RANGE 1,26 DOFUNC: MOV (PC)+,@R4 ;SET THE FUNCTION RXFUN2: .WORD 0 ;READ OR WRITE COMMAND ON CORRECT UNIT 1$: TSTB @R4 ;WAIT FOR TRANSFER READY BEQ 1$ ;WAIT BPL RXERR1 ;TR IS NOT UP, THATS AN ERROR MOV R3,@R5 ;SET SECTOR FOR FLOPPY 2$: TSTB @R4 ;WAIT FOR TRANSFER READY BEQ 2$ ;WAIT BMI SECOK ;BRANCH IF TR UP, ELSE ERROR RXERR1: DEC RXTRY ;SHOULD WE TRY AGAIN? BLT RXERR ;BRANCH IF NO, RETRY COUNT EXPIRED MOV #CSINIT,@R4 ;START A RECALIBRATE BR RXINIT ;EXIT THROUGH START OPERATION CODE SECOK: MOV R2,@R5 ;SET TRACK FOR FLOPPY RXWAIT: MOV R3,INTINT ;INTINT >0 FOR PROCESS INTERRUPT ENTRY MOV (SP)+,R3 ;RESTORE THE REGS MOV (SP)+,R2 BIS #CSINT,@RXCSA ;ENABLE FLOPPY INTERRUPTS, ;THIS SHOULD CAUSE AN INTERRUPT WHEN DONE IS UP RETURN: RTS PC ;RETURN, WE'LL BE BACK WITH AN INTERUPT NXTSEC: ADD R3,BUFRAD ;UPDATE BUFFER ADDRESS INC RXLSN ;BUMP LOGICAL SECTOR SUB R3,BYTCNT ;REDUCE THE AMOUNT LEFT TO TRANSFER BHI RETURN ;BRANCH IF WE ARE NOT DONE CLR BYTCNT ;INIT FOR POSSIBLE SHORT WRITE BIT #CSEBUF+SPFUNC,RXFUN2 ;IS THIS A READ OR SPECIAL ;FUNCTION OPERATION? BNE 1$ ;BRANCH IF EITHER, FOR .WRITE WE HAVE ;TO 0 TO THE END OF A BLOCK BIT #3,RXLSN ;ARE WE AT 1ST SECTOR IN BLOCK? BNE RETURN ;BRANCH IF NOT TO CONTINUE 1$: TST (SP)+ ;POP RETURN ADDRESS FROM STACK BR RXDONE ;REQUEST DONE RXABRT: MOV #CSINIT,@RXCSA ;PERFORM AN RX11 INITIALIZE RXEXIT: MOV PC,R4 ;EXIT TO MONITOR FREEING QUEUE ELEMENT ADD #RXCQE-.,R4 ;R4 HAS ADDRESS OF RXCQE MOV @#SYSPTR,R5 JMP @OFFSET(R5) ;GO BACK TO MONTOR ; R3 IS 128 ON ENTRY ; **NOTE** THIS ROUTINE ASSUMES ERROR CAN NOT COME UP ; DURING A FILL OR EMPTY!! FILEMB: MOV (R0)+,EFBUF ;PUT CORRECT MOV INSTRUCTION IN FOR ;EITHER FILLING OR EMPTYING RX BUFFER MOV (R0)+,@R4 ;INITIATE FILL OR EMPTY BUFFER COMMAND MOV (PC)+,-(SP) ;ASSUME MAXIMUM OF BYTCNT ; TO MOVE FROM BUFFER BYTCNT: .WORD 0 ;THE BYTE COUNT IS KEPT HERE BEQ ZFILL ;BRANCH IF SEEK OR SHORT WRITE ;NOTE SEEK DOES THE EMPTY (TIME WASTER) CMP @SP,R3 ;NOW MAKE SURE COUNT IS 128 OR LESS BLOS 1$ ;BRANCH IF @SP IS 128 OR LESS MOV R3,@SP ;RESET COUNT TO 128 1$: MOV (PC)+,R2 ;PUT THE BUFFER ADDRESS IN R2 BUFRAD: .WORD 0 ;THE BUFFER ADDRESS IS KEPT HERE TRBYT: TSTB @R4 ;WAIT FOR TRANSFER READY BPL TRBYT ;BRANCH IF TR NOT UP EFBUF: HALT ;INSTRUCTIONS TO MOV OR SLUFF DATA FROM ;BUFFER GETS PLACED HERE ; MOVE DATA SLUFF DATA ;MOVB (R2)+,@R5 CLRB @R5 FILL ;MOVB @R5,(R2)+ MOVB @R5,R2 EMPTY DEC @SP ;CHECK FOR COUNT DONE BGT TRBYT ;STILL MORE TO TRANSFER ZFILL: MOV @R0,EFBUF ;CHANGE MOV INSTRUCTION TO CORRECT ;INSTR FOR SLUFFING DATA TO/FROM BUFFER 1$: TSTB @R4 ;WAIT LOOP BEQ 1$ ;WAIT FOR SOME INDICATION (TR,DONE) BMI EFBUF ;BRANCH IF TR CAME UP TO SLUFF DATA BIT (R0)+,(SP)+ ;BUMP R0 TO RET. ADDR AND REMOVE ;JUNK WORD FROM STACK LEAVING C BIT=0 RTS R0 ;RETURN .BYTE 6*2 ;READ+GO -> WRITE DELETED+GO .BYTE -2*2 ;READ+GO -> WRITE+GO .BYTE 0*2 ;READ+GO -> READ+GO CHGTBL: .BYTE 0*2 ;READ/WRITE STAY THE SAME .EVEN $INPTR: .WORD $INTEN ;INTERUPT ENTRY COMMMUNICATIONS WORD SYSIZE=.-RXSTRT ;TOTAL SIZE OF HANDLER .END