.TITLE DWDRV .IDENT /01/ .LIST ME .LIST BEX .NLIST CND .NLIST TTM ; ; DWK mini winchester controller driver ; ; MACRO library calls ; D$$W11=2 LD$DW=1 VC$DW=0 .MCALL PKTDF$ .MCALL KRBDF$,UCBDF$ PKTDF$ ; Define i/o packet offsets KRBDF$ UCBDF$ .MACRO DB REPT .REPT 'REPT' .WORD 0 .ENDR .ENDM DB .MACRO PATCH REPT ; .REPT 'REPT' ; NOP ; .ENDR .ENDM PATCH ; ; Equated symbols ; RETRY=2. ; Error retry count DWID=-20 DW$ID=401 DWPRE=-14 DWERR=-14 ER.SNF=400 ER.TR0=1000 ER.GFL=2000 ER.HNF=10000 ER.ACR=20000 ER.DCR=40000 DWREV=-12 DWSEC=-12 DWRD=-10 DWCYL=-6 DWTRK=-4 DWCSR2=-2 HSEEK= 20 READ= 40 WRITE= 60 FORMAT=120 S2.ERR=400 S2.DRQ=4000 S2.SEK=10000 S2.WRF=20000 S2.DWY=40000 DWCSR=0 ST.OPN= 1 ST.INIT=10 ST.IE= 100 ST.DRQ= 200 ST.DCP= 4000 ST.BUSY=100000 ; ; Local data ; ; Controller impure data tables (indexed by controller number) ; ; ; Diagnostic function code table ; FUNTBL: .WORD IO.HMS!IQ.UMD, 20 .WORD IO.WDH!IQ.UMD, 120 FUNTBE: .IF DF R$$MPL S.VCTM=-1 S.VITM=-1 S.VKRB=-1 S.VPKT=-1 S.VSTS=-1 S.VST2=-1 EXEVEC: .WORD 0 ; Vector yet not filled SCTM: .WORD S.CTM SITM: .WORD S.ITM SKRB: .WORD S.KRB SPKT: .WORD S.PKT SSTS: .WORD S.STS SST2: .WORD S.ST2 BLKC2: .WORD $BLKC2 BMSET: .WORD $BMSET CRPAS: .WORD $CRPAS CVLBN: .WORD $CVLBN DTOER: .WORD $DTOER DVERR: .WORD $DVERR FORK: .WORD $FORK GTPKT: .WORD $GTPKT IODON: .WORD $IODON KISR6: .WORD KISAR6 RLCN: .WORD $RLCN RQCND: .WORD $RQCND VOLVD: .WORD $VOLVD EXEVCL=<<<.-EXEVEC>/2>-1> SCBPAT: .WORD CTM1,SCTM .WORD ITM1,SITM .WORD RKRB1,SKRB .WORD KRB1,SKRB .WORD KRB2,SKRB .WORD KRB3,SKRB .WORD KRB4,SKRB .WORD KRB5,SKRB .WORD PKT1,SPKT .WORD PKT2,SPKT .WORD PKT3,SPKT .WORD PKT4,SPKT .WORD STS1,SSTS .WORD RST21,SST2 .WORD 0 .ENDC ;DF R$$MPL RTTBL: DB D$$W11 ; Error retry count and positioning flag ; ; Driver dispatch table ; DDT$ DW,D$$W11,NEW=Y,OPT=Y ; Generate dispatch table ;+ ; ** - DWINI - Controller initiator ; ; This routine is entered from the queue I/O directive when an I/O request ; is queued and at the end of a previous I/O operation to propagate the ini- ; tion of the driver. If the specified controller is not busy, then an attempt ; is made to dequeue the next I/O request. Else a return to the caller is ; executed. If the dequeue attempt is successful, then the next I/O operation ; is initiated. A return to the caller is then executed. ; ; Inputs: ; ; R5=address of the UCB of the controller to be initiated. ; ; Outputs: ; ; If the specified controller is not busy and an I/O request is waiting ; to be processed, then the request is dequeued and the I/O operation ; is initiated. ;- .ENABL LSB DWINI: NOP ; OR BPT - CALL XDT - for debug only GTPKT$ DW,D$$W11 ; Get next i/o packet to process ; ; The following arguments are returned by $GTPKT: ; ; R1=address of the I/O request packet. ; R2=physical unit number of the request UCB. ; R3=controller index. ; R4=address of the status control block. ; R5=address of the UCB of the controller to be initiated. ; ; Controller I/O request packet format: ; ; WD. 00 -- I/O queue thread word. ; WD. 01 -- request priority, event flag number. ; WD. 02 -- address of the tcb of the requestor task. ; WD. 03 -- pointer to second lun word in requestor task header. ; WD. 04 -- contents of the first lun word in requestor task heade ; WD. 05 -- I/O function code (IO.RLB or IO.WLB). ; WD. 06 -- virtual address of I/O status block. ; WD. 07 -- relocation bias of I/O status block. ; WD. 10 -- I/O status block address (real or displacement + 14000 ; WD. 11 -- virtual address of AST service routine. ; WD. 12 -- relocation bias of buffer address ; WD. 13 -- buffer address of I/O transfer. ; WD. 14 -- number of bytes to be transfered. ; WD. 15 -- not used. ; WD. 16 -- cylinder ; WD. 17 -- sector in low and track in high byte of word ; WD. 20 -- relocation bias of diagnostic reg. adrs else not used ; WD. 21 -- diagnostic reg. blk adrs (real or displ.+140000) ; PATCH 5 CALL @RQCND ; Request controller for data transfer MOV S.VPKT(R4),R1 ; Retreive I/O packet address PKT1=.-2 MOV S.VKRB(R4),R3 ; Retrieve address of KRB KRB1=.-2 MOVB K.CON(R3),R3 ; Retrieve controller index CALL @VOLVD ; Validate volume valid BCS 50$ ; If CS we failed (JMP 200$ THRU 50$:) TST R0 ; Transfer function? BMI 10$ ; If MI yes TST I.PRM+2(R1) ; Size the disk? BPL 50$ ; If PL no (JMP 200$ THRU 50$:) MOV @S.VKRB(R4),R2 ; RETREIVE CSR ADDRESS KRB2=.-2 CALL DWWAIT ; MOV #IS.SUC&377, R0 CLR U.CNT(R5) JMP 220$ ; and exit 10$: ; Ref label PATCH 3 MOV #RETRY&377,RTTBL(R3) ; Clear recal flag and set retries CLC ; Convert ROR U.CNT(R5) ; to word count PATCH 5 CMPB #IO.HMS/^D<256>,I.FCN+1(R1) ; DIAGNOSTIC FUNCTION? BNE 40$ ; IF NE NO MOV #FUNTBL,R0 ; GET ADDRESS OF FUNCTION TABLE 20$: CMP (R0)+,I.FCN(R1) ; FUNCTION CODE MATCH? BEQ 30$ ; IF EQ YES TST (R0)+ ; BYPASS CONTROLLER CODE CMP #FUNTBE,R0 ; END OF FUNCTION TABLE? BEQ 40$ ; IF EQ YES BR 20$ ; TRY AGAIN 30$: MOV (R0),U.BUF(R5) ; SET CONTROLLER FUNCTION BITS BR 70$ ; GO CHECK LOGICAL BLOCK NUMBER 40$: MOV #IE.IFC&377,R0 ; ASSUME ILLEGAL FUNCTION MOV #READ,U.BUF(R5) ; ASSUME READ LOGICAL FUNCTION CMPB #IO.RLB/256.,I.FCN+1(R1) ; READ LOGICAL FUNCTION? BHIS 60$ ; IF HIS FUNCTION IS LEGAL 50$: JMP 200$ ; FUNCTION IS ILLEGAL 60$: BEQ 70$ ; IF EQ FUNCTION WAS READ ; CONVERT TO WRITE LOGICAL FUNCTION ADD #WRITE-READ, U.BUF(R5) 70$: PATCH 3 ; ; INITIATE i/o OPERATION ; DWLOOP: PATCH 5 MOV @S.VKRB(R4),R2 ; GET ADDRESS OF CSR KRB3=.-2 MOV S.VPKT(R4),R1 ; RETRIEVE ADDRESS OF I/O REQUEST PACKET PKT2=.-2 MOVB S.VITM(R4),S.VCTM(R4) ; SET CURRENT DEVICE TIMEOUT COUNT ITM1=.-4 CTM1=.-2 CALL DWWAIT ; MOV I.PRM+10(R1), DWCYL(R2) ; INSERT CYLINDER ADDRESS MOVB I.PRM+13(R1), DWTRK(R2) ; INSERT TRACK ADDRESS MOVB I.PRM+12(R1), R0 INC R0 BIC #^C<17>, R0 MOVB R0, DWSEC(R2) ; INSERT SECTOR ADDRESS CMP U.BUF(R5), #WRITE BNE 80$ MOV #360./4, DWPRE(R2) 80$: MOV U.BUF(R5), DWCSR2(R2) ; LOAD FUNCTION AND GO CMP U.BUF(R5), #WRITE BNE 90$ CALL LOAD 90$: CALL @BMSET BIS #ST.IE, (R2) BMI 100$ BIC #ST.IE, (R2) CALL @(SP)+ BR 110$ 100$: RETURN ;+ ; CANCEL i/o OPERATION IS A NOP FOR FILE STRUCTURED DEVICES. ;- DWCAN: ;;;NOP FOR DW ;+ ; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND ; CAUSES NO IMMEDIATE ACTION ON THE UNIT. ;- DWPWF: RETURN ;+ ; **-$DWINT-CONTROLLER INTERRUPTS ;- INTSE$ DW,PR4,D$$W11 ;;;SAVE REGISTERS AND SET PRIORITY PATCH 5 MOV U.SCB(R5),R4 ;;;GET ADDRESS OF SCB MOV @S.VKRB(R4),R4 ;;;GET ADDRESS OF CSR KRB4=.-2 BIC #ST.IE,(R4) ;;;CLEAR INTERRUPT ENABLE CALL @FORK ;;;CREATE A SYSTEM PROCESS PATCH 5 MOV R4,R2 ;COPY ADDRESS OF CSR MOV U.SCB(R5),R4 ;RETRIEVE ADDRESS OF SCB MOV S.VKRB(R4),R3 ;RETRIEVE ADDRESS OF KRB KRB5=.-2 MOVB K.CON(R3),R3 ;RETRIEVE CONTROLLER INDEX MOV S.VPKT(R4),R1 ;GET i/o PACKET ADDRESS PKT3=.-2 110$: MOV #IS.SUC&377,R0 ;ASSUME SUCCESSFUL TRANSFER BITB #IQ.UMD,I.FCN(R1) ;DIAGNOSTIC FUNCTION EXECUTED? BNE 220$ ;IF NE YES PATCH 5 BIT #S2.ERR, DWCSR2(R2) ; Any errors ? BEQ 150$ ; Branch, if no CALL @DVERR ; Log device error CALL FLUSH 120$: BITB #IQ.X,I.FCN(R1) ; Inhibit retries ? BNE 180$ ; Branch, if yes 130$: DECB RTTBL(R3) ; Any more retries ? BLE 180$ ; Branch, if no 140$: JMP DWLOOP ; Retry entire operation 150$: PATCH 5 BITB #IO.WLC&377,I.FCN(R1) ; Write followed by write check ? BNE 170$ ; Branch, if yes BITB #US.WCK,U.STS(R5) ; Write check enabled by MCR? BEQ 170$ ; Branch, if no 160$: CMPB U.BUF(R5), #WRITE ; Write function ? BNE 170$ ; Branch, if no ; BIS #2*2,U.BUF(R5) ; Set write check function ; BIT #2*2,R1 ; Was last function a write check ? ; BNE 170$ ; Branch, if yes ; MOV #RETRY&377,RTTBL(R3) ; Reinitialize retry count ; BR 140$ ; Start write check operation 170$: CMPB U.BUF(R5), #READ BNE 172$ CALL UNLOAD 172$: ADD #256.*2/100, I.PRM(R1) ; Adjust KISAR6 value SUB #256., U.CNT(R5) ; Yet one sector BHI 175$ ; Branch, if request not sutisfied CLR U.CNT(R5) ; All request BR 190$ 175$: PATCH 5 INCB I.PRM+12(R1) ; Next sector BICB #^C<17>, I.PRM+12(R1) ; Up to 16. sectors on track BNE 140$ ; Branch, if not sector #0 INCB I.PRM+13(R1) ; Next track BICB #^C<3>, I.PRM+13(R1) ; Up to 4. headers on cylinder BNE 140$ ; Branch, if not header #0 INC I.PRM+10(R1) ; Next cylinder BR 140$ 180$: MOV #IE.VER&377,R0 ;UNRECOVERABLE ERROR CLR R1 BR 200$ 190$: MOV I.PRM+4(R1), R1 CLC ROL U.CNT(R5) SUB U.CNT(R5), R1 ; CALCULATE BYTES ACTUALLY TRANSFERED 200$: MOVB RTTBL(R3),R2 ;GET FINAL ERROR RETRY COUNT BIS #RETRY*256.,R2 ;MERGE STARTING RETRY COUNT PATCH 2 CALL @RLCN ;RELEASE CONTROLLER CALL @IODON ;FINISH i/o OPERATION JMP DWINI ;PROCESS NEXT REQUEST ; ; DEVICE TIMEOUT RESULTS IN A HOME SEEK FOLLOWED BY THE i/o OPERATION ; BEING REPEATED UNLESS THE OPERATION WAS DIAGNOSTIC. TIMEOUTS ARE ; USUALLY CAUSED BY POWERFAILURE BUT MAY ALSO BE THE RESULT OF A ; HARDWARE FAILURE. ; DWOUT: INCB S.VSTS(R4) ;;;LEAVE CONTROLLER BUSY STS1=.-2 CALL @DTOER ;;;LOG DEVICE TIMEOUT BCC 230$ ;IF CC TIMEOUT DURING NORMAL FUNCTION 220$: CALL @CRPAS ; Pass controller registers to task BR 190$ ; Diagnostic processing complete 230$: MOV S.VPKT(R4),R1 ;GET i/o PACKET ADDRESS PKT4=.-2 BITB #IQ.X,I.FCN(R1) ;INHIBIT RETRIES? BNE 180$ ;IF NE YES BR 130$ ; .DSABL LSB ;+ ; ;- DWWAIT: PATCH 6 TST (R2) BMI DWWAIT RETURN ; ;+ ; ;- FLUSH: PATCH 4 TST DWRD(R2) BIT #S2.DRQ, DWCSR2(R2) BNE FLUSH RETURN ;+ ; R0 - ; R1 - I/O packet address ; R2 - CSR ; R3 - controller index ; R4 - SCB ; R5 - UCB ;- LOAD: PATCH 4 BIT #S2.DRQ, DWCSR2(R2) BEQ LOAD MOV R0, -(SP) MOV U.CNT(R5), R0 MOV R5, -(SP) ; for KISAR6 MOV R4, -(SP) MOV R3, -(SP) MOV KISR6, R5 MOV (R5), -(SP) MOV I.PRM(R1), (R5) MOV I.PRM+2(R1), R4 MOV #256., R3 10$: TST R0 BEQ 20$ MOV (R4)+, DWRD(R2) DEC R0 BR 30$ 20$: CLR DWRD(R2) 30$: SOB R3, 10$ BR COMM ;+ ; R0 - ; R1 - I/O packet address ; R2 - CSR ; R3 - controller index ; R4 - SCB ; R5 - UCB ;- UNLOAD: PATCH 4 BIT #S2.DRQ, DWCSR2(R2) BEQ UNLOAD MOV R0, -(SP) MOV U.CNT(R5), R0 MOV R5, -(SP) ; for KISAR6 MOV R4, -(SP) MOV R3, -(SP) MOV KISR6, R5 MOV (R5), -(SP) MOV I.PRM(R1), (R5) MOV I.PRM+2(R1), R4 MOV #256., R3 10$: TST R0 BEQ 20$ MOV DWRD(R2), (R4)+ DEC R0 BR 30$ 20$: TST DWRD(R2) 30$: SOB R3, 10$ COMM: MOV (SP)+, (R5) MOV (SP)+, R3 MOV (SP)+, R4 MOV (SP)+, R5 MOV (SP)+, R0 RETURN ;+ ; **-DWCHK-VALIDATE AND CONVERT THE LBN ; ; THIS ROUTINE IS CALLED FROM $DRQRQ TO DO LBN PROCESSING ; FOR DEVICES WHICH SUPPORT QUEUE OPTIMIZATION. IF BLKC2 ; DETECTS AN ERROR IT WILL RETURN TO THE CORRECT PLACE IN ; $DRQRQ AFTER CALLING $IOALT. ; ; INPUTS: ; ; R1=i/o PACKET ADDRESS ; R5=ucb ADDRESS ; ; OUTPUTS: ; ; IF THE CHECKS SUCCEEDS, THEN THE LBN IN THE PACKET ; IS REPLACED BY THE CYLINDER/TRACK/SECTOR. R1 IS PRESERVED. ; ; IF THE CHECKS FAILS, THEN $IOALT IS ENTERED WITH A FINAL ; STATUS OF IE.BLK AND A RETURN TO THE CORRECT PLACE IN ; $DRQRQ IS EXECUTED. ; ; ; NOTE: ALL FUNCTIONS PUT INTO THE DRIVER QUEUE ARRIVE HERE. ; THESE INCLUDE IO.ATT, IO.DET, AND ACP FUNCTIONS. ;- DWCHK: PATCH 5 MOV I.FCN(R1),-(SP) ;PUT THE FUNCTION ONTO THE STACK CMPB #IO.ATT/256.,1(SP) ;IS IT ATTACH BEQ 20$ ;IF EQ YES - LEAVE IT ALONE CMPB #IO.DET/256.,1(SP) ;IS IT DETACH BEQ 20$ ;IF EQ YES - LEAVE IT ALONE BIC #7,(SP) ;CLEAR THE SUBFUNCTION BITS CMP #IO.STC,(SP) ;IS IT SET CHARACTERISTICS? BEQ 20$ ;IF EQ YES - LEAVE IT ALONE TST (SP)+ ;CLEAN THE STACK CALL @BLKC2 ;CHECK LOGICAL BLOCK NUMBER CALL @CVLBN ;CONVERT LOGICAL BLOCK NUMBER SWAB R1 ;SWAP TRACK TO HIGH BYTE BIS R1,R0 ;MERGE TRACK WITH SECTOR MOV R0,I.PRM+12(R3) ;SAVE DESIRED TRACK AND SECTOR ADDRESS MOV R2,I.PRM+10(R3) ;SAVE DESIRED CYLINDER ADDRESS MOV R3,R1 ;RESTORE THE PACKET ADDRESS 10$: RETURN ;EXIT 20$: TST (SP)+ ;CLEAN THE STACK BR 10$ ;AND EXIT .IF DF R$$MPL DWKRB: BCS 20$ ; Off-line request - done TST EXEVEC ; If done already BNE 20$ ; Skip this PATCH 5 MOV R2,-(SP) ; Save R2 MOV R3,-(SP) ; and R3 MOV @#KINAR6,-(SP) ; and mapping APR6 MOV @#112,R0 ; Get address of table of entries MOV (R0),R0 ; Get address of APR bias (first word) MOV (R0),@#KINAR6 ; Map common through APR6 MOV #EXEVEC,R3 ; Point to vector MOV #EXEVCL,R2 ; Specify length of vector CALL @#140004 ; Translate vector MOV (SP)+,@#KINAR6 ; Restore mapping MOV (SP)+,R3 ; And R3 MOV (SP)+,R2 ; And R2 MOV #SCBPAT,R0 ; Get patch table address 10$: MOV (R0)+,R1 ; Move table entry BEQ 20$ ; If EQ - end of table MOV @(R0)+,(R1) ; If NEQ - start to patch BR 10$ ; Complete it 20$: RETURN DWUCB: RETURN PATCH 40 .ENDC ;DF R$$MPL .END