Trailing-Edge
-
PDP-10 Archives
-
bb-jr93j-bb
-
7,6/ap023/dpxkon.x23
There is 1 other file named dpxkon.x23 in the archive. Click here to see a list.
TITLE DPXKON - DEVICE DEPENDENT RP10/RP01(RP02) DRIVER V137
SUBTTL T WACHS/TH 25 APR 89
SEARCH F,S,DEVPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1973,1988>
XP VDPKON,137 ;DEFINE VERSION FOR GLOB AND MAP
DPXKON::ENTRY DPXKON
BSYBIT==20 ;DP KONTROL BUSY
STPBIT==20 ;STOP DP (CLEAR BUSY, SET DONE CAUSE INTERRUPT)
ALLERR==177720
DPCLR==177710
DPATTN==776
STATBT==176 ;READY, ONLINE, UNSAFE,NO SUCH DEV, RD ONLY
STATB2==174 ;ALL EXECPT READ ONLY
UNSAFE==10 ;FILE UNSAFE
SEKINC==100
ENDCYL==200000
SRCHER==40000
CORPAR==12 ;CHAN-DETECTED CORE PARITY ERROR BITS
NXMERR==10000 ;CHAN-DETECTED NXM
DLERR==20000 ;DATA LATE (OVER RUN)
DPDONE==10
PARDIS==5000 ;DISABLE STOP ON PAR ERROR
;EXTRA BITS IN DPXFNC
FNCRCL==20 ;FREE RECALIBRATE
FNCPOS==10 ;FREE POSITION
FNCHNG==100 ;HUNG RECOVERY
SUBTTL AUTOCONFIGURATION
DPFIX==0 ;NOT A FIXED HEAD DEVICE (IF 0)
DPOFS==400000 ;NO OFFSET CAPABILITY
DPRDC==400000 ;NO 10/11 COMPATABILITY MODE
DPUNL==400000 ;NO UNLOAD CAPABILITY
DPCPY==KOPIDL ;KONTROLLER MUST BE IDLE TO DETERMINE UNIT TYPE
DPMX==0 ;CANNOT DO MULTIPLE TRANSFERS
DPDRB==0 ;DOESN'T USE DISK I/O REQUEST BLOCKS
DPBMX==0 ;NOT A BLOCK MULTIPLEX KONTROLLER
DPECA==0 ;TRY OFFSET/RECAL BEFORE TRYING ECC
DPERNO==0 ;NO DRIVE REGISTERS TO SAVE ON ERROR
DPXELG==DPEELG## ;ERROR LOG ROUTINE IS IN COMMOD
DPXDMX==10 ;MAXIMUM DRIVES PER KONTROLLER
DPXHDN==DPXDMX-1 ;HIGHEST DRIVE NUMBER ON KONTROLLER
;DRIVER CHARACTERISTICS
; DPX = DPXCNF
; DSK = DISK
; 0 = MAXIMUM DEVICES IN SYSTEM (NO LIMIT)
; TYPDP = KONTROLLER TYPE
; DPXDMX = MAXIMUM DRIVES PER KONTROLLER
; DPXHDN = HIGHEST DRIVE NUMBER ON KONTROLLER
; MDSEC0 = SECTION FOR KDB/UDB
; MDSEC0 = SECTION FOR DDB
DRVCHR (DPX,DSK,0,TYPDP,DPXDMX,DPXHDN,MDSEC0,MDSEC0,<DR.MCD>)
.ORG KONUDB ;START OF KONTROLLER SPECIFIC DATA
DPXUTB:!BLOCK DPXDMX ;UDB TABLE
DPXEBK:!BLOCK 1 ;DUMMY WORD FOR REGISTER STORAGE
DPXIOB:! ;START OF SPECIAL I/O INSTRUCTIONS
DPXCO1:!BLOCK 1
DPXDOT:!BLOCK 1
DPXDO1:!BLOCK 1
DPXDI1:!BLOCK 1
DPXCIT:!BLOCK 1
DPXCI2:!BLOCK 1
DPXDI3:!BLOCK 1
DPXIOE:! ;END OF SPECIAL I/O INSTRUCTIONS
DPXFNC:!BLOCK 1 ;INITIAL FUNCTION CODE (SET TO BE POSITION
; IN CASE THE OPERATOR CAUSES INTERRUPT
; BEFORE DISK PACKS ARE EVER USED BY SYSTEM
DPXIWD:!BLOCK 1
DPXIUM:! BLOCK DPXDMW ;IGNORE DRIVE MASK
DPXNUM:! BLOCK DPXDMW ;NEW DRIVE MASK
DPXKLN:! ;LENGTH OF KDB
.ORG
;PROTOTYPE KDB
DPXKDB: XXKON (DP)
SETWRD (DPXCO1,<CONO 000,(T2)>)
SETWRD (DPXDOT,<DATAO 000,T1>)
SETWRD (DPXDO1,<DATAO 000,T2>)
SETWRD (DPXDI1,<DATAI 000,T2>)
SETWRD (DPXCIT,<CONI 000,T1>)
SETWRD (DPXCI2,<CONI 000,T2>)
SETWRD (DPXDI3,<DATAI 000,T3>)
SETWRD (DPXFNC,<EXP OPPOS>) ;INITIAL FUNCTION CODE
KDBEND
EQUATE (LOCAL,0,<DPXULP,DPXULB>)
EQUATE (LOCAL,CPOPJ##,<DPXEDL,DPXINI,DPXRLD>)
DPXCCM==CYLCM##
DPXICD==DSKICD## ;PROTOTYPE INTERRUPT CODE
DPXICL==DSKICL##
DPXUDB==0 ;NO PROTOTYPE UDB
DPXULN==UNIEBK+DPERNO ;LENGTH OF UDB
DPXDSP: DRVDSP (DPX,DSKCHN##,DSKDDB##,DDBLEN##,DSKDIA##)
;DEFAULT MONGEN'ED DEVICE TABLE
DEFMDT: MDKL10 (7,250,0,0,<MD.KON>) ;DEVICE CODE 250
MDKL10 (7,254,0,0,<MD.KON>) ;DEVICE CODE 254
MDKL10 (7,260,0,0,<MD.KON>) ;DEVICE CODE 260
MDTERM ;TERMINATE TABLE
DPXCKT: EXP 0 ;COMPATIBLE KONTROLLER TABLE
DPXCFG: XMOVEI T1,DPXMDT## ;MONGEN'ED DEVICE TABLE
XMOVEI T2,DEFMDT ;DEFAULT TABLE
MOVNI T3,1 ;NO MASSBUS UNIT OR DRIVE INFORMATION
MOVEI T4,MD.KON ;MATCH ON KONTROLLER DEFINITION
PUSHJ P,AUTMDT## ;SCAN THE TABLES
JRST CPOPJ1## ;NO MATCHES
PUSHJ P,SAVE1## ;SAVE P1
MOVSI T1,0 ;I/O BUS-STYLE CHANNEL
PUSHJ P,AUTCHN## ;BUILD A CHANNEL DATA BLOCK
POPJ P, ;NO CORE
MOVNI T1,1 ;NO MASSBUS UNIT NUMBER
MOVEI T2,TYPDP ;KONTROLLER TYPE
PUSHJ P,DSKKON## ;BUILD A KDB
POPJ P, ;GIVE UP IF NO CORE
MOVSI T1,-<DPXIOE-DPXIOB> ;NUMBER OF WORDS TO CHECK
XMOVEI T2,DPXIOB(J) ;STARTING WORD
HRRZ T3,.CPDVC## ;<DEVICE CODE>/4
PUSHJ P,AUTDVC## ;SET DEVICE CODES
MOVE T1,KDBCSO(J) ;GET CONSO SKIP CHAIN ADDRESS
;***NEED SYMBOL (DONE)
MOVEI T2,10 ;AND INTERRUPT FLAGS
HRRM T2,DICDIF##(T1) ;SET THEM
MOVSI P1,-1 ;NO MASSBUS UNIT,,DRIVE 0
DPXCF1: PUSHJ P,DPXDRV ;AUTOCONFIGURE A SINGLE DRIVE
JFCL ;IGNORE ERRORS
HRRZ T1,P1 ;GET DRIVE NUMBER
CAIGE T1,DPXDMX-1 ;DONE ALL DRIVES?
AOJA P1,DPXCF1 ;LOOP BACK FOR MORE
JRST CPOPJ1## ;TRY ANOTHER DEVICE ON CHANNEL
;CONFIGURE A SINGLE DRIVE
DPXDRV: HRRZ T1,P1 ;GET UNIT
MOVE T1,BITTBL##(T1) ;AND IT'S BIT
TDNE T1,DPXIUM(J) ;WANT TO IGNORE THIS DRIVE?
POPJ P, ;SAY IT DOESN'T EXIST
XMOVEI T1,DPXMDT## ;MONGEN'ED DEVICE TABLE
XMOVEI T2,DEFMDT ;AND THE DEFAULT TABLE
MOVE T3,P1 ;DRIVE INFORMATION
PUSHJ P,AUTMDT## ;FOUND A DRIVE MATCH?
POPJ P, ;NO
HRLZ T1,P1 ;PHYSICAL DRIVE NUMBER
HRR T1,P1 ;UDB TABLE INDEX
MOVEI T2,TYPDP ;FLAGS,,UNIT TYPE
PUSHJ P,DSKDRV## ;BUILD A UDB
JFCL ;FAILED
JRST CPOPJ1## ;RETURN
;ONCE A SECOND CODE
DPXSEC: SKIPL @KDBCHN(J) ;CHANNEL BUSY?
POPJ P, ;LEAVE IT ALONE
SKIPE T1,DPXNUM(J) ;GET BIT MASK
JFFO T1,DPXSE1 ;FIND FIRST UNIT NUMBER
HRRZS KDBNUM(J) ;INDICATE NO DRIVES TO CONFIGURE
POPJ P, ;DONE
DPXSE1: PUSHJ P,AUTLOK## ;GET AUTCON INTERLOCK
POPJ P, ;TRY AGAIN NEXT TIME
PUSHJ P,SAVW## ;PRESERVE W
MOVE W,J ;COPY KDB ADDRESS TO W FOR AUTCON
PUSH P,T2 ;SAVE PHYSICAL DRIVE NUMBER
MOVE T1,KDBDVC(J) ;DEVICE CODE
XMOVEI T2,DPXDSP ;DISPATCH
MOVE T3,KDBCHN(J) ;CHANNEL DATA BLOCK
PUSHJ P,AUTSET## ;SET UP CPU VARIABLES
EXCH P1,(P) ;SAVE P1, PHYSICAL DRIVE NUMBER
TLO P1,-1 ;NO MASSBUS UNIT
PUSH P,KDBUNI(J) ;SAVE KDBUNI
MOVEM P1,KDBUNI(J) ;SET FOR THIS MASSBUS UNIT NUMBER (FOR RDMBR)
PUSHJ P,DPXDRV ;CONFIGURE A NEW UNIT
JFCL ;IGNORE ERRORS
PUSHJ P,AUTULK## ;RELEASE AUTCON INTERLOCK
POP P,KDBUNI(J) ;RESTORE KDBUNI
PJRST P1POPJ## ;RESTORE P1 AND RETURN
DPXWTF: MOVEI T4,OPWTF ;WRITE FORMAT (HEADERS)
JRST DPXGO
DPXRDC:
DPXRDF:
DPXRED: TDZA T4,T4 ;OP=0(READ)
DPXWTC:
DPXWRT: MOVEI T4,OPWRT
JRST DPXGO ;START MOVING DATA
DPXRDS: TDZA T4,T4 ;OP=0(READ)
DPXWTS: MOVEI T4,OPWRT
HRLI T4,1 ;LH=1 - STOP ON ERR
DPXGO: PUSHJ P,KONECT ;CONNECT RP10 TO DRIVE, SET UP T1
JRST DPXDWN ;ERROR - UNIT NOT READY
MOVE T2,@KDBICP(J) ;LOC OF FIRST IOWD
MOVE T2,(T2) ;INITIAL IOWD ITSELF
MOVEM T2,DPXIWD(J) ;SAVE IN CONTROL DATA BLOCK
DPXGO1: LDB T4,UNYBPT## ;T3 HAS SURFACE*SECTOR
IDIV T3,T4 ;T3=SURF T4=SECTOR
DPB T3,[POINT 5,T1,18] ;STORE SURFACE
DPB T4,[POINT 4,T1,23] ;STORE SECTOR
OR T1,KDBICP(J) ;INITIAL KON WD ADDR
DPXGO2: TRZE T1,1 ;SEEK INC?
JRST RECAL2 ;YES
SETZM T2 ;TURN OFF RP10 PI CHANNEL
XCT DPXCO1(J) ;CONO DPN,(T2)
POP P,DPXFNC(J) ;SAVE FUNCTION (CAN'T GET INTERRUPTED
; NOW TILL DATA TRANSFER IS DONE)
XCT DPXDOT(J) ;START THE OPERATION
MOVEI T2,DSKCHN## ;TURN PI CHANNEL BACK ON
XCT DPXCO1(J)
JRST CPOPJ1## ;GIVE GOOD (SKIP) RETURN TO FILSER
DPXPOS: HRROI T4,OPPOS ;FUNCTION=POSITION, DISABLE PARITY STOP
JRST DPXRC1 ;CONNECT TO UNIT AND DO POSITIONING
DPXRCL: MOVEI T4,OPCAL ;FUNCTION=RECALIBRATE
DPXRC1: PUSHJ P,KONECT ;CONECT TO DRIVE, SET UP T1
JRST DPXDWN ;ERROR - UNIT NOT READY
JRST DPXGO2 ;START RP10 GOING (FUNCTION ON END OF PD LIST)
DPXUNL:
DPXERR:
DPXECC: STOPCD CPOPJ1##,DEBUG,RIF, ;++RP10 ISNT FANCY
DPXREG: POPJ P, ;NO MASSBUS REGS TO READ
;HERE WHEN A UNIT IS NOT READY. (ERROR BITS FOR T1 IN T3)
;SINCE IT MAY BECOME READY BEFORE THE CONTROLLER IS USED AGAIN, AND IF IT
; DOES WE WILL GET A FREE INTERRUPT, DPXFNC MUST BE RESET SO THAT WE WONT
; TELL FILSER ABOUT A SPURIOUS DATA INTERRUPT
DPXDWN: MOVEI T1,OPPOS ;SET UP A "POSITION" FUNCTION
MOVEM T1,DPXFNC(J) ;IN THE KONTROLLER DATA DBLOCK
IOR T1,T3 ;ADD ERROR BITS
MOVEI T2,DSKCHN## ;ENSURE THAT RP10 HAS A PIA
XCT DPXCO1(J) ; (IN CASE OF POWER FAIL RECOVERY)
XCT DPXCI2(J) ;COMI BITS INTO T2
XCT DPXDI3(J) ;DATAI BITS INTO T3
POPJ P, ;GIVE NON-SKIP RETURN TO FILSER
;SUBROUTINE TO CONNECT RP10 TO A UNIT, FUNCTION IN T4
;RETURNS CPOPJ IF CANT CONNECT OR WRITE-PROTECTED ON A WRITE REQUEST
; WITH HARDWARE FUNCTION (DATAO) IN T1 ERROR BITS IN T3
;CPOPJ1 NORMALLY, FUNCTION ON END OF PD LIST, FUNCTION STILL IN T4
KONECT: XCT DPXCIT(J) ;CONI DPN,T1
TRNN T1,BSYBIT ;BUSY?
JRST KONEC1 ;NO
MOVEI T2,STPBIT ;YES. CLEAR BUSY, SET DONE
XCT DPXCO1(J)
AOS UNIHNG(U) ;COUNT THE ERROR IN UNIHNG
JRST KONECT ;TRY, TRY AGAIN
KONEC1: PUSHJ P,CLRSET ;CONNECT TO DRIVE, DATAI T2 (SIM ERROR)
CAIN T4,OPWTF ;IF TRYING TO FORMAT,
TLNN T2,1 ;WRITE-HEADER LOCKOUT MUST BE OFF
TLNE T2,STATBT ;UNIT OK?
JRST KONERX ;NO - CHECK WRITE LOCK
KONEC2: DPB T4,[POINT 3,T1,2];YES. SET OPERATION IN T1
TLNN T4,1 ;STOP ON ERROR?
TRO T1,PARDIS ;NO, DISABLE STOP ON ERROR
EXCH T4,(P) ;SAVE FUNCTION ON PD LIST
;(CAN'T DO A MOVEM DPXFNC SINCE
;WE MIGHT GET A POSITION INTERRUPT
;BEFORE THE DATA-TRANSFER STARTS)
MOVE T2,UNIBLK(U) ;DESIRED BLOCK
LDB T3,UNYBPY## ;NUMBER OF BLOCKS/CYLINDER
IDIV T2,T3 ;CYLINDER IN T2
DPB T2,[POINT 8,T1,13] ;SAVE IN T1
TRNE T2,400 ;EXTRA BIT IN CYLINDER NUMBER (RP03)?
TRO T1,200000 ;YES SET BIT IN DATAO WORD
MOVEM T2,UNICYL(U) ;SAVE CYLINDER IN UNIT DB
PJRST 1(T4)
KONERX: TLNN T2,STATB2 ;WAS THE STATUS "ERROR" WRITE LOCK?
TRNE T4,1 ;YES. IS THE OPERATION A WRITE?
TDZA T3,T3 ;NO-CLEAR POPJ ERROR BITS
JRST KONEC2 ;READ-ONLY IS OK
TLNE T2,SEKINC
JRST KONER2
TLNE T2,70 ;NOT-READY, FILE UNSAFE, OR OFF-LINE?
TRO T3,KOPOFL ;YES-LIGHT BIT FOR FILSER
TLNE T2,UNSAFE ;FILE UNSAFE
TRO T3,KOPFUS ;YES, LIGHT BIT FOR FILSER
POPJ P, ;ERROR STATUS
;HERE ON SEEK INCOMPLETE
KONER2: TRO T1,1 ;IDICATE SEEK INCOMPLETE
JRST KONEC2 ;AND CONTINUE
;ROUTINE TO COMPUTE LATENCY TIME FOR A UNIT LESS A SAFETY FACTOR
; TO INSURE THAT A COMPLETE REVOLUTION WILL NOT BE MISSED
; 0 FOR AN ANSWER MEANS CLOSEST POSSIBLE NEXT BLOCK
REPEAT 0,<
TABLE SHOWING INSTANEOUS TIME RELATION BETWEEN SECTOR COUNTER
AND ACTUAL SECTOR POSITION FOR RPO2 AND RP01 UNITS:
SECTOR COUNTER: 20
!19!! 0! 1! 2! 3! 4! 5! 6! 7! 8! 9!10!11!12!13!14!15!16!17!18!19!
RP02: ! 9 ! 0 ! 1 ! 2 ! 3 ! 4 ! 5 ! 6 ! 7 ! 8 !
RP01: ! 4 ! 0 ! 1 ! 2 ! 3 !
>
DPXLTM: MOVE T2,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
ROT T2,-6 ;SHIFT TO UNITS POSITION FOR DATAO
TLO T2,<OPSEL>B20 ;SET OPERATION TO SELECT
XCT DPXDO1(J) ;DO A DATAO DPX,T2 TO SELECT UNIT
XCT DPXDI1(J) ;DO A DATAI DPX,T2 TO READ SECTOR COUNTER
XCT DPXDI1(J) ;READ A SECOND TIME SINCE COUNTER IS
; STROBBED INTO BUFFER ON TRAILING EDGE OF DATAI
TLC T2,60 ;COMPLEMENT ON-LINE,ON-CYL
TLNE T2,60 ;ON-LINE AND ON-CYL?
POPJ P, ;NO, ERROR RETURN, T1=UNSPECIFIED
LDB T4,[POINT 4,T2,22] ;GET ACTUAL HALF SECTOR COUNTER
LDB T3,UNYBPT## ;NO. OF BLOCKS PER TRACK(REVOLUTION)
IDIVI T1,(T3) ;T2 GETS DESIRED SECTOR NO.(RP02=0-9;RP01=0-4)
LSH T2,1 ;CONVERT TO HALF SECTOR LIKE HARDWARE
CAIE T3,^D10 ;IS THIS AN RP02?
ADDI T2,2(T2) ;NO, MUST BE RP01, CONVERT TO QUARTER SECTOR
; PLUS 2
SUB T2,T4 ;DESIRED HALF SECTOR - MOD20(ACTUAL HALF SECT+2)
; GIVES NO. OF HALF(QUART) SECTORS TO WAIT
; TO GET TO DESIRED HALF(QUART) SECTOR(-20 THRU +20)
HRREI T1,0(T2) ;MOVE NO. OF HALF SECTORS TO WAIT
; SINCE HARDWARE CONVENIENTLY HAS A BUILT
; IN SAFETY FACTOR, NO NEED TO SUBTRACT
; ANYTHING HERE.
JUMPGE T1,DPXLT1 ;IF DISTANCE IS NEGATIVE
ADDI T1,^D20 ;ADD NO. OF HALF SECTORS IN ONE REVOLUTION
; SINCE DISK SPINS IN ONE DIRECTION
DPXLT1: IMULI T1,^D1250 ;CONVERT HALF SECTORS TO MICROSECONDS
JRST CPOPJ1## ;AND GIVE GOOD RETURN
;HERE WHEN A UNIT HANGS DURING A TRANSFER (IE DOES NOT INTERRUPT)
;ATTEMPT TO CLEAR CONTROL AND CAUSE AN INTERRUPT
DPXSTP: XCT DPXDI1(J) ;READ IN UNIT STATUS OF LAST UNIT CONTROLLER
; CONNECTED TO, THE ONE TRANSFERRING (DATAI DPX,T2)
MOVE T3,T2 ;SAVE IN T3 FOR RETURN
XCT DPXCIT(J) ;READ CONTROL STATUS (CONI DPX,T1)
PUSH P,T1 ;SAVE ON STACK
MOVEI T2,STPBIT ;STOP THE UNIT BIT
XCT DPXCO1(J) ;STOP UNIT AND CLEAR PI (SO NO INT.)
XCT DPXCIT(J) ;READ STATUS (CONI DPX,T1)
TRNN T1,BSYBIT ;IS BUSY FLAG NOW OFF?
AOS -1(P) ;YES; SET SUCCESSFUL RETURN
MOVEI T2,FNCHNG ;INDICATE HUNG-RECOVERY
IORM T2,DPXFNC(J) ; INTERRUPT
MOVEI T2,DSKCHN## ;PI FOR THIS KONTROLLER
XCT DPXCO1(J) ;RESTORE PI AND GET INTERRUPT (CONO DPX,T2)
PJRST T2POPJ## ;RETURN PREVIOUS CONI STATUS IN T2
;OK OR ERROR RETURN
;CHECK IF KONTROL IS ALIVE
DPXALV: XCT DPXCIT(J) ;CONI
TRNE T1,7 ;IS IT ALIVE?
POPJ P,
MOVEI T2,DSKCHN## ;NO. GIVE IT A PI
XCT DPXCO1(J)
POPJ P, ;AND RETURN
;HERE FROM COMMON ON AN INTERRUPT
;ACS HAVE BEEN SAVED, J AND P SET UP
DPXINT: XCT DPXCIT(J) ;CONI DPN,T1
PUSH P,T1 ;SAVE CONI BITS
MOVE U,KONCUA(J) ;UNIT DATA BLOC LOC
HRRZ S,DPXFNC(J) ;S=FUNCTION
TRZE S,FNCHNG ;HUNG RECOVERY?
JRST DEVERR ;YES, RETURN AN ERROR
TRNE S,74 ;POSITIONING INTERRUPT?
JRST POSINT ;YES
TRNE T1,ALLERR ;ERROR?
JRST ERROR ;TOO BAD
TRNN T1,ENDCYL ;DATA INTERRUPT. END OF CYLINDER?
JRST DATAIN ;NO
;HERE ON END-OF-CYLINDER
MOVE F,KDBICP(J) ;INITIAL KONTROL WORD ADDRESS
HLRZ T1,1(F) ;LOC(LAST IOWD)+1
SUBI T1,1 ;R=LOC OF LAST IOWD
HRRZ T2,(T1) ;INITIAL ADDR. OF LAST IOWD
HRRZ T3,1(F) ;NO - LOC. OF LAST DATA WORD
SUBI T3,1(T2) ;# OF WORDS TRANSFERRED
CAIG T3,2 ;WAS THIS IOWD STARTED?
JRST ERROR ;NO - END CYLINDER WAS FROM PREVIOUS IOWD
TRNE S,1 ;OP = WRITE?
SUBI T3,2 ;YES. CHAN STORE IS 2 TOO HIGH
TRNN T3,177 ;EVEN NUMBER OF BLOCKS MOVED?
JRST ERROR ;NO. POSSIBLE CHANNEL ERROR
;HERE ON A POSSIBLE CHANNEL ERROR. THE WORDCOUNT COMPUTATION GAVE A "FUNNY" COUNT,
; WITH END OF CYLINDER. THIS IS POSSIBLE IF IT IS THE LAST IOWD,
; AND END OF CYLINDER CAME UP ON THE LAST WORD XFERRED
TRNE S,1 ;WRITING?
ADDI T3,2 ;YES. ADD BACK THE 2 WORDS
HLRE T4,(T1) ;-WDCNT OF LAST IOWD
TRNE T4,177 ;NOT EVEN MULTIPLE OF 200 WORDS?
TRNE T3,176 ;YES, 200 OR 201 WORDS COMPUTED?
JRST ENDTS1 ;NO
JRST ERROR ;YES, REAL END OF CYLINDER
ENDTS1: ADD T3,T4 ;+NO OF WORDS XFERRED (-1?)
SKIPN 1(T1) ;LAST IOWD?
AOJE T3,DATAIN ;YES. OK IF T3=-1
MOVE T1,(P) ;RESTORE CONI BITS FOR DEVERR
JRST DEVERR ;NO. CHANNEL ERROR (WRONG WORDCOUNT)
;HERE WHEN ALL DATA IS IN CORE
DATAIN: XCT DPXDI1(J) ;DATAI DPN,T2
LSH T2,-^D15 ;SHIFT DRIVE NUMBER
HLLM T2,S ;SAVE DRIVE IN LH(S)
DATIN1: MOVEI T3,OPPOS ;SET FUNCTION=POSITION, SO ON NEXT
MOVEM T3,DPXFNC(J) ; INTERRUPT WE DONT TELL FILSER ABOUT THIS DATA
XCT DPXDI1(J) ;DATAI DPN,T2
CLRATN: MOVE T3,T2 ;SAVE DATAI WORD
ANDI T2,DPATTN ;GET ATTENTION BITS
JUMPE T2,INTXIT ;THROUGH IF NONE
HRLI T2,<OPCLR>B20 ;SET TO CLEAR ATTENTIONS
XCT DPXDO1(J) ;DATAO DPN,T2 - CLEAR ATTNS
LSH T2,^D27 ;POSITION ATTNS IN LH
ORM T2,S ;SAVE IN S
INTXIT: MOVEI T2,DSKCHN##+DPCLR ;SET TO CLEAR THE RP10
XCT DPXCO1(J) ;CLEAR ALL BUT PI ASSIGNMENTS
MOVE T1,S ;RETURN TO FILSER WITH T1 =
;BITS 0-7 = ATTENTIONS
;BITS 15-17 = DRIVE NUMBER(IF DATA INTERRUPT)
;BITS 18-23 = ERROR INDICATION
;BITS 33-35 = FUNCTION
POP P,T2 ;T2 = CONI BITS
PJRST FILINT## ;RETURN TO FILSER
;HERE ON A POSITIONING INTERRUPT
POSINT: XCT DPXDI1(J) ;DATAI DPN,T2
TRNN S,70 ;SPECIAL INTERRUPT?
;(RECALIBRATE OR FREE POSITIONING)
JRST CLRATN ;NO. SET ATTNS IN LH AND GO TO FILSER
MOVN T1,UDBPDN(U) ;U=SPECIAL NUMBER
;SET TO COMPUTE RIGHT ATTN BIT
MOVEI T3,400
LSH T3,(T1) ;T3= ATTN BIT WHICH SHOULD BE ON
TDNN T2,T3 ;IS IT FOR "SPECIAL" UNIT?
JRST POSIN3 ;NO. DON'T WORRY ABOUT IT
MOVE T4,DPXFNC(J)
TRNN T4,OPPOS
JRST POSIN1
TLNE T2,SEKINC
JRST DEVERR
JRST POSIN3
POSIN1: TLO T3,<OPCLR>B20 ;YES. CLEAR THIS ATTN
MOVE T1,T3 ;(LEAVE THE OTHER ATTNS FOR LATER)
XCT DPXDOT(J) ;DATAO DPN,T1
TRZN T4,10 ;FREE POSITION?
JRST POSIN2 ;NO. MUST BE FROM RECALIBRATE
TLNE T2,SEKINC
JRST POSIN4
MOVE T1,UDBPDN(U) ;GET PHYSICAL DRIVE NUMBER
ROT T1,-6 ;POSITION TO DRIVE FIELD
POP P,T2 ;PD LIST HAS CONI BITS - REMOVE IT
SOS (P) ;DPXGO1 WILL EXIT CPOPJ1
PUSHJ P,KONEC2 ;SET UP FOR DATA IO COMMAND
STOPCD .+1,DEBUG,KDS, ;++KONEC2 DIDN'T SKIP
PJRST DPXGO1 ;START NEW DATA COMMAND AND EXIT THE INTERRUPT
;WAS A RECALIBRATE INTERRUPT FOR SELECTED DRIVE
POSIN2: TRZ T4,20 ;RESET RECALIBRATE BIT
MOVEM T4,DPXFNC(J) ;SAVE IN FUNCTION
MOVE T1,UNICYL(U) ;GET DESIRED CYLINDER
MOVE T2,UDBPDN(U) ;GET PHYSICAL DRIVE NUMBER
LSH T1,^D22 ;POSITION NEW CYLINDER ADDRESS
TLZE T1,10000 ;EXTENDED CYLINDER NUMBER (RP03)?
TRO T1,200000 ;YES, SET EXTENDED BIT
DPB T2,[POINT 3,T1,5] ;SET UP DRIVE NUMBER
TLO T1,<OPPOS>B20 ;POSITION TO IT
MOVEI T2,10 ;INDICATE "FREE" POSITIONING
ORM T2,DPXFNC(J)
XCT DPXDOT(J) ;DATAO DPN,T1
JRST TPOPJ## ;AND EXIT THE INTERRUPT
;HERE WHEN "WRONG" ATTENTION BIT IS UP
POSIN3: MOVEI S,OPPOS ;JUST A POSITIONING INTERRUPT
JRST CLRATN ;GO CLEAR THE ATTENTION AND TELL FILSER
;HERE ON SEEK INCOMPLETE AFTER FREE POSITION
POSIN4: TRC S,IODERR+10 ;TURN ON IODERR, TURN OFF 10
MOVS T2,UDBPDN(U) ;PHYSICAL DRIVE NUMBER IN LH (T2)
JRST DATIN1 ;GO TELL FILSER
ERROR: TLNN T1,CORPAR ;NO, CORE PARITY ERROR?
TRNE T1,NXMERR!DLERR ;NO. NXM OR DATA LATE?
JRST REF ;YES. REFRENCE THE LOC
CHANER: TLNE T1,DATBTS ;DATA ERROR (PARITY)?
TROA S,IODTER ;DATA ERROR
DEVERR: TRO S,IODERR ;YES
TRNE T1,SRCHER ;SEARCH ERROR (HEADERS)?
TRO S,IOHDER ;YES
JRST DATAIN ;LOOK AT ATTNS AND GO TO FILSER
;HERE ON SEEK-INCOMPLETE
RECAL2: TLO T1,<OPCAL>B20 ;RECALIBRATE TO BRING DRIVE TO LIFE
XCT DPXDOT(J)
POP P,T1 ;FUNCTION
TRO T1,20 ;INDICATE RECALIBRATE
MOVEM T1,DPXFNC(J)
PJRST CPOPJ1## ;AND TELL FILSER ALL'S OK
DATBTS=5
ERRBTS=143720
REF: TRNN T1,NXMERR!DLERR ;CHAN - DETECTED ERROR
TROA S,IOCHMP!IODERR ;CORE PARITY ERR
TRO S,IOCHNX!IODERR ;NXM OR DATA LATE
TRNE T1,DLERR ;DATA LATE (=OVERRUN)?
TRO S,IOVRUN ;YES
JRST CHANER ;SET IODERR AND CONTINUE
;SUBROUTINE TO GET STATUS OF A UNIT
; ENTER WITH U=UNIT DATA BLOCK ADR. J=KONTROLLER DATA BLOCK ADR.
; RETURN WITH T2=UNIT STATUS FROM DATAI, GOOD-BITS ARE COMPLEMENTED
; SO ERRORS CAN BE CHECKED EASILY
DPXSTS: MOVEI T2,DPCLR ;ENTRY TO CLEAR CONO
XCT DPXCO1(J) ;DO THE CONO TO RP10
CLRSET: MOVE T1,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
ROT T1,-6 ;POSITION TO DRIVE FIELD
TLO T1,<OPSEL>B20 ;SET OPERATION = NOP
TLC T1,10000 ;FIRST CONNECT TO ANOTHER DRIVE
XCT DPXDOT(J) ;SO THAT RECONNECTING TO RIGHT
TLC T1,10000 ;DRIVE WILL GIVE GOOD STATUS INFORMATION
XCT DPXDOT(J) ;DATAO DPN,T1
XCT DPXDI1(J) ;DATAI DPN,T2
TLC T2,60 ;INVERT BITS WHICH SHOULD BE 1
POPJ P, ;AND EXIT
;HERE TO CHECK CAPACITY & STATUS OF A UNIT
DPXCPY: PUSHJ P,DPXSTS ;GET STATUS OF OF THIS UNIT IN T2
PUSH P,T2 ;SAVE STATUS
MOVSI T4,KOPUHE ;ASSUME ERRORS
TLO T4,KOPNSU ;ALSO SUCH UNIT
TLNE T2,4 ;DOES NOT EXIST
JRST DPXCP3 ;NO, GIVE DON'T ASK QUESTION RETURN
SETZ T4, ;ASSUME UNIT IS UP
SKIPN DINITF## ;IN ONCE-ONLY?
JRST DPXCP3 ;NO, ASSUME CONTROLLER IS UP
TLCN T2,60 ;UNIT ON CYLINDER & ON-LINE?
TLNE T2,110 ;YES - SEEK INCOMPLETE,FILE UNSAFE
TLO T4,KOPUHE ;YES - INDICATE UNIT HAD ERROR
LDB T2,[POINT 11,T2,10] ;GET DRIVE & CYLINDER # FOR DATAO
TLO T2,417400 ;(10,,370000)_^D14 - SELECT AN ILLEGAL SECTOR
ROT T2,-^D14 ;SHIFT INTO CORRECT POSITION FOR DATAO
OR T2,KDBICP(J)
XCT DPXDO1(J) ;DO A DATAO DPX,T2
MOVEI T2,^D1000 ;LOOP 1000 TIMES
DPXCP1: XCT DPXCIT(J) ;DO A CONI DPX,T1
TRNE T1,DPDONE ;DONE YET?
JRST DPXCP2 ;YES
SOJG T2,DPXCP1 ;NO, LOOP
MOVSI T4,KOPNSU ;UNIT DOESN'T EXIST
JRST DPXCP3 ;CONTROLLER IS DEAD
DPXCP2: TRNN T1,200 ;ILLEGAL SECTOR?
TLO T4,KOPUHE ;NO - SOMETHING'S AMISS!
DPXCP3: MOVEI T2,DSKCHN##
XCT DPXCO1(J) ;GIVE RP10 A PI
XCT DPXCIT(J) ;CONI DP'N,T1
SKIPN DINITF## ;IF ATTACH COMMAND,
TRNE T1,7 ;IF THE CONTROLLER ISN'T THERE,
CAIA
JRST T2POPJ## ;NEITHER IS THE UNIT
POP P,T2 ;RESTORE UNIT STATUS TO T2
TRNE T2,2000 ;SKIP IF UNIT NOT RP03
JRST DPXCP4 ;IS RP03, SET UP
MOVEI T1,^D40000 ;# BLOCKS ON UNIT (RP02)
MOVEI T2,^D40600 ;# BLOCKS INCLUDING MAINT CYLS
HRRI T4,1 ;RETURN RP02 TYPE CODE
JRST DPXCP5 ;TEST IF UNIT UP AND RETURN
;HERE IF UNIT IS RP03
DPXCP4: MOVEI T1,^D80000 ;# BLOCKS (RP03)
MOVEI T2,^D81200 ;# BLOCKS INCLUDING MAINT CYLS
HRRI T4,2 ;RETURN RP03 TYPE CODE
DPXCP5: SETZ T3, ;NO 10/11 COMPATABILITY MODE
MOVE W,[^D10,,^D200] ;BLKS PER TRK,,BLKS PER CYL
TLNN T4,KOPUHE ;UNIT UP?
AOS (P) ;YES, SKIP-RETURN
IFN FTDUAL,<
HRRZS J ;NO SERIAL NUMBER
>
POPJ P, ;RETURN TO CALLER
$INIT
;CHECK FOR KONTROLLER UP
DPXUPA: PUSHJ P,SAVE2## ;SAVE P1-P2
MOVEI T2,DPCLR+DSKCHN## ;CLEAR ALL ERROR FLAGS
XCT DPXCO1(J) ;DO THE CONO
MOVE T1,[XWD 500000,DPATTN]
XCT DPXDOT(J)
XCT DPXCIT(J)
TRNE T1,7 ;CONTROLLER ON-LINE?
TRNE T1,175770 ;YES. TEST ALL BUT DISK NRDY
POPJ P,
XCT DPXDI1(J) ;DATAI DP'N, T2
TLNN T2,1 ;WRITE-HEADER LOCKOUT ON?
SETZ T1, ;NO, SO INDICATE
JRST CPOPJ1##
;CHECK HARDWARE WRITE PROTECT
DPXHWP: PUSHJ P,DPXSTS ;GET STATUS FOR THIS UNIT IN T2
TLNE T2,2 ;WRITE PROTECT ON?
AOS (P) ;YES -SKIP
POPJ P, ;RETURN
$HIGH
LIT
DPXEND: END