.TITLE DSKDY RX21/RX02 disk driver .NLIST BEX .ENABL LC ; ; Pdp11/dcn rx21/rx02 disk driver ; ; This module is an extension of the disk driver process. it services ; The dec rx21/rxv21 disk controller with up to two rx02 drives and ssdd ; disks. It also supports 22-bit mode and dsdd disks using the dsd 880 or ; sigma rxv31 controllers. This driver does not support sssd disks. ; ; Max blocks: 988/1976, rt-11 directory segments: 4 (8 blocks), rt-11 id: 6 ; ; Note: standard csr/vector addresses are 777170/264. ; ; Conditional assembly switches ; .IIF NDF,CS.D22 CS.D22 == 0 ;0: dec rxv21, 1: dsd 880, 2: sigma rxv31 ; ; External symbols ; .GLOBL DSKINI,.WAIT,.SKED ; ; Entry symbols ; .GLOBL DYDPAT ;process control vector ; ; System definitions ; .ASECT .MCALL .COM,.PSA,.DFBLK,.DSK,.PAT ;dcnlib definitions .COM ;define common data .PSA ;define process save area .DFBLK ;define message codes .DSK ;define disk parameters ; ; Module definitions ; .MACRO SPIN,?L ;wait for transfer request L: TSTB RX2CS(R2) BPL L .ENDM SPIN ; ; Assembly parameters ; RTYCNT = 8. ;max retry count MAXTRK = 76. ;maximum tracks per side SECTRK = 26. ;sectors per track SECBLK = 2. ;sectors per block MAXBLK = MAXTRK*SECTRK/SECBLK ;blocks per side SECLNG = 256./SECBLK ;words per sector ; ; Control/status register bits (rx2cs) ; CSGO = 000001 ;start operation CSFBUF = 0*2 ;fill buffer CSEBUF = 1*2 ;empty buffer CSWRT = 2*2 ;write sector CSRD = 3*2 ;read sector CSRDST = 5*2 ;read status CSWRTD = 6*2 ;write deleted sector CSMAIN = 7*2 ;read error register CSUNIT = 000020 ;unit select CSDONE = 000040 ;done flag CSIEN = 000100 ;interrupt enable CSTR = 000200 ;transfer request CSDN = 000400 ;density select CSHEAD = 001000 ;head select CS22 = 002000 ;22-bit select (sigma rxv31 only) CSRX02 = 004000 ;rx02 flag CSINIT = 040000 ;initialize ; ; Error/status register bits (rx2es) ; DBCRC = 000001 ;crc error DBLSID = 000002 ;media double-side DBIN = 000004 ;initialize done DBACLO = 000010 ;ac power low DBDNER = 000020 ;density error DBDN = 000040 ;media double-density DBDD = 000100 ;deleted data DBRDY = 000200 ;drive ready DBUNSL = 000400 ;unit select DBHDSL = 001000 ;head select DBWCOV = 002000 ;word count overflow DBNEXM = 004000 ;bus timeout ; ; Process save area extension (dya) ; . = DASEND DYATWC: .BLKW 1 ;current block word count DYAFUN: .BLKW 1 ;function word DYAINT: .BLKW 1 ;interrupt routine pointer .BLKW REGEND/2+DSKSTK ;process stack DYAEND = . ;end of psa extension ; ; Rx21/rxv21 device registers ; . = 0 RX2CS: .BLKW 1 ;control/status register RX2DB: .BLKW 1 ;data buffer RX2AE: .BLKW 1 ;address extension (dsd 880 only) .PAGE ; ; Procedure segment ; ; Supervisor-state procedure ; Dsects: r2 = dev, r3 = par, r4 = reg, r5 = psa ; .PSECT $KERI,RO,I ; ; Start i/o operation ; DSKGO: JSR PC,.WAIT ;switch to wait state ASL DASBLK(R5) ;compute initial logical sector .IF EQ,CS.D22-2 ;conditional assembly for sigma controller MOV #CS22+CSDN+CSIEN+CSGO,DYAFUN(R5) ;construct command .IFF MOV #CSDN+CSIEN+CSGO,DYAFUN(R5) ;construct command .ENDC TSTB DASDRV(R5) ;is this unit 1 BEQ RESTRT ;branch if no BIS #CSUNIT,DYAFUN(R5) ;yes. set unit-1 bit RESTRT: MOV #DSK10,DYAINT(R5) ;is this write CMPB #BC.WRT+CHNCTL,DASOPN(R5) BEQ 1$ ;branch if yes MOV #DSK20,DYAINT(R5) ;no. must be read 1$: BIS #100,RX2CS(R2) ;fall into interrupt routines RTS PC ; ; Device interrupt ; DSKINT: MOV RX2DB(R2),R0 ;fetch ending status TST RX2CS(R2) ;did error occur BMI 1$ ;branch if yes JMP @DYAINT(R5) ;execute interrupt routine ; 1$: TSTB DASERC(R5) ;error. is this the first one BNE 2$ ;branch if no INC PARTRY(R3) ;yes. record total faults 2$: INCB DASERC(R5) ;bump retry count CMPB DASERC(R5),#RTYCNT ;is it exceeded BHI 5$ ;branch if yes BIT #DBCRC,R0 ;no. is this crc error BEQ 3$ ;branch if no INC PARCRC(R3) ;yes. data check BR 4$ ; 3$: INC PARSEK(R3) ;seek check 4$: MOV #CSINIT,RX2CS(R2) ;reinitialize and try again BR RESTRT ; 5$: BIS #1,REGPS(R4) ;return hard error MOV R0,@R4 DONE: ASR DASBLK(R5) ;restore block number CLR RX2CS(R2) ;operation complete JMP .SKED ;shortcut ; ; Write segments ; DSK31: JSR PC,NXTSEC ;end write sector. bump to next sector BEQ DONE ;branch if done DSK10: MOV #CSFBUF,R1 ;write. fill buffer MOV #DSK12,DYAINT(R5) BR XFER ; DSK12: MOV #CSWRT,R1 ;end fill buffer. write sector MOV #DSK31,DYAINT(R5) BR CONVRT ; ; Read segments ; DSK21: JSR PC,NXTSEC ;end empty buffer. bump to next sector BEQ DONE ;branch if done DSK20: MOV #CSRD,R1 ;read. read sector MOV #DSK22,DYAINT(R5) CONVRT: MOV DASBLK(R5),R0 ;get logical sector CMP R0,#MAXTRK*SECTRK ;select head BLO 1$ SUB #MAXTRK*SECTRK,R0 BIS #CSHEAD,R1 1$: BIS DYAFUN(R5),R1 ;load function MOV R1,RX2CS(R2) MOV R0,R1 ;compute raw sector/track numbers CLR R0 DIV #SECTRK,R0 CMP #12.,R1 ;fiddle for interleaving ROL R1 ASL R0 ADD R0,R1 ADD R0,R1 ADD R0,R1 ASR R0 INC R0 2$: SUB #SECTRK,R1 BGE 2$ ADD #SECTRK+1,R1 SPIN ;load sector MOV R1,RX2DB(R2) SPIN ;load track MOV R0,RX2DB(R2) RTS PC ; DSK22: MOV #CSEBUF,R1 ;end read sector. empty buffer MOV #DSK21,DYAINT(R5) XFER: MOVB DASADX(R5),R0 ;set up address extension bits .IF EQ,CS.D22-1 ;conditional assembly for dsd controller MOVB R0,RX2AE(R2) ;insert bus address 16:22 .ENDC BIC #^C3,R0 ;insert bus address 16:17 ASH #12.,R0 BIS R0,R1 BIS DYAFUN(R5),R1 ;load function MOV R1,RX2CS(R2) MOV DASRWC(R5),R0 ;compute word count CMP R0,#SECLNG BLOS 1$ MOV #SECLNG,R0 1$: MOV R0,DYATWC(R5) SPIN ;load word count MOV R0,RX2DB(R2) SPIN ;load bus address 0:15 MOV DASADR(R5),RX2DB(R2) .IF EQ,CS.D22-2 ;conditional assembly for sigma controller SPIN ;load bus address 16:21 MOVB DASADX(R5),RX2DB(R2) .ENDC RTRN: RTS PC ; ; Subroutine to update transfer parameters ; Returns c(cc) = z if transfer complete ; NXTSEC: INC DASBLK(R5) ;update logical sector MOV DYATWC(R5),R0 ;update transfer parameters SUB R0,DASRWC(R5) ASL R0 ADD R0,DASADR(R5) ADCB DASADX(R5) TST DASRWC(R5) ;set transfer-complete indicator RTS PC ; ; Data segment ; .PSECT $KERD,RO,D ; ; Process header ; DYDPAT: .PAT DYAEND,DSKINI,PRI2,<0,0,DSKGO,DSKINT> ; .END