Trailing-Edge
-
PDP-10 Archives
-
bb-pbdea-bb
-
10,7/unsmon/dsxkon.mac
There are 4 other files named dsxkon.mac in the archive. Click here to see a list.
TITLE DSXKON - CONTROLLER ROUTINE FOR 3330/3331 DISK - V7
SUBTTL JOSEPH A. DZIEDZIC/JAD (DEC) & JEFF GUNTER/JEG (ADP) 25-APR-89
;OLD AUTHORS - CYPHERNETICS CORPORATION 18-MAR-76
SEARCH F, S, DEVPRM, SAXPRM
$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 1987,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1987,1988>
XP VDSXKN,7 ;VERSION NUMBER FOR GLOB AND MAP
DSXKON::ENTRY DSXKON
EXTERN SAXSER ;FORCE LOAD OF SERVICE ROUTINES
;MISCELLANEY UNTIL ELSEWHERE
.UT330==0
.UT331==1
;COMPUTE SIZE OF CHANNEL PROGRAM FROM CYLINDER SIZE (342) BLOCKS
;TIMES THE SIZE OF A WRITE (4 WORDS+2 DATA=6 WORDS) + 25% (BECAUSE 1 BLOCK
;OUT OF EVERY PAGE MIGHT REQUIRE A SPLIT IOWD)
;PLUS THE OVERHEAD OF A SEEK COMMAND, A SET-SECTOR COMMAND, AND THEIR ARGS
;(2 SEEK+2DATA+2 SECTOR+1DATA=7 WORDS)+A HALT
CPAOVR==10 ;SEEK,IOWD,DATA(2); SECTOR,IOWD,DATA; HALT
CPAWRT==^D342*6 ;ENOUGH TO WRITE 342 BLOCKS
CPASPL==^D342/4+1 ; INCASE EVERY PAGE (IE: EVERY 4TH BLOCK) IS SPLIT
CPALEN==CPAOVR+CPAWRT+CPASPL+1 ;ENOUGH FOR MAXIMUM SIZED PROGRAM+A HALT
BLKBYT==<BLKSIZ##/2>*^D9 ;SIZE OF A DISK BLOCK IN BYTES (9 PER TWO WORDS)
DSXMAX==2 ;MAX NUMBER OF CONSECUTIVE ERRORS ON A SINGLE BLOK#
;BYTE POINTERS
DSYDLO: POINT SASDLO,T1,SANDLO ;BYTE PTR TO STORE OPCODE IN DEVLST
DSYDLC: POINT SASDLC,T1,SANDLC ;POINTER TO ADDRESS FIELD
DSYDLD: POINT SASDLD,T1,SANDLD ;POINTER TO DEVICE-ADDRESS FIELD
DEFINE SIOW(LEN,ADR),<<-^D'LEN'>B11> ;GENERATE BYTE MODE "LAST" IOWD
SUBTTL DEVICE-DEPENDENT DEFINITIONS
;3330 DEVICE COMMANDS
O.RCL==23 ;RECALIBRATE
O.NOP==03 ;NO-OP
O.SEK==07 ;SEEK
O.SEC==43 ;SET SECTOR
O.SIE==61 ;SEARCH ID EQUAL
O.RED==06 ;READ
O.MTR==206 ;MULTI-TRACK READ
O.WRT==05 ;WRITE
O.SNS==04 ;SENSE I/O
O.RR0==26 ;READ-RECORD-0
;THE FOLLOWING ARE NOT REALLY SENSE BITS, BUT ARE SET FOR SYSERR IN ERROR STATUS
SN.CDE==1B35 ;CHANNEL DETECTED ERROR (ERROR BUT NO SENSE)
SN.RTR==1B34 ;RETRY REQUESTED BY CHANNEL
SN.HNR==1B33 ;HUNG DISK RECOVERY - ASSUME ERROR
SN.COE==1B32 ;ERROR CORRECTED WITH ECC (ACTUAL NONZERO DATA FIELD CORRECTION)
SUBTTL AUTOCONFIGURATION TABLES
SUBTTL DEFINITIONS
;PARAMETERS TO CONTROL XXKON MACRO:
DSFIX==0 ;NOT A FIXED-HEAD DEVICE
DSOFS==400000 ;NO OFFSET CAPABILITY
DSRDC==400000 ;NO 10/11 COMPATABILITY MODE
DSUNL==400000 ;NO UNLOAD CAPABILITY
DSCPY==0 ;CAN TELL UNIT TYPE EVEN IF KONTROLLER BUSY
DSMX==0 ;CANNOT DO MULTIPLE TRANSFERS
DSDRB==KOPDRB ;USES DISK I/O REQUEST BLOCKS
DSBMX==KOPBMX ;IS A BLOCK MULTIPLEX KONTROLLER
DSECA==KOPECA ;KONTROLLER CAN HANDLE ECC FIRST
DSERNO==0 ;NO DRIVE REGISTERS TO SAVE ON ERROR
DSXELG==DPEELG## ;ERROR LOG ROUTINE IS IN COMMOD
DSXDMX==MAXUNS ;MAX DRIVES/KONTROLLER
DSXHDN==DSXDMX-1 ;HIGHEST DRIVE NUMBER
;DRIVER CHARACTERISTICS
; DSX = DSXCNF
; DSK = DISK
; TYPDS = KONTROLLER TYPE
; DSXDMX = MAXIMUM DRIVES PER KONTROLLER
; DSXHDN = HIGHEST DRIVE NUMBER
; MDSEC0 = SECTION FOR KDB/UDB
; MDSEC0 = SECTION FOR DDB
DRVCHR (DSX,DSK,0,TYPDS,DSXDMX,DSXHDN,MDSEC0,MDSEC0,<DR.MCD!DR.UCK!DR.UCU>)
SUBTTL KDB EXTENSIONS
.ORG KONUDB ;START OF 3330/3331 SPECIFIC DATA
DSXUTB:!BLOCK DSXDMX ;TABLE OF POINTERS TO UDBS
DSXEBK:!BLOCK 1 ;DUMMY ERROR BLOCK
DSXBUC:!BLOCK 1 ;COUNT OF BUSY UNITS RIGHT NOW
DSXBSY:!BLOCK 1 ;COUNT OF ABSOLUTE BUSYS SEEN
DSXIUU:!BLOCK 1 ;INTERRUPT UNKNOWN UNIT
DSXSUI:!BLOCK 1 ;SPURIOUS UNIT INTERRUPTS
DSXSCH:!BLOCK 1 ;LH = SA10 SUBCHANNEL IN CONO POSITION
;RH = SA10 SUBCHANNEL NUMBER
DSXGSN:!BLOCK 1 ;GLOBAL SUBCHANNEL NUMBER
DSXICW:!BLOCK 1 ;BASE ADDR FOR SUBCHANNEL THIS KONTROLLER IS ON
DSXCSW:!BLOCK 1 ;CHANNEL STATUS WORD ADDR FOR THIS KONTROLLER
DSXDVP:!BLOCK 1 ;POINT TO DEVICE LIST FOR UNIT 0
DSXPTR:!BLOCK 1 ;USED TO PICK UP UNIT DATA BLOCK ADDRESS
; GIVEN PHYSICAL UNIT NUMBER IN T3 (@ USED)
DSXIOB:! ;BEGINNING OF I/O INSTRUCTIONS IN KDB
DSXCO2:!BLOCK 1 ;CONO (T2)
DSXCI2:!BLOCK 1 ;CONI T2
DSXDTI:!BLOCK 1 ;DATAI T1
DSXIOE:! ;END OF I/O INSTRUCTIONS IN KDB
DSXIUM:! BLOCK DSXDMW ;IGNORE DRIVE MASK
DSXNUM:! BLOCK DSXDMW ;NEW DRIVE MASK
DSXKLN:! ;LENGTH OF KDB
.ORG
;PROTOTYPE KDB
DSXKDB: XXKON (DS)
SETWRD (DSXCO2,<CONO 000,(T2)>)
SETWRD (DSXCI2,<CONI 000,T2>)
SETWRD (DSXDTI,<DATAI 000,T1>)
SETWRD (DSXPTR,<DSXUTB(T3)>)
KDBEND
SUBTTL UDB EXTENSIONS
.ORG UNIEBK ;FOLLOW THE JUNK
UNIRCL:!BLOCK 1 ;RECALIBRATE PROTOTYPE
UNISEK:!BLOCK 1 ;SEEK-CMD PROTOTYPE
UNINOP:!BLOCK 1 ;PROTOTYPE NOP COMES AFTER SEEK
BLOCK 1 ;...HALT AFTER NOP
UNISS:! BLOCK 1 ;SET-SECTOR-CMD PROTOTYPE
UNISIE:!BLOCK 1 ;SEARCH ID EQUALS PROTOTYPE
UNISNC:!BLOCK 1 ;SENSE-I/O COMMAND PROTOTYPE
BLOCK 1 ;SENSE-I/O IOWD
BLOCK 1 ;SENSE-I/O HALT
UNIRWC:!BLOCK 1 ;PROTOTYPE DVW FOR CHANNEL PROGRAMS
UNIRR0:!BLOCK 1 ;PROTOTYPE READ-RECORD-0
UNISND:!BLOCK SNSLEN ;SENSE DATA
UNIR0D:!BLOCK 2 ;R0 DATA, 8 BYTES
UNIFNC:!BLOCK 1 ;(RH) FILSER FUNCTION LAST ATTEMPTED
UNPSNS==1 ;(LH) BIT SET IF DOING SENSE I/O
UNPBSY==2 ; BIT SET IF GOT BUSY RESPONSE FOR UNIT
UNPHNS==4 ; BIT SET IF SET GO FLAG AFTER HUNG DISK
UNPONP==20 ; BIT SET IF POSITIONING FOR UNIT COMING ON-LINE
UNPCPY==40 ; BIT SET IF IN CPY ROUTINE FOR ATT CMD
UNPCPD==400000 ;(SIGN) BIT SET IF CPY ROUTINE DONE
UNIDRB:!BLOCK 1 ;ADDRESS OF DRB FOR THIS UNIT
UNIBBK:!BLOCK 1 ;"BAD BLOK" - LAST LBN COMPUTED BY DSXSNS
UNIRTC:!BLOCK 1 ;NUMBER OF RETRIES INVESTED IN THIS OPERATION
UNICSW:!BLOCK 1 ;SAVED COPY OF SACSW FOR DEBUGGING
UNIECW:!BLOCK 1 ;TEMP COPY OF SATCA FROM LAST INTERRUPT
UNITCA:!BLOCK 1 ;SAVED COPY OF SATCA FROM BEFORE SENSE COMMAND
UNICBN:!BLOCK 1 ;CURRENT BLOCK NUMBER (USED WHILE BUILDING PROGRAM)
UNILPC:!BLOCK 1 ;PHYSICAL PC OF FAILING XFER CMD
UNIDVL:!BLOCK 1 ;SAVED COPY OF DEVICE LIST ENTRY WHEN SET UP
UNIDVP:!BLOCK 1 ;POINTER TO DEVICE LIST ENTRY FOR THIS UNIT
UNIPCP:!BLOCK 1 ;PHYSICAL ADDRESS OF CHANNEL PROGRAM
UNITCP:!BLOCK 1 ;POINTER TO NEXT WORD IN CHANNEL PROGRAM
UNISDA:!BLOCK 1 ;PHYSICAL ADDRESS OF SEARCH-ID DATA BUFFER
UNISUI:!BLOCK 1 ;SPURIOUS UNIT INTERRUPTS
;THE NEXT 5 WORDS ARE USED DURING ATTACH/KONCPY CALL
UNICCF:!BLOCK 1 ;"ComCon Flag" NONZERO IF ATTACH CMD IN PROGRESS
UNICAD:!BLOCK 1 ;"Continue ADdress" where to go at next DSXINT time
UNIACP:!BLOCK 1 ;"Attach Channel Program" pointer to chan program
UNIPRU:!BLOCK 1 ;COPY OF BLKPRU DATA FOR THIS DRIVE
UNITYP:!BLOCK 1 ;FLAGS,,UNIT TYPE FOR ATTACH
DSXULN:!
.ORG
;PROTOTYPE DEVICE-COMMANDS KEPT IN UDB, DSXUNI FILLS IN DEVICE-ADDRESS
DSXUDB: UDBBEG (UNI,DSXULN)
SETWRD (UNIRCL,<F.XEC!F.CC!F.NMT!<O.RCL>B15>) ;RE-CALIBRATE
SETWRD (UNISEK,<F.XEC!F.CC!F.BYTE!<O.SEK>B15>) ;SEEK Z,Z,C,C,H
SETWRD (UNINOP,<F.XEC!F.CC!F.NMT!<O.NOP>B15>) ;NO-OP
SETWRD (UNINOP+1,BMXEND) ;HALT FOR NO-OP
SETWRD (UNISS, <F.XEC!F.CC!F.BYTE!<O.SEC>B15>) ;SET-SECTOR S
SETWRD (UNISIE,<F.XEC!F.CC!F.BYTE!<O.SIE>B15>) ;SEARCH-ID C,C,H,H,R
SETWRD (UNISNC,<F.XEC!F.CC!F.BYTE!<O.SNS>B15>) ;SENSE-I/O 24 BYTES DATA
SETWRD (UNISNC+2,BMXEND) ;END OF SENSE PROGRAM
SETWRD (UNIRWC,<F.XEC!F.CC!F.SLI!<O.MTR>B15>) ;MULTI-TRAK READ
SETWRD (UNIRR0,<F.XEC!F.CC!F.SLI!F.BYTE!<O.RR0>B15>) ;READ-RECORD-0
UDBEND
SUBTTL DRIVER DISPATCH TABLE
EQUATE (LOCAL,0,<DSXICD,DSXICL,DSXULP,DSXULB>)
EQUATE (LOCAL,CPOPJ##,<DSXINI,DSXRLD,DSXEDL>)
DSXATK==ATTKON## ;ATTACH DISK KONTROLLER
DSXDTK==DETKON## ;DETACH DISK KONTROLLER
DSXCCM==CYLCM##
DSXDSP::DRVDSP (DSX,DSKCHN##,DSKDDB##,DDBLEN##,DSKDIA##)
;DEFAULT MONGEN'ED DEVICE TABLE
DEFMDT: MDKL10 (7,274,0,0,<MD.KON>) ;SA10 DEVICE CODE 274
MDKL10 (7,270,0,0,<MD.KON>) ;SA10 DEVICE CODE 270
MDTERM ;TERMINATE TABLE
DSXCKT: EXP TYPDS, 0 ;COMPATIBLE KONTROLLER TABLE
SAXDSP (DSX)
SUBTTL START DRIVE POSITIONING
;ROUTINE TO CAUSE THE DRIVE TO DO A RECALIBRATE OPERATION.
;CALL:
; J/KDB ADDRESS
; U/UDB ADDRESS
; PUSHJ P,DSXRCL
;RETURN CPOPJ IF ERROR
; CPOPJ1 WITH RECAL STARTED
DSXRCL: SETZ T1, ;NO DRB HERE
MOVEI T4,OPCAL ;RE-CAL REQUEST
PJRST DSXGO ;START IT AND RETURN
;ROUTINE TO START A POSITION OPERATION GOING.
;CALL WITH UNIBLK(U) CONTAINING THE DESIRED BLOCK NUMBER.
;CALL:
; J/KDB ADDRESS
; U/UDB ADDRESS
; PUSHJ P,DSXPOS
;RETURN CPOPJ IF ERRORS
; CPOPJ1 WITH POSITION STARTED
DSXPOS: SETZ T1, ;NO DRB
MOVEI T4,OPPOS ;POSITION REQUEST
JRST DSXGO ;FINISH REQUEST
;ROUTINE TO CHECK FOR AND DO ECC CORRECTION
;CALLED FROM FILIO WITH:
; J/KDB ADDRESS
; U/UDB ADDRESS
; PUSHJ P,DSXECC
;ALWAYS RETURNS CPOPJ (=ECC NOT POSSIBLE) BECAUSE WE NEVER SET IOECCX
DSXECC: POPJ P, ;WON'T EVER GET HERE
;ROUTINE TO UPDATE THE RE-START PC FOR AN ECC ERROR
XXXECC: PUSHJ P,YYYECC ;GO DO THE CORRECTION
POPJ P, ;PASS BACK THE ERROR
XXXEC1: AOS UNILPC(U) ;POINT AT NEXT IOWD
PMOVE T2,UNILPC(U) ;GET AN IOWD
JUMPG T2,XXXEC1 ;BRANCH IF MORE IOWDS TO SKIP
AOS UNILPC(U) ;STEP TO FIRST UNDONE COMMAND
POPJ P, ;RETURN
;ROUTINE TO DO AN ECC CORRECTION ON THE LAST BLOK XFERED
YYYECC: PUSHJ P,SAVE4## ;SAVE SOME ACS
LDB T1,[POINTR (UNISND+S07WRD(U),D07FMC)] ;GET FORMAT/MESSAGE CODE
CAIE T1,FMCECC ;SKIP IF ECC IS POSSIBLE AND APPLIES TO DATA
PJRST CPOPJ1## ;EXIT IF ECC ERROR IS NOT IN THE DATA PART
LDB T1,[POINTR (UNISND+S15WRD(U),D15RD1)] ;GET 1ST BYTE OF RESTART
LDB P1,[POINTR (UNISND+S16WRD(U),D16RD2)] ;GET REST OF RESTART DISP
LSH T1,^D16 ;POSITION HIGH BYTE
IOR P1,T1 ;COMBINE TO GET RESTART-DISPLACEMENT IN P1
CAIE P1,BLKBYT ;SKIP IF #BYTES IS EXACTLY THAT FOR 200 WORDS
POPJ P, ;GIVE ERROR RETURN IF BLOCK SIZE ISN'T NORMAL
LDB P2,[POINTR (UNISND+S16WRD(U),D16ERD)] ;P2=ERROR DISPLACEMENT
CAILE P2,BLKBYT+3 ;SKIP IF ERROR BYTES ARE WITHIN DATA BYTES
JRST CPOPJ1## ;EXIT IF ERROR IS OUTSIDE DATA ERROR - WE WIN
LSH P1,1 ;P1=RESTART NIBBLES
LSH P2,1 ;P2=ERROR NIBBLES
SUB P1,P2 ;NOW P1=FORWARD NIBBLES
MOVEI P3,6 ;6 NIBBLES = 3 BYTES = #BYTES IN ERROR PATTERN
CAIGE P2,6 ;SKIP IF ALL PATTERN NIBBLES ARE SIGNIFICANT
MOVE P3,P2 ;...ELSE REDUCE # OF PATTERN NIBBLES TO USE
MOVE P4,[POINT 4,UNISND+S20WRD(U)] ;POINT AT PATTERN NIBBLES
DSXEC1: ILDB P2,P4 ;GET A CORRECTION NIBBLE
SKIPE P2 ;SKIP IF NO CHANGE REQUIRED
PUSHJ P,FIXNIB ;GO AND FIX A NIBBLE
JUMPL P3,CPOPJ## ;BRANCH IF WE FOUND AN XFER'ED NIBBLE NEEDING
;CORRECTING, BUT IT FALLS IN THE TRUNCATED AREA
SOJG P3,[AOJA P1,DSXEC1] ;LOOP FOR ALL NIBBLES NEEDING FIXING
JRST CPOPJ1## ;THEN GIVE IT GOOD RETURN
;ROUTINE APPLY ECC ERROR CORRECTION TO A SINGLE NIBBLE
; P1/ NIBBLE NUMBER NEEDING NEXT CORRECTION
; P2/ CORRECTION NIBBLE
; P3/ NUMBER OF REMAINING NIBBLES NEEDING CORRECTION
; P4/ BYTE POINTER TO PATTERN NIBBLES
FIXNIB: PUSHJ P,NIBSET ;SETUP T3=PHYSICAL ADDRESS, T4=NIBBLE INDEX
POPJ P, ;...RETURN IF NIBBLE # NOT IN IOWD LIST (?)
MOVE T1,UNISND+S23WRD(U) ;GET TRUNCATION BYTE
TDNE T1,[D23CHT] ;SKIP IF NOT TRUNCATED BY CHANNEL
JRST [SETO P3, ;***UGH - BUT PASS BACK ERROR
POPJ P,0] ;***GIVE ERROR RETURN
PMOVE T1,T3 ;GET WHOLE WORD
ROT P2,@NIBTAB(T4) ;POSITION THE CORRECTION DATA
XOR T1,P2 ;CORRECT THE BROKEN NIBBLE
PMOVEM T1,T3 ;RESTORE THE CORRECTED WORD
POPJ P, ;RETURN
NIBTAB: EXP ^D32,^D28,^D24,^D20,^D16,^D12,^D8,^D4,^D0 ;1ST WORD
EXP ^D0,^D32,^D28,^D24,^D20,^D16,^D12,^D8,^D4 ;2ND WORD
;N.B.: THE LAYOUT OF NIBBLES COMING FROM THE DISK INTO MEMORY IS AS FOLLOWS:
;
; 0/ BYTE(4)0,1,2,3,4,5,6,7,8 ;1st 8 NIBBLES GO INTO 1ST WORD
; 1/ BYTE(4)10,11,12,13,14,15,16,17,9 ;9th NIBBLE IS LOW 4 BITS!
;
;NOTE: THAT 1ST 8 NIBBLES GO DIRECTLY INTO FIRST 8 MEMORY NIBBLES,
; BUT THAT 9TH NIBBLE GOES INTO LOW ORDER MEMORY NIBBLE OF NEXT WORD,
; LEAVING THE REMAINING 8 NIBBLES TO GO LEFT JUSTIFIED INTO 2ND WORD.
;(WHY DOESN'T DISK USE "NATURAL MODE" ?)
;ROUTINE TO CALCULATE PHYSICAL ADDRESS OF A NIBBLE GIVEN:
;
; P1/ NIBBLE NUMBER NEEDING CORRECTION
; UNILPC(U) ;POINTER TO CMD,IOWD LIST IN 4 1/2 PACKED MODE
NIBSET: PUSHJ P,SAVE2## ;SAVE P1, P2
IDIVI P1,^D9 ;COMPUTE P1=WORD#, P2=NIBBLE INDEX
TRNE P1,1 ;SKIP IF EVEN WORD OF PAIR
ADDI P2,^D9 ;P2=NIBBLE INDEX BASED ON A WORD PAIR, 0-17
SETZ T1, ;T1=# WORDS SO FAR
MOVE T2,UNILPC(U) ;T2=POINTER TO CMD
ADDI T2,1 ;NOW T2=POINTER TO IOWD LIST
NIBSE1: PMOVE T3,T2 ;GET AN IOWD
MOVE T4,T3 ;SAVE A COPY
TLO T3,(1B0) ;MAKE SURE IT APPEARS -VE
ASH T3,-^D24 ;NOW T3=-VE WORDS IN THIS IOWD
MOVNS T3 ;NOW T3=+VE WORDS IN THIS IOWD
SUB P1,T3 ;COMPUTE P1=# WORDS REMAINING TO BE SKIPPED
JUMPL P1,NIBSE2 ;BRANCH IF WE FINALLY FOUND RELAVENT IOWD
JUMPG T4,[AOJA T2,NIBSE1] ;LOOP FOR NEXT IOWD, IF THERE IS ONE
POPJ P, ;GIVE ERROR RETURN IF NOT THERE
;HERE WHEN WE FIND THE RELAVENT IOWD
NIBSE2: ADD P1,T3 ;NOW P1=# WORDS INTO THIS IOWD
LDB T3,[POINT 22,T4,35] ;LOAD T3=BASE ADDRESS OF THIS IOWD
ADD T3,P1 ;COMPUTE AFFLICTED ADDRESS
MOVE T4,P2 ;LOAD UP NIBBLE NUMBER
JRST CPOPJ1## ;GIVE GOOD RETURN IF WE FIND IOWD
SUBTTL START DATA TRANSFERS
;ROUTINES TO START A DATA TRANSFER GOING ON A DRIVE. ENTRY POINTS
;ARE:
; DSXRED - READ DATA, DON'T STOP ON ERROR
; DSXRDS - READ DATA, STOP ON ERROR
; DSXRDF - READ FORMAT
; DSXWRT - WRITE DATA, DON'T STOP ON ERROR
; DSXWTS - WRITE DATA, STOP ON ERROR
; DSXWTF - WRITE FORMAT
;CALL:
; J/KDB ADDRESS
; U/UDB ADDRESS
; T1/ DRB ADDRESS
; P1/CHANNEL DATA BLOCK ADDRESS
; PUSHJ P,ROUTINE
;RETURN CPOPJ IF ERRORS WITH:
; T1/ERROR BITS
; CPOPJ1 IF TRANSFER STARTED SUCCESSFULLY
;HERE TO START TRANSFER TO READ/WRITE FORMATS.
DSXRDF:
DSXWTF: SETZ T1, ;CAN'T DO FORMATTING YET
POPJ P, ;BAD UNIT RETURN
;HERE TO START TRANSFER TO READ/WRITE DATA, NOT STOPPING ON ERRORS.
DSXRED: SKIPA T4,[OPRED] ;GET FILSER READ FUNCTION
DSXWRT: MOVEI T4,OPWRT ;GET FILSER WRITE FUNCTION
JRST DSXGO ;START THE I/O
;HERE TO START TRANSFER TO READ/WRITE DATA, STOPPING ON ERRORS.
DSXRDS: SKIPA T4,[OPRED] ;GET FILSER READ FUNCTION
DSXWTS: MOVEI T4,OPWRT ;GET FILSER WRITE FUNCTION
JRST DSXGO ;START THE I/O
;HERE TO START ALL OPERATIONS GOING
DSXGO: MOVEM T1,UNIDRB(U) ;SAVE DRB, IF ANY
SETZM UNIRTC(U) ;# RETRIES FOR THIS LOGICAL OPERATION
SETOM UNIBBK(U) ;LAST BLOK THAT HAD AN ERROR
DSXGO0: PUSHJ P,SETCHP ;SET UP CHANNEL PROGRAM
POPJ P, ;GIVE ERROR RETURN, T1=KOPXXX BITS
DSXGO1: PUSHJ P,SETGOB ;SET GO BIT
MOVE T1,UNIDRB(U) ;RESTORE DRB, IF ANY
PJRST CPOPJ1## ;GIVE OK (SKIP) RETURN
;HERE TO RE-START AN INTERRUPTED XFER
DSXRGO: MOVE T1,UNIDRB(U) ;GET DRB, IF ANY
JUMPN T1,DSXRG1 ;BRANCH IF DRB, (IE: IF XFER)
;HERE TO RE-START A CHANNEL PROGRAM WITH NO (FURTHER) CHANGE
DSXRG0: PUSHJ P,SETDVP ;RESET DEVL SLOT, ETC
PJRST SETGOB ;SET GO BIT AND EXIT
;HERE TO RE-START A TRANSFER
DSXRG1: SKIPN DRBGOD(T1) ;SKIP IF SOME GOOD BLOKS
JRST DSXRG0 ;BRANCH IF NOTHING GOOD AT ALL
PUSHJ P,SETTCP ;SETUP PROGRAM POINTERS
MOVE T1,UNIBBK(U) ;GET THE OFFENDING BLOCK'S LBN + 1
MOVEM T1,UNICBN(U) ;SAVE AS CURRENT BLOCK #
PUSHJ P,STOSEK ;STORE SEEK
PUSHJ P,STOSS ;STORE SET-SECTOR
PUSHJ P,STOSID ;STORE SEARCH-ID-EQUAL
MOVE T1,UNILPC(U) ;GET PC OF OFFENDING XFER CMD
TDO T1,[TIC] ;MAKE A TIC
PUSHJ P,STODVC ;INSERT A TIC TO THE GOOD PART
PJRST DSXRG0 ;JOIN CODE TO START XFER
;HERE TO DO FUNCTION RELATED CONO SET/CLEAR
CNOSET: TRO T2,SO.SET ;SET BIT TO SET THE DESIRED FLAG
CNOCLR: HLRZ T1,DSXSCH(J) ;GET SUBCHANNEL NUMBER IN CONO POSITION
IORI T2,DSKCHN##(T1) ;INCLUDE PI CHANNEL AND SUBCHANNEL NUMBER
XCT DSXCO2(J) ;DO THE CONO
POPJ P, ;RETURN
SUBTTL STOP TRANSFER FOR HUNG RECOVERY
;ROUTINE TO STOP THE CURRENT TRANSFER WHEN THE HUNG TIMER TIMES
;OUT.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,DSXSTP
;RETURN CPOPJ IF COULDN'T GET BUSY TO CLEAR
; CPOPJ1 IF SUCCESSFUL
;SUBROUTINE TO STOP DEVICE FOR ERROR RECOVERY
DSXSTP: MOVSI T1,UNPHNS ;GET HUNG-RECOVERY-IN-PROGRESS BIT
TDNE T1,UNIFNC(U) ;SKIP IF 1ST HUNG SINCE LAST GOOD OPERATION
JRST DSXST1 ;BRANCH IF 2ND (OR WORSE) TO RESET SA10 CHANNEL.
IORM T1,UNIFNC(U) ;REMEMBER WE'RE NOW IN HUNG-RECOVERY
PUSHJ P,SETDVR ;SETUP TO RUN LAST PROGRAM AGAIN
AOS (P) ;GIVE SKIP RETURN
PJRST DSXST4 ;SET GO FLAG, RETURN PROPER AC'S
;HERE WHEN SET GO FLAG AND TIMED OUT AGAIN IN HUNG RECOVERY
DSXST1: PMOVE T1,UNIDVP(U) ;GET DEVICE LIST ENTRY
PUSH P,T1 ;SAVE CURRENT DEVICE LIST ENTRY
MOVEI T2,UNINOP(U) ;POINT AT NULL NO-OP PROGRAM
PUSHJ P,SETDVL ;SET UP FOR THAT
MOVE T3,UNIFNC(U) ;RETURN UNIFNC AS DATAI WORD
POP P,T2 ;RESTORE PREVIOUS DEVICE LIST ENTRY
PMOVE T1,UNIDVP(U) ;GET CURRENT DEVICE LIST ENTRY
CAME T1,T2 ;SKIP IF DIDN'T CHANGE SINCE LAST TRY
JRST DSXST4 ;OK
DSXST2: STOPCD .+1,DEBUG,SAH, ;++ SA10 HUNG
MOVEI T2,SO.RCH ;FUNCTION TO RESET SUBCHANNEL
PUSHJ P,CNOCLR ;DO IT - SHOULD GET SA10 STARTED AGAIN
PUSHJ P,SETDVP ;TRY TO RE-RUN THE OPERATION'S CHANNEL PROGRAM
DSXST4: PUSHJ P,SETGOB ;SET GO FLAG FOR THIS SUBCHANNEL
MOVE T2,UNISND(U) ;T2="CONI"=FIRST SENSE BYTES
MOVE T3,@DSXCSW(J) ;T3="DATAI"=CHANNEL STATUS WORD
POPJ P, ;GIVE NOT-RECOVERED RETURN
SUBTTL INTERRUPT HANDLER
;ROUTINE TO PROCESS SA10 INTERRUPTS.
;CALL:
; T3/ CONI STATUS BITS
; W/ KDB ADDRESS
; PUSHJ P,DSXINT
;EXITS CPOPJ ALWAYS THROUGH FILINT WITH:
; T1/ COMMUNICATIONS WORD (ATN BITS+DRIVE,,ERROR+FUNCTION)
; T2/ CONI
; T3/ ENDING STATUS,,ERROR REGISTER
;CALLED FROM SA10 INTERRUPT HANDLER WHEN AN INTERRUPT HAS
;OCCURRED FOR THE SUBCHANNEL TO WHICH THIS KDB IS CONNECTED.
DSXINT: SETZB S,F ;CLEAR ERROR FLAGS (S), ALSO "CONI" FLAGS (F)
MOVE J,W ;COPY KDB ADDRESS TO FILSER AC
TRNE T3,SI.PAR!SI.NXM ;SKIP UNLESS MEMORY ERRORS
JRST MEMERR ;HANDLE MEMORY ERRORS
DMOVE T1,@DSXCSW(J) ;GET CHANNEL-STATUS, UNDONE-PC
PUSH P,[CLRSTS] ;CALL CLRSTS ON OUR WAY OUT OF INTERRUPT
LDB T3,[POINT CSSUNI,T1,CSNUNI] ;GET UNIT NUMBER
MOVE U,@DSXPTR(J) ;GET ADDR OF UNIT IF EXISTS
JUMPE U,DSXIIN ;JUMP IF NO SUCH UNIT, IGNORE INTERRUPT
DMOVEM T1,UNICSW(U) ;SAVE CHANNEL-STATUS, UNDONE-PC
MOVE T2,UNIFNC(U) ;GET CURRENT FUNCTION BITS
TLNN T2,UNPONP ;SKIP IF POSITION FOR ON-LINE INTERRUPT
TLNE T2,UNPCPY ;OR SEE IF CALLING CPY ROUTINE
JRST DSXDCH ;DISPATCH TO CONTINUING HANDLER
TLNE T1,(S.SE) ;SKIP UNLESS SELECT ERROR
JRST SELERR ;BRANCH IF SELECT ERROR (CU OFFLINE?)
TLNE T1,(S.CUE) ;SKIP UNLESS CONTROL-UNIT-END
JRST HCUE ;GO HANDLE THAT
HRRE T4,UNIFNC(U) ;GET FILSER OPERATION IN PROGRESS
SKIPGE T4 ;SKIP IF IT LOOKS LEGAL
JRST DSXSPR ;BRANCH IF APPARENTLY SPURIOUS
TLNE T1,(S.BUSY) ;SKIP UNLESS BUSY
JRST HBUSY ;GO HANDLE BUSY
TLNE T1,(S.UC) ;SKIP UNLESS UNIT CHECK
JRST HUC ;GO HANDLE THAT
TLNE T1,(S.CTLE) ;SKIP UNLESS CONTROL ERROR
JRST HCTLE ;GO HANDLE CONTROL ERROR
TLNN T2,UNPHNS ;SET AN ERROR IF HUNG RECOVERY
JRST DSXIN2 ;NO, OK
TRO S,IODERR ;HUNG RECOVERY
TRO F,SN.HNR ;NOTE HUNG RECOVERY
DSXIN2: TLNN T1,(S.BIPE+S.LE+S.PCI+S.ATN+S.UE) ;SKIP IF SA10 REPORTS ERRORS
JRST DSXRET ;NO, OK
DEVERR: TRO S,IODERR ;SOME ERROR DECTECTED
TRO F,SN.CDE ;CHANNEL DETECTED ERROR
;FALL INTO DSXRET
;HERE ON NORMAL DEV-END + CHAN-END COMPLETION OF AN OPERATION
DSXRET: MOVE T1,UNIFNC(U) ;GET CURRENT FUNCTION
TLNE T1,UNPSNS ;SKIP IF NOT SENSE AFTER UNIT CHECK
JRST DSXSNS ;IT WAS
MOVE T2,UNICSW(U) ;GET CHANNEL-STATUS
TLNE T2,(S.DE) ;SKIP UNLESS DEVICE END ON
TLNE T2,(S.CE) ;SKIP IF DEVICE END, NO CHANNEL END
JRST NOTCU1 ;OK, NO DEVICE END, OR DEV END AND CHN END
SKIPN UNISTS(U) ;SKIP UNLESS UNIT IDLE (PROBABLY COMING ON-LINE)
JRST NOTCU1 ;WAS IDLE, PROBABLY COMING ON-LINE
PUSHJ P,CUERES ;DEVICE END ALONE MAY BE AFTER UNIT BUSY
PJRST SETGOB ;UNIT WAS BUSY, SET GO BIT AND DISMISS
TRO S,IODERR ;FORCE RETRY
TRO F,SN.RTR ;RETRY REQUESTED BY CONTROLLER
NOTCU1: MOVE T2,UNIECW(U) ;GET RESIDUAL_COUNT & UNDONE_PC WORD
MOVEM T2,UNITCA(U) ;SAVE FOR LATER IN CASE ANOTHER UNIT FINISHES
MOVE T1,UNIFNC(U) ;RESTORE T1 AGAIN
MOVE T2,UNIDES(U) ;GET UNIT DESCRIPTION
TLNE T2,UNPOFL ;SKIP UNLESS UNIT WAS OFF-LINE
PJRST FREINT ;MUST BE ON-LINE INTERRUPT
MOVE T2,UNISTS(U) ;GET UNIT STATUS
CAIL T2,OWCOD ;SKIP IF NOT OPERATOR WAIT
PJRST FREINT ;BRANCH TO GIVE ON-LINE INTERRUPT
MOVE T2,F ;NO SENSE DATA, USE FLAGS FOR "CONI" DATA
DSXRT1: HRRZ T1,UNIFNC(U) ;GET FILSER OPERATION
CAIE T1,OPRED ;READ OR
CAIN T1,OPWRT ; WRITE OPERATION?
PUSHJ P,FIXCWA ;YES, FIXUP DF10'S ICWA+1 WORD
DSXRT0: HRRZ T1,UNIFNC(U) ;GET FILSER OPERATION
HLLOS UNIFNC(U) ;THEN INVALIDATE IT
LDB T3,[POINT CSSUNI,UNICSW(U),CSNUNI] ;UNIT NUMBER TO RH T3
HRL T1,T3 ;UNIT NUMBER TO LH T1
MOVE T3,UNICSW(J) ;T3=CHANNEL-STATUS WORD FOR "DATAI"
;NOTE AFTER UNIT CHECK THIS WILL BE FROM AFTER THE SENSE COMMAND
IOR T1,S ;INCLUDE ERROR BITS IN T1 FOR FILSER
;*** SHOULDN'T DRREST DO THIS? DOES ANYONE CARE?
HRRM U,KONCUA(J) ;MUST TRUST HARDWARE SINCE ALL DRIVES MAY BE GOING
SKIPE DSXBUC(J) ;SKIP IF NO BUSY UNITS
PUSHJ P,FAKCUE ;FAKE A C-U-E IF BUSY UNITS
HLRZ T4,T1 ;GET UNIT WHICH INTERRUPTED
TRNE T1,OPPOS ;POSITIONING INTERRUPT?
SKIPA T4,BITTBL##(T4) ;YES, GET BIT FOR THAT (SINGLE) UNIT
SETZ T4, ;NO, NO UNITS HAVE POSITIONED
SKIPN UNIDRB(U) ;DRB PRESENT?
PJRST FLHTID## ;NO, KINDA EASY TO CALL FILINT
EXCH T3,UNIDRB(U) ;GET DRB ADDRESS, SAVE "DATAI" BITS
MOVEM T2,DRBCNI##(T3) ;SAVE "CONI"
MOVE T2,UNIDRB(U) ;GET "DATAI" BITS
MOVEM T2,DRBDTI##(T3) ;SAVE "DATAI"
SETZM UNIDRB(U) ;CLEAR MEMORY OF DRB
PJRST FLHTID## ;CALL FILINT
;HERE ON INTERRUPT DURING KONCPY
DSXDCH: MOVEI T2,@UNICAD(U) ;ADDRESS TO CONTINUE
CAIL T2,DSXKON ;MUST BE IN DSXKON
CAILE T2,DSXEND ;SKIP IF VALID
STOPCD CPOPJ##,DEBUG,DND, ;++DISPATCH NOT IN DSXKON
JRST @T2 ;DISPATCH OK, DO IT
;HERE ON INTERRUPT SHOWING SELECT ERROR
SELERR: MOVSI T1,(S00IRQ) ;GET INTERVENTION REQUIRED
IORM T1,UNISND+S00WRD(U) ;SET IT IN UDB
PJRST DSXSNZ ;MAKE SURE BADUNI GETS CALLED TO SLOW US DOWN
;HERE ON "ON-LINE" INTERUPT (DEV END WHILE UNIT IS "OFFLINE")
FREINT: PUSHJ P,FJCONT## ;ENSURE WE TRY THIS UNIT AGAIN ASAP
MOVEI T1,OPPOS ;MAKE LOOK LIKE FREE INTERUPT SINCE NOW ON-LINE
HRL T1,UDBPDN(U) ;INSERT DRIVE #
SETZB T2,T3 ;NO CONI ETC
MOVE T4,UDBPDN(U) ;GET DRIVE #
MOVE T4,BITTBL##(T4) ;GET "ATTENTION" BIT
PJRST FLHTID## ;GIVE FREE-INTERRUPT TO FILSER
; HERE WHEN SENSE COMMAND DONE
DSXSNS: MOVSI T1,UNPSNS ;GET SENSE-IN-PROGRESS BIT
ANDCAM T1,UNIFNC(U) ;CLEAR IT
SKIPN UNIDRB(U) ;SKIP IF AN XFER OPERATION
JRST DSXSNK ;BRANCH IF ERROR ON SEEK/RECAL
PUSHJ P,FIXBAD ;GO UPDATE UNILPC, ETC
MOVE T1,UNIDRB(U) ;GET POINTER TO DRB
MOVE T2,DRBBLK(T1) ;GET 1ST BLOK IN XFER
ADD T2,DRBGOD(T1) ;COMPUTE BLOK IN ERROR
EXCH T2,UNIBBK(U) ;REMEMBER THE BAD BLOK FOR THIS PASS
CAMN T2,UNIBBK(U) ;SKIP IF SAME OFFENDER
;HERE DIRECTLY ON SEEK/RECAL ERROR
DSXSNK: AOSA T2,UNIRTC(U) ;UP RETRY COUNT BY ONE
SETZB T2,UNIRTC(U) ;START OVER WITH NEXT BLOCK
CAILE T2,DSXMAX ;SKIP IF NOT TOO MANY CONSECUTIVE ERRORS
JRST DSXSNZ ;BRANCH TO JUST GIVE UP
MOVE T2,UNISND+S02WRD(U) ;GET WORD WITH CORRECTION BIT
TDNE T2,[D02COR] ;SKIP IF NOT AN ECC-CORRECTABLE ERROR
PUSHJ P,XXXECC ;GO DO ECC CORRECTION
PJRST DSXRGO ;RE-CALL "DSXGO" AND EXIT INTERRUPT
;HERE TO JUST GIVE UP ON THIS XFER
DSXSNZ: SKIPN UNIDRB(U) ;SKIP IF XFER REQUEST
PJRST DSXRT0 ;POS IGNORES ERROR, XFER VIA CONECT CATCHS IT
MOVE T2,UNISND(U) ;GET SENSE DATA FOR "CONI"
TLNE T2,(S00DCK) ;SKIP IF NOT DATA CHECK
TROA S,IODTER ;NOTE DATA ERROR
TRO S,IODERR ;NOTE AN EQUIPMENT ERROR
TDNE T2,[D01ITF!D01EOC!D01NRF]
TRO S,IODERR!IODTER ;NOTE FORMAT ERROR IF BAD PACK
PJRST DSXRT0 ;BRANCH OFF TO EXIT INTERRUPT AND TELL FILSER
;HERE TO HANDLE UNIT CHECK - DO A SENSE I/O COMMAND
HUC: MOVE T1,UNIECW(U) ;GET TERMINAL COUNT, UNDONE-PC WORD
MOVEM T1,UNITCA(U) ;SAVE FOR LATER SENSE PROCESSING
MOVSI T1,UNPSNS ;GET SENSE-IN-PROGRESS BIT
IORM T1,UNIFNC(U) ;SET IT
MOVEI T2,UNISNC(U) ;POINT AT SENSE PROGRAM
PUSHJ P,SETDVL ;SETUP TO RUN SENSE PROGRAM
PJRST SETGOB ;SET GO BIT AND EXIT INTERRUPT
;HERE TO HANDLY BUSY - SET A FLAG TO RETRY LATER
HBUSY: AOS DSXBSY(J) ;COUNT AN ABSOLUTE BUSY
PJRST SETBSY ;SET UNIT'S BUSY BIT AND DISMISS INTERRUPT
;HERE TO HANDLE CONTROL UNIT END - SET UP TO RETRY UNITS THAT GOT A BUSY
HCUE: TLNE T1,(S.UC) ;UNIT-CHECK ALSO?
JRST HUC ;CU END + UNIT CHECK MEANS ERROR AFTER CHAN END
TLNE T1,(S.BUSY) ;BUSY ALSO?
PUSHJ P,SETBSY ;SET BUSY BIT FOR THIS UNIT
HCUE6: MOVE T2,UNIFNC(U) ;GET STATUS OF THE UNIT THAT GOT CUE
TLNE T2,UNPSNS ;SKIP IF NOT SENSE-IN-PROGRESS
JRST HCUE9 ;IF THAT UNIT IS SENSING, GIVE IT PRIORITY
PUSHJ P,UCCHK ;CHECK FOR UNITS THAT ARE SENSE-BUSY'ED
PJRST SETGOB ;BRANCH TO SET GO BIT AND EXIT
HCUE4: PUSHJ P,CUECHK ;NO, SET UP ALL OTHERS
PJRST SETGOB ;SET GO BIT AND DISMISS INTERRUPT
;HERE TO FAKE A CUE WHEN WE EXIT AN INTERRUPT VIA FILINT
FAKCUE: PUSHJ P,SAVT## ;SAVE ACS, CUZ FILINT CARES
PJRST HCUE6 ;GET THINGS GOING AGAIN
HCUE9: PUSHJ P,SETDVR ;SET TO RE-RUN CHANNEL PROGRAM
PJRST SETGOB ;SET GO BIT AND DISMISS CUE
;ROUTINE TO CHECK IF ANY UNIT(S) ARE WAITING FOR "SENSE"
UCCHK: PUSH P,U ;SAVE FIRST UNIT
UCCHK1: MOVSI T1,UNPSNS ;GET BIT INDICATING SENSE IN PROGRESS
TDNN T1,UNIFNC(U) ;SKIP IF SENSE IN PROGRESS
JRST UCCHK2 ;BRANCH IF NOT SENSING
PUSHJ P,SETDVR ;RESTART THE SENSEING UNIT
JRST UPOPJ## ;RETURN TO CALLER, WHO SETS GO BIT AND DISMISSES
UCCHK2: MOVE U,UNIKON(U) ;STEP TO NEXT UNIT IN RING
CAME U,(P) ;SKIP IF BACK TO ORIGINAL UNIT
JRST UCCHK1 ;NO
PJRST UPOPJ1## ;YES, NO UNITS WAITING FOR SENSE
;SUBROUTINE TO CHECK ALL UNITS AND SET UP TO RESTART
;VAL: T1=NUMBER OF UNITS SETUP TO RETRY BECAUSE BUSY
CUECHK: PUSH P,[0] ;PUT ZERO ON STACK
PUSH P,U ;SAVE U FOR END OF LOOP
BSYCHK: PUSHJ P,CUERES ;SKIP IF UNIT NOT BUSY, NORMAL IF RESTARTED
AOS -1(P) ;COUNT UNITS WAITING BECAUSE BUSY
MOVE U,UNIKON(U) ;STEP TO NEXT UNIT
CAME U,(P) ;SKIP IF BACK TO FIRST UNIT
JRST BSYCHK ;NO, CHECK ALL UNITS ON CONTROLLER
POP P,U ;RESTORE U
PJRST TPOPJ## ;GET COUNT AND RETURN
;SUBROUTINE TO CHECK IF UNIT HAD BUSY RESPONSE, AND SET CHAN PROG FOR RESTART
; NON-SKIP IF UNIT HAD BUSY RESPONSE, CHANNEL PROGRAM SET TO RESTART
; SKIP RETURN IF DID NOT HAVE BUSY
CUERES: MOVSI T1,UNPBSY ;BIT SET IN UNIFNC IF UNIT GOT BUSY RESPONSE
TDNN T1,UNIFNC(U) ;SKIP IF SET FOR THIS UNIT
JRST CPOPJ1## ;NO, UNIT NOT WAITING AFTER BUSY
PJRST SETDVR ;RUN SAME PROGRAM AGAIN
;ROUTINE TO SET BUSY AND KEEP DSXBUC STRAIGHT
SETBSY: PUSH P,T1 ;SAVE AN AC
MOVSI T1,UNPBSY ;GET THE BUSY BIT
TDNE T1,UNIFNC(U) ;SKIP IF NOT SET YET
JRST TPOPJ## ;EXIT NOW IF ALREADY SET
IORM T1,UNIFNC(U) ;SET THE BIT
AOS DSXBUC(J) ;BUMP THE COUNT
JRST TPOPJ## ;EXIT WITH BIT SET AND COUNT FIXED
;ROUTINE TO CLEAR BUSY AND DSXBUC STRAIGHT
CLRBSY: PUSH P,T1 ;SAVE AN AC
MOVSI T1,UNPBSY ;GET THE BUSY BIT
TDNN T1,UNIFNC(U) ;SKIP IF ALREADY SET
JRST TPOPJ## ;EXIT WITH BIT ALREADY CLEARED
ANDCAM T1,UNIFNC(U) ;CLEAR BIT
SOS DSXBUC(J) ;FIX THE COUNT
JRST TPOPJ## ;EXIT WITH BIT CLEAR AND COUNT FIXED
;HERE TO HANDLE MEMORY ERRORS
MEMERR: MOVEI T2,SO.CME ;CLEAR MEMORY ERRORS
PUSHJ P,CNOCLR ;DO THE CONO
MOVEI T2,SO.SRS ;SELECTIVE RESET COMMAND
PJRST CNOCLR ;DO SELECTIVE RESET
;SELECTIVE RESET SHOULD CAUSE CONTROL ERROR AND INVOKE ERROR RECOVERY.
;AT WORST, IF NOTHING HAPPENS FROM RESET, DSXTMO WILL TIME OUT THE OPERATION.
;HERE TO HANDLE CONTROL ERROR
HCTLE: HRRZ T3,DSXGSN(J) ;GET GLOBAL SUBCHANNEL NUMBER
MOVE T2,SAMERR##(T3) ;GET MEMORY ERROR WORD
TRNN T2,SI.NXM!SI.PAR ;SKIP IF THIS IS AFTER MEMORY ERROR
JRST DEVERR ;NO, JUST RETURN ERROR
TRNN T2,SI.NXM ;SKIP IF WAS NXM
TROA S,IOCHMP!IODERR ;NO, MEMORY PARITY ERROR
TRO S,IOCHNX!IODERR ;YES, NXM
SETZM SAMERR##(T3) ;CLEAR FLAGS
JRST DEVERR ;RETURN CHANNEL DETECTED DEVICE ERROR
;HERE WHEN INTERRUPT FOR UNKNOWN UNIT - COUNT AND IGNORE
DSXIIN: AOS DSXIUU(J) ;COUNT TIMES GOT INT FOR UNKNOWN UNIT
MOVE T3,BITTBL##(T3) ;GET BIT FOR THE NEW UNIT
IORM T3,DSXNUM(J) ;SET IN BIT MASK
HRROS KDBNUM(J) ;FLAG FOR THE REST OF THE WORLD TO SEE
POPJ P, ;EXIT INTERRUPT
;HERE ON INTERRUPT FOR KNOWN BUT IDLE UNIT
DSXSPR: TLNN T1,(S.CE) ;NORMAL SPURIOUS?
JRST FREINT ;BRANCH IF DEV-END ONLY ON APPARENTLY IDLE UNIT
AOS DSXSUI(J) ;REMEMBER APPARENTLY SPURIOUS INTERRUPT
AOS UNISUI(U) ;AND KEEP PER UNIT COUNT TOO
POPJ P,
SUBTTL DETERMINE CAPACITY AND STATUS
;ROUTINE TO RETURN CAPACITY AND STATUS OF AN IBM DRIVE TO FILSER.
;CALL: J/KDB ADDRESS
; U/UDB ADDRESS
; PUSHJ P,DSXCPY
;RETURN CPOPJ IF ERROR
; CPOPJ1 IF DRIVE EXISTS AND IS OK TO USE WITH:
; T1/BLOCKS PER UNIT
; T2/BLOCKS PER UNIT INCLUDING MAINTENANCE CYLINDERS
; T3/BLOCKS PER UNIT IN 10/11 COMPATABILITY MODE
; T4/STATUS BITS (KOPUHE,KOPNSU),,UNIT TYPE
; W/BLOCKS PER TRACK,,BLOCKS PER CYLINDER
DSXCPY: MOVSI T1,UNPCPY ;BIT MARKING IN CPY ROUTINE
TDNE T1,UNIFNC(U) ;SKIP IF NOT HERE BEFORE
JRST DSXCPA ;YES, COMMAND TRIES EVERY TICK OR SO
MOVEM T1,UNIFNC(U) ;NOTE WE ARE IN CPY ROUTINE
SETOM UNICCF(U) ;SET COMCON FLAG SO HE KNOWS WE'RE STILL GOING
PUSHJ P,SETTCP ;SETUP UNITCP, UNISDA
PUSHJ P,STONOP ;INSERT ONLY A NO-OP
PUSHJ P,STOHLT ;INSERT A HALT
PUSHJ P,CPYWAT ;START NO-OP, RETURN A SKIP TO COMCON
;HERE AFTER NO-OP
DSXCP1: TLNE T1,(S.SE) ;SKIP UNLESS SELECT ERROR
JRST DSXCPD ;STILL DOWN
PUSHJ P,SETSNS ;SETUP A SENSE
PUSHJ P,CPYWAT ;SET UP, START CHAN PROG, RETURN AFTER INT
;HERE WHEN SENSE CMD DONE
SETZ T4, ;ZERO T4 IN CASE OFF-LINE
TLNE T1,(S.SE) ;SKIP UNLESS SELECT ERROR
JRST DSXCPD ;STILL DOWN
MOVE T1,UNISND(U) ;GET SENSE INFO
TLNE T1,(S00IRQ) ;SKIP IF UNIT OK
DSXCP2: TLO T4,KOPUHE ;NOTE UNIT OFF-LINE
JUMPN T4,DSXCPS ;ASSUME 3330 IF OFF-LINE
PUSHJ P,SETTCP ;SETUP UNITCP, UNISDA
MOVE T1,[^D411 * ^D342] ;T1=1ST BLOCK IN CYL 411
MOVEM T1,UNICBN(U) ;SET AS CURRENT BLOCK
PUSHJ P,STOSEK ;STORE IT
PUSHJ P,STONOP ;GET A NO-OP
PUSHJ P,STOHLT ;AND A HALT
PUSHJ P,CPYWAT ;SET UP, START CHAN PROG, RETURN AFTER INT
;HERE AFTER SEEK
SETZ T4, ;ZERO T4 SINCE NOT OFF-LINE
TLNN T1,(S.UC) ;SKIP IF UNIT CHECK
JRST DSXCPL ;NO, MUST BE 3331
PUSHJ P,SETSNS ;SETUP FOR A SENSE
PUSHJ P,CPYWAT ;SET UP, START CHAN PROG, RETURN AFTER INT
;HERE AFTER SENSE AFTER SEEK
SETZ T4, ;CLEAR T4 FOR ON-LINE UNIT
MOVE T1,UNISND(U) ;GET SENSE INFO
TLNN T1,(S00REJ+S00IRQ) ;SKIP IF ILLEGAL SEEK
JRST DSXCPL ;MUST HAVE FAILED FOR SOME OTHER REASON
;HERE IF 3330 UNIT
DSXCPS: HRRI T4,.UT330 ;UNIT TYPE
JRST DSXCPC ;RETURN VALUES
;HERE IF 3331 UNIT
DSXCPL: HRRI T4,.UT331 ;UNIT TYPE
DSXCPC: MOVE T1,BLKPRU(T4) ;GET BLOCKS/UNIT BASED ON UNIT TYPE
MOVEM T1,UNIPRU(U) ;SAVE VALUES
MOVEM T4,UNITYP(U)
SETZM UNICCF(U) ;CLEAR COMCON FLAG TO NOTE WE'RE FINISHED
POPJ P, ;EXIT INTERRUPT AND RETURN
DSXCPD: MOVSI T4,KOPNSU ;UNIT IS DOWN
JRST DSXCP2 ;RETURN THAT
;HERE WHEN CALLED AGAIN FROM COMMAND - SEE IF FINISHED
DSXCPA: SKIPE UNICCF(U) ;SKIP IF FINISHED
JRST CPOPJ1## ;NO, STILL WAITING
MOVSI T1,UNPCPD ;FLAG TO NOTE CPY ROUTINE DONE
MOVEM T1,UNIFNC(U) ;SO COMMAND WILL CONTINUE
;ALSO PREVENT INTS FROM DISPATCHING
PUSHJ P,SNSCLR ;CLEAR OUT SENSE BYTES
MOVE T1,UNIPRU(U) ;GET SIZE OF UNIT
MOVE T2,T1 ;BLOCKS INCLUDING MAINT CYLS
SETZ T3, ;NO 10/11 COMPATIBILITY MODE
MOVE T4,UNITYP(U) ;AND UNIT TYPE
MOVE W,[^D18,,^D18*^D19] ;BLKS, PER TRK,,BLKS PER CYL
TLNN T4,-1 ;ANY ERRORS?
AOS (P) ;NO, SET FOR SKIP RETURN
POPJ P, ;GIVE DOWN RETURN
;SUBROUTINE TO SET UP CHAN PROG, SET GO FLAG, AND MARK RETURN AFTER INT
CPYWAT: PUSHJ P,SETDVP ;SET UP DEVICE LIST ENTRY
POP P,UNICAD(U) ;SAVE RETURN ADDR FOR AFTER INT
IFN FTKL10,< ; IF KL10
SKIPN DINITF## ;NO NEED TO FLUSH CACHE IF ONCE ONLY
PUSHJ P,CSDMP## ;FLUSH CACHE
>;END IFN FTKL10
PUSHJ P,DSXGO1 ;SET GO FLAG
JFCL ;DONT CARE ABOUT THIS
CONSO PI,PIPROG## ;SKIP IF PIS IN PROGRESS (CALLED AT INT LEVEL)
SKIPN DINITF## ;NOT INTERRUPT LEVEL, DURING ONCE-ONLY?
POPJ P, ;PIS IN PROGRESS OR NOT ONCE-ONLY, DISMISS
; INTERRUPT AND WAIT FOR COMPLETION
PJRST DSXWAT ;ONCE-ONLY, WAIT A WHILE FOR COMMAND TO COMPLETE
SNSCLR: SETZM UNISND(U) ;CLEAR FIRST WORD
MOVEI T2,UNISND+1(U)
HRLI T2,-1(T2) ;MAKE BLT PTR
BLT T2,UNISND+5(U) ;CLEAR SENSE DATA
POPJ P, ;RETURN
$INIT
;SUBROUTINE TO WAIT FOR DSX COMMAND FOR ONCE-ONLY
DSXWAT: MOVSI T1,ONCTIM## ;GET TIME TO WAIT FOR COMPLETION
SKIPE UNICCF(U) ;SEE IF CPY CHECK STILL IN PROGRESS
SOJG T1,.-1 ;KEEP LOOPING
JUMPG T1,DSXCPA ;IF COMPLETED, FETCH DATA FROM UDB AND RETURN
MOVSI T4,KOPNSU!KOPUHE ;GET THE ERROR FLAGS
POPJ P, ;RETURN TO ONCE CALLER
$HIGH
SUBTTL MISCELLANEOUS TO BE CLEANED UP
;*** TEST INTERRUPT ENABLED FLAG FOR SUBCHANNEL?
DSXALV: XCT KDBCNI(J) ;GET CONI
TRNE T1,7 ;ALIVE?
POPJ P, ;YES, JUST RETURN
MOVEI T1,SAXCHN## ;GET THE CHANNEL THE SA10 BELONGS ON
XCT KDBCNO(J) ;INSIST ON A NEW PI CHANNEL
STOPCD .+1,INFORM,DSXPIA, ;++ DSXKON NOTICES SA10 HAS NO PI-ASSIGNMENT
POPJ P, ;RETURN
;HERE TO COPY SA10 DISK REGISTERS FOR SYSERR ET AL
DSXREG: POPJ P,
SUBTTL CHECK IF CONTROLLER IS UP/CHECK UNIT WRITE LOCK
$INIT
DSXHWP: POPJ P, ;WRITE-ENABLED FOR NOW
REPEAT 0,< ;*** TEMP
PUSHJ P,GTHOM## ;TRY TO READ A HOME BLOCK
POPJ P, ;IF BOTH BAD, DONT RISK WRITING, ASSUME OK
JUMPL T2,.+2 ;JUMP IF FIRST HOME BLOCK BAD, USE SECOND
SKIPA T2,UNIHOM(U) ;FIRST IS OK, REWRITE IT
HLRZ T2,UNIHOM(U) ;SECOND IS OK, REWRITE IT
HRRZS T2 ;JUST BLOCK NUMBER IN RH
PUSHJ P,OMNWRT## ;REWRITE THE GOOD BLOCK
SKIPA T2,UNISND(U) ;ERROR, GET SENSE DATA FOR UNIT
POPJ P, ;OK, MUST NOT BE WRITE-PROTECTED
TLNE T2,(D01WRL) ;SKIP IF WRITE-INHIBIT OFF
AOS (P) ;WRITE INHIBIT - SKIP RETURN
POPJ P, ;RETURN
>; *** TEMP
DSXUPA: PUSHJ P,SAVE1## ;SAVE P1
MOVEI T1,7 ;GET PI ASSIGNMENT
XCT KDBCNO(J) ;TRY TO GIVE IT ONE
XCT KDBCNI(J) ;READ IT BACK
TRNN T1,7 ;DID IT WORK?
POPJ P, ;NO, ASSUME DEAD
PUSHJ P,DSXENB ;ENABLE INTERRUPTS FOR THIS CONTROLLER
HRRZ T1,DSXSCH(J) ;GET SUBCHANNEL
MOVNS T1 ;NEGATIVE FOR RIGHT SHIFT
MOVEI T2,SI.ENB ;BIT FOR SUBCHAN ZERO
LSH T2,(T1) ;GET OUR INT ENABLE BIT
XCT KDBCNI(J) ;GET CONI STATUS
TRNN T1,(T2) ;INTERRUPTS ENABLED?
POPJ P, ;SA10 PROBABLY NOT WORKING
SJSP T1,CPOPJ1## ;FLAG WRITE-HEADER-LOCKOUT OK AND RETURN SUCCESS
$HIGH
;ROUTINE TO TELL FILIO OF RETRY-STRATEGY ON ERROR.
;IF HARDWARE LOOKS OK AND ERROR IS PROBABLY MEDIA, GIVE UP.
;IF HARDWARE LOOKS BAD (OFFLINE, UNSAFE, ETC) TRY RECALS FOREVER.
DSXERR: PUSHJ P,CONECT ;SKIP IF WE LOST FAIR AND SQUARE
SKIPA T1,[5] ;TRY RECAL IF HARDWARE CROAKED IN MID XFER
MOVEI T1,3 ;GIVE UP
POPJ P, ;RETURN
;READ PDP11 MODE (?)
;WRITE PDP11 MODE (?)
;UNLOAD UNIT
DSXRDC:
DSXWTC:
DSXUNL: STOPCD .,STOP,DSX3IF, ;++ 3330 ISN'T FANCY
SUBTTL ROUTINES TO BUILD CHANNEL PROGRAMS
;SUBROUTINE TO CONSTRUCT CHANNEL PROGRAM FOR FILSER OPERATION
;ARGS: T4=FILSER OPCODE
; U=UNIT
SETCHP: HRRZM T4,UNIFNC(U) ;REMEMBER FILSER FUNCTION AND CLEAR LH FLAGS
PUSHJ P,SETTCP ;SETUP UNITCP, UNISDA
MOVE T1,UNIDRB(U) ;GET DRB ADDRESS, IF ANY
PJUMPE T1,SETPOS ;SETUP A POSITIONING PROGRAM
PJRST SETXFR ;SETUP AN XFER PROGRAM
; ROUTINE TO SETUP A POSITION PROGRAM
SETPOS: SETZM UNISND(U) ;DEFAULT TO NO SENSE DATA INFO
MOVE T1,UNIBLK##(U) ;PICK UP THE BLOCK NUMBER
MOVEM T1,UNICBN(U) ;SAVE AS CURRENT BLOCK #
MOVE T1,UNIRCL(U) ;GET PROTOTYPE RECAL
CAIN T4,OPCAL ;SKIP IF POSITION
PUSHJ P,STODVC ;INSERT A RE-CAL
PUSHJ P,STOSEK ;INSERT A SEEK
PUSHJ P,STONOP ;INSERT A NO-OP
TLNE S,IO ;SKIP IF READ
PUSHJ P,STORC0 ;INSERT READ/WRITE RECORD 0
PUSHJ P,STOHLT ;INSERT A HALT
AOS (P) ;ALWAYS GIVE GOOD RETURN
PJRST SETDVP ;SETUP TO RUN SEEK PROGRAM
; ROUTINE TO SETUP A DATA XFER PROGRAM
SETXFR: PUSHJ P,CONECT ;TRY TO CONECT TO DRIVE
POPJ P, ; CANNOT CONECT TO DRIVE
AOS (P) ;GIVE GOOD RETURN
SKIPN T1,UNIDRB(U) ;T1=DRB
XCT DSXXWD ;++ XFER WITHOUT DRB
MOVE T3,DRBNUM##(T1) ;T3=# OF BLOCKS TO XFER
SKIPN T3 ;SKIP IF WE FOUND SOMETHING TO DO
STOPCD SETDVP,INFORM,SETXF0, ;++ DRBNUM =0 IN DSXKON
PUSHJ P,MAPIO ;CALL LOCAL MAPIO TO CONVERT DF10C TO SA10B
PJRST SETDVP ;SETUP TO RUN XFER PROGRAM
; ROUTINE TO CHECK STATUS OF DRIVE
CONECT: SETZ T1, ;DEFAULT TO NO-PROBLEMS
MOVE T2,S00WRD+UNISND(U) ;GET BYTE 0
TDNN T2,[S00OVR] ;SKIP IF OVERRUN
TDNE T2,[S00IRQ] ;SKIP IF NOT INTERVENTION REQUIRED
TRO T1,KOPOFL ;JUST PLAIN OFFLINE
TDNE T2,[S00REJ] ;SKIP IF NOT REJECTED COMMAND
TDNN T2,[D01WRL] ;SKIP IF CMD-REJ + WRITE-LOCKED
SKIPA
TRO T1,KOPWLK ;WRITE-LOCKED
TDNE T2,[S00BOC] ;SKIP IF NOT BUS-OUT-CHECK
TRO T1,KOPUSI ;THEN STATUS-INCONSISTENT
JUMPE T1,CPOPJ1## ;BRANCH IF NO PROBLEMS SPOTTED
LDB T2,[POINTR (UNISND+S07WRD(U),D07FMC)] ;GET FORMAT/MESG CODE
LSH T2,-4 ;DUMP MESG, EXTRACT FORMAT
CAIE T2,1 ;SKIP IF FORMAT 1
POPJ P, ;RETURN WITH T1=DIAGNOSIS
MOVE T2,UNISND+S08WRD(U) ;GET 1ST WORD OF UNSAFE BITS
MOVE T3,UNISND+S12WRD(U) ;GET 2ND WORD OF UNSAFE BITS
TDNN T2,[D09PLU!D11HUS] ;SKIP IF PLO OR HEAD UNSAFES
TDNE T3,[D12DUS!D12SUS!D12PUS] ;DATA,SERVO,OR PAD UNSAFE
TRO T1,KOPFUS ;SET UNSAFE BIT
POPJ P, ;AND RETURN
; ROUTINES TO RUN A CHANNEL PROGRAM
;
; SETDVP TO RUN THE FILSER PROGRAM
; SETDVL TO RUN THE VIRTUAL (T2) PROGRAM
; SETDVR TO RUN THE PREVIOUS PROGRAM AGAIN
SETDVP: SKIPA T2,UNIPCP(U) ;JUST USE UDB PROGRAM
SETDVL: MAP T2,(T2) ;CONVERT VIRTUAL ADDRESS TO PHYSICAL
TLZ T2,(MP.NAD) ;CLEAR NON-ADDRESS BITS
PMOVE T3,UNIDVP(U) ;GET DEVICE LIST ENTRY
AND T3,[776000,,0] ;PRESERVE ONLY DEVICE ADDRESS
TLO T3,(<DL.STA>B<SANDLO>) ;INSERT THE "GO" CODE
TDOA T3,T2 ;INSERT THE PROGRAM ADRESS
SETDVR: MOVE T3,UNIDVL(U) ;GET ORIGINAL DEVL SLOT CONTENTS
PMOVEM T3,UNIDVP(U) ;INSERT NEW DEVICE LIST ENTRY IN LIST
MOVEM T3,UNIDVL(U) ;SAVE FOR DEBUGGING
PJRST CLRBSY ;NOT BUSY NOW
;ROUTINE TO ACTUALLY SET GO BIT FOR A CHANNEL
SETGOB: PUSHJ P,SAVT## ;SAVE THE ACS
MOVEI T2,SO.GO ;GET GO FLAG FUNCTION
PJRST CNOSET ;GO DO CONO TO SET IT AND THEN EXIT
;ROUTINE TO CLEAR STATUS FLAG AT INTERRUPT TIME
CLRSTS: PUSHJ P,SAVT## ;SAVE THE ACS
MOVEI T2,SO.STS ;GET THE STATUS-FLAG FUNCTION
PJRST CNOCLR ;CLEAR FUNCTION AND THEN EXIT
;SUBROUTINE TO COMPUTE LATENCY - SHOULDN'T BE CALLLED
DSXLTM: SETZ T1, ;RETURN PERFECT EVERY TIME
JRST CPOPJ1## ;
;SUBROUTINE TO RETURN A PROTOTYPE DEVICE COMMAND WORD FOR SETTING UP CHANNEL PROGRAM
;REQUIRED BECAUSE IOWD IS MAPPED BEFORE CALLING DSX??? TO START READ OR WRITE
DSXDVC: MOVE T1,UNIRWC(U) ;GET PROTOTYPE READ DVW
TLNE S,IO ;SKIP IF READ IS DESIRED
ADD T1,[<O.WRT>B15-<O.MTR>B15] ;NO, CONVERT TO WRITE DVW
POPJ P,
;SUBROUTINE TO SET INTERRUPT ENABLE FOR A SUBCHANNEL
DSXENB: MOVEI T2,SO.ENB ;INTERRUPT ENABLE
PJRST CNOSET ;SET THE FLAG AND RETURN
SUBTTL AUTOCONFIGURE
;AUTCON ENTRY POINT
DSXCFG: JRST CPOPJ1## ;I'M NOT INTERESTED UNTIL SAXSER IS
;SAXSER ENTRY POINT
;M/ GLOBAL SA10 SUBCHANNEL NUMBER
;P1/ -N,,CONTROL UNIT ADDRESS (HIGH 'WIDCUA' BITS)
;P2/ SA10 SUBCHANNEL NUMBER
;P3/ AVAILABLE FOR USE
;P4/ ADDRESS OF SENSE CHANNEL PROGRAM FOR UNIT ZERO
DSXCFS: PUSHJ P,SAVW## ;FREE UP KDB ADDRESS AC
SETZ W, ;HAVEN'T SEEN A KDB YET
MOVSI P3,-DSXDMX ;INIT SEARCH FOR EXISTANT UNITS
DSXCF1: HRRZ T1,P1 ;GET DCU ADDRESS
LSH T1,WIDUNA ;POSITION IN HIGH 'WIDCUA' BITS
IORI T1,(P3) ;INCLUDE UNIT ADDRESS
PUSH P,T1 ;SAVE UNIT ADDRESS
PUSHJ P,DSXNOP ;DO A NO-OP ON THE UNIT
JRST DSXCF5 ;FAILED - GO SENSE AND STEP TO NEXT UNIT
POP P,T1 ;GET UNIT ADDRESS
PUSHJ P,DSXSNU ;DO A SENSE TO GET SOME USEFUL INFORMATION
JRST DSXCF4 ;SENSE TIMED OUT, MUST NOT BE A UNIT THERE
TLNE T1,(S.SE) ;SELECT ERROR?
JRST DSXCF4 ;YES
SKIPE SNSDAT+S16WRD(P4) ;ANY TCU REV LEVEL INFORMATION RETURNED?
JRST CPOPJ1## ;YES, MUST NOT BE A DISK CU
JUMPN W,DSXCF2 ;JUMP IF HAVE ALREADY SEEN A UNIT
PUSHJ P,DSXBKD ;BUILD AND LINK THE KDB
POPJ P, ;NO CORE, GIVE UP
DSXCF2: LDB T1,[POINT 8,SNSDAT+S04WRD(P4),7] ;GET SENSE BYTE 4
; (PHYSICAL MODULE ID)
ANDI T1,77 ;KEEP JUST GOOD STUFF
JUMPN T1,DSXCF3 ;JUMP IF ANYTHING THERE
SKIPN SNSDAT+S08WRD(P4) ;HOW ABOUT BYTES 8-11?
JRST DSXCF4 ;NOPE
DSXCF3: PUSHJ P,DSXUNI ;BUILD UDB
POPJ P, ;NO CORE
DSXCF4: AOBJN P3,DSXCF1 ;BUMP UNIT NUMBER AND KEEP LOOKING
POPJ P, ;RETURN
DSXCF5: POP P,T1 ;GET UNIT ADDRESS
PUSHJ P,DSXSNU ;DO A SENSE TO UNLOAD UNIT-CHECK INFO
JFCL ;OH WELL
JRST DSXCF4 ;THEN REJOIN CODE AND STEP TO NEXT UNIT
;BUILD AND LINK KDB
;M/ GLOBAL SA10 SUBCHANNEL NUMBER
;P1/ JUNK,,DCU ADDRESS (HIGH 'MAXCUA' BITS)
;P2/ SA10 SUBCHANNEL NUMBER
DSXBKD: HRRZ T1,P1 ;GET DCU ADDRESS AS MASSBUS NUMBER
TRO T1,400000 ;BUT MAKE IT LOOK NEGATIVE TO FAKE OUT AUTKDB
;*** MOVEI T2,'ZZ ' ;PREFERRED UNIT NAMES, IF ANY
;*** HRLM T2,DSXKDB ;...SO FORCE THEM
MOVEI T2,TYPDS ;UNIT TYPE CODE
PUSHJ P,DSKKON## ;BUILD A DISK KDB
POPJ P, ;GIVE UP IF NO CORE
ADDM J,DSXPTR(J) ;ADJUST DSXPTR
MOVSI T1,-<DSXIOE-DSXIOB> ;NUMBER OF WORDS TO CHECK
XMOVEI T2,DSXIOB(J) ;STARTING WORD
HRRZ T3,.CPDVC## ;<DEVICE CODE>/4
PUSHJ P,AUTDVC## ;SET DEVICE CODES
MOVS T1,P2 ;GET SUBCHANNEL NUMBER
IMULI T1,SO.CHN ;POSITION FOR CONO
HRR T1,P2 ;INCLUDE SUBCHANNEL NUMBER
MOVEM T1,DSXSCH(J) ;STORE IN KDB
MOVEM M,DSXGSN(J) ;SAVE GLOBAL SUBCHANNEL NUMBER
MOVE T1,SAXSBA##(M) ;GET BASE ADDRESS FOR THIS SUBCHANNEL
MOVEI T2,.CLICW(T1) ;GET ICW ADDRESS
MOVEM T2,DSXICW(J)
MOVEI T2,.CLCSW(T1) ;GET ECW ADDRESS
MOVEM T2,DSXCSW(J)
MOVEI T1,DSXDMX ;NUMBER OF DEVICE LIST ENTRIES WE'LL REQUIRE
PUSHJ P,SAXDVL## ;ASSIGN THEM
POPJ P, ;THERE WEREN'T ENOUGH FREE?!
MOVEM T1,DSXDVP(J) ;SAVE ADDRESS OF START OF DEVICE LIST
JRST CPOPJ1## ;SKIP RETURN
;BUILD AND LINK UDB
;M/ GLOBAL SA10 SUBCHANNEL NUMBER
;J/ KDB ADDRESS
;P1/ JUNK,,DCU ADDRESS (HIGH 'MAXCUA' BITS)
;P2/ SA10 SUBCHANNEL NUMBER
;P3/ JUNK,,UNIT ADDRESS
;P4/ SENSE PROGRAM BUFFER ADDRESS
DSXUNI: HRLZ T1,P3 ;PHYSICAL DRIVE NUMBER
HRR T1,P3 ;UDB TABLE INDEX
MOVEI T2,.UT331 ;ASSUME 3331 UNIT
PUSHJ P,DSKDRV## ;BUILD AND LINK THE UDB
POPJ P, ;NO CORE
HRRZ T1,P1 ;GET DCU ADDRESS
LSH T1,WIDUNA ;POSITION IN HIGH 'WIDCUA' BITS
IORI T1,(P3) ;INCLUDE UNIT NUMBER
DPB T1,[POINT DVSDVA, UNIRCL(U), DVNDVA] ;INSERT DEVICE ADDRESS
DPB T1,[POINT DVSDVA, UNINOP(U), DVNDVA]
DPB T1,[POINT DVSDVA, UNISEK(U), DVNDVA]
DPB T1,[POINT DVSDVA, UNISS(U), DVNDVA]
DPB T1,[POINT DVSDVA, UNISIE(U), DVNDVA]
DPB T1,[POINT DVSDVA, UNISNC(U), DVNDVA]
DPB T1,[POINT DVSDVA, UNIRWC(U), DVNDVA]
DPB T1,[POINT DVSDVA, UNIRR0(U), DVNDVA]
MAP T1,UNISND(U) ;POINT AT SENSE DATA BUFFER
TLZ T1,(MP.NAD) ;TURN OFF MAP BITS
TLO T1,(SIOW 24,0) ;TURN ON WORD COUNT
MOVEM T1,UNISNC+1(U) ;INSERT INTO PROGRAM
MOVE T1,DSXDVP(J) ;GET START OF DEVICE LIST
ADDI T1,(P3) ;INCLUDE UNIT ADDRESS
MOVEM T1,UNIDVP(U) ;SAVE POINTER TO DEVICE LIST ENTRY
MOVEI T1,CPALEN ;GET LENGTH OF CHANNEL PROGRAM AREA
PUSHJ P,SAXCOR## ;GO GET A CHUNK OF SA10 MEMORY
POPJ P, ;DARN.
MOVEM T1,UNIPCP(U) ;SAVE ADDRESS OF CHANNEL PROGRAM BUFFER
;*** NOTE THAT IF THE "SERIAL NUMBER" WERE MADE UP OF
;*** THE "DCU ADDRESS" PLUS THE MODULE ID (IE: AND NOT THE UNIT NUMBER)
;*** THEN "DUAL PORTING" WOULD WORK EVEN IF LAP PLUGS WERE SWAPPED.
HRRZ T2,P1 ;GET DCU ADDRESS
LSH T2,WIDUNA ;POSITION IT SO THAT T2=UNIT#0 ADDRESS
IORI T2,(P3) ;MERGE THIS UNIT NUMBER
SETZ T1, ;REALLY A ONE-WORD QUANTITY
DMOVEM T1,UDBDSN(U) ;SET SERIAL NUMBER IN UDB
JRST CPOPJ1## ;RETURN
;EXECUTE A SENSE OPERATION FOR A SPECIFIED ADDRESS.
;CALL:
; T1/ DEVICE ADDRESS
; P4/ CHANNEL PROGRAM BUFFER ADDRESS
; PUSHJ P,DSXSNU
; <ERROR RETURN>
; <NORMAL RETURN> ;T1/ CHANNEL STATUS BITS
DSXSNU: DPB T1,[POINT DVSDVA, SNSDVW(P4), DVNDVA] ;INSERT DEVICE ADDRESS
MOVE T1,P4 ;COPY CHANNEL PROGRAM ADDRESS
ADDI T1,SNSDVW ;POINT AT SENSE CMD
PJRST SAXRCP## ;RUN THE SENSE CHANNEL PROGRAM
;EXECUTE A NO-OP OPERATION FOR A SPECIFIED ADDRESS.
;CALL:
; T1/ DEVICE ADDRESS
; P4/ CHANNEL PROGRAM BUFFER ADDRESS
; PUSHJ P,DSXNOP
; <ERROR RETURN>
; <NORMAL RETURN> ;T1/ CHANNEL STATUS BITS
DSXNOP: DPB T1,[POINT DVSDVA, SNSDVW(P4), DVNDVA] ;INSERT DEVICE ADDRESS
DPB T1,[POINT DVSDVA, SNSNOP(P4), DVNDVA] ;INSERT DEVICE ADDRESS
MOVE T1,P4 ;COPY CHANNEL PROGRAM ADDRESS
PJRST SAXRCP## ;RUN THE NO-OP/SENSE CHANNEL PROGRAM
SUBTTL ONCE A SECOND CODE
DSXSEC: PUSHJ P,DSXTMO ;GO TIME OUT DISKS IF NECESSARY
SKIPL @KDBCHN(J) ;CHANNEL BUSY?
POPJ P, ;LEAVE IT ALONE
SKIPE T1,DSXNUM(J) ;GET BIT MASK
JFFO T1,DSXSE1 ;FIND FIRST UNIT NUMBER
HRRZS KDBNUM(J) ;INDICATE NO DRIVES TO CONFIGURE
POPJ P, ;DONE
DSXSE1: 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
REPEAT 0,<
MOVSS T2 ;MASSBUS UNIT = DRIVE NUMBER FOR DSX DISKS
PUSH P,T2 ;SAVE
MOVE T1,KDBDVC(J) ;DEVICE CODE
XMOVEI T2,DSXDSP ;DISPATCH
MOVE T3,KDBCHN(J) ;CHANNEL DATA BLOCK
PUSHJ P,AUTSET## ;SET UP CPU VARIABLES
EXCH P1,(P) ;SAVE P1, GET MASSBUS UNIT
PUSH P,KDBUNI(J) ;SAVE KDBUNI
MOVEM P1,KDBUNI(J) ;SET FOR THIS MASSBUS UNIT NUMBER (FOR RDMBR)
PUSHJ P,DSXUNI ;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
>; END REPEAT 0
POPJ P, ;*** FOR NOW
;ROUTINE TO INSPECT ALL ACTIVE DISKS ONCE-A-SECOND AND TIME THEM OUT IF NEEDED
;AS A BMUX KONTROLLER, FILIO WON'T DO THIS FOR US - AND THATS PROBABLY A FAVOR.
DSXTMO: PUSH P,U ;SAVE "REAL" U IN CASE CALLER CARES
MOVE T1,KDBIUN(J) ;GET POINTER TO UNIT LIST
DSKOFF ;NO INTERRUPTS
DSXTM1: SKIPE U,(T1) ;PICK UP A U
SKIPN T3,UNITIM(U) ;SKIP AND PICK UP FILSER TIMER
JRST DSXTM2 ;BRANCH IF NO SUCH UNIT
HRRO T4,UNIFNC(U) ;PICK UP FILSER OPERATION
JUMPL T4,DSXTM2 ;BRANCH IF UNIT WASN'T REALLY ACTIVE
SOSN T3 ;COUNT DOWN TIMER
PUSHJ P,DSXTM9 ;BRANCH TO FIX UP A HUNG UNIT
MOVEM T3,UNITIM(U) ;PUT BACK INCREMENTED TIMER
DSXTM2: AOBJN T1,DSXTM1 ;LOOP BACK FOR ALL UNITS
DSKON ;TURN INTERRUPTS BACK ON
PJRST UPOPJ## ;RETURN TO CALLER
DSXTM9: PUSHJ P,SETBSY ;GO SET BUSY BIT FOR THIS UNIT TO RESTART IT
PUSHJ P,FAKCUE ;FAKE UP A CUE AND GET SOMETHING STARTED
MOVEI T3,DSKTIM## ;AND PREPARE TO RESTART TIMER
POPJ P, ;
;TABLES OF BLOCKS PER UNIT INDEXED BY UNIT TYPE
BLKPRU: DEC 18*19*411 ;TYPE 0 (3330)
DEC 18*19*815 ;TYPE 1 (3331)
SUBTTL MAPIO AND FRIENDS
; ROUTINE TO SETUP UNITCP AND UNISDA
SETTCP: MOVE T1,UNIPCP(U) ;PICK UP PHYSICAL POINTER TO SA10 PROGRAM
MOVEM T1,UNITCP(U) ;SAVE AS FIRST FREE WORD
ADDI T1,CPALEN ;COMPUTE FIRST AVAILABLE SID-DATA AREA
MOVEM T1,UNISDA(U) ;SAVE POINTER
POPJ P, ;RETURN
; ROUTINE TO TAKE A DF10C (IE: DEFAULT CHANNEL) CHANNEL IO LIST
; AND CONVERT IT INTO A 3330/3331 CHANNEL PROGRAM.
;
; PUSHJ P,MAPIO
; <ONLY RETURN, EVERYTHING DONE>
;
; P1=POINTER TO CURRENT DF10 LIST, USED ONLY BY GETIOW ET AL
;
; P3=COUNT OF CONSECUTIVE WORDS IN A SINGLE DF10 IOWD, RETURNED BY GETIOW
; P4=ADDRESS OF CONSECUTIVE WORDS IN IOWD AS P3
; N.B.: GETIOW COMBINES CONSECUTIVE CONTIGUOUS DF10 IOWDS
MAPIO: PUSHJ P,SAVE4## ;SAVE SOME ACS
PUSHJ P,SAVR## ;SAVE SOME MORE
PUSH P,M ;SAVE STILL MORE
SKIPN P1,UNIDRB(U) ;PICK UP POINTER TO DRB FOR THIS UNIT
XCT DSXXWD ;++ XFER WITHOUT DRB
MOVE T1,DRBBLK##(P1) ;GET 1ST BLOCK IN XFER
MOVEM T1,UNICBN(U) ;SAVE CURRENT BLOCK NUMBER
MOVE P1,DRBPRG##(P1) ;PICK UP POINTER TO DF10C LIST FOR THIS UNIT
PUSHJ P,DSXDVC ;COMPUTE CORRECT XFER COMMAND
MOVE W,T1 ;SAVE COPY OF COMMAND IN W
SETZ M, ;M=THIS BLOCKS WORD COUNT SO FAR
MAPIO2: PUSHJ P,STOXFR ;INSERT A COPY OF THE XFER COMMAND
MAPIO3: PUSHJ P,GETIOW## ;GO GET AN IOWD PAIR T1=COUNT,T2=ADR
JUMPE T1,MAPIOD ;BRANCH IF "HALT"
DMOVE P3,T1 ;P3=COUNT, P4=ADR
MAPIO4: MOVEI T1,BLKSIZ ;GET SIZE OF A BLOCK
SUBI T1,(M) ;COMPUTE NUMBER OF WORDS NEEDED
CAILE T1,(P3) ;SKIP IF NEEDED IS LESS THAN AVAILABLE
JRST MAPIO5 ;BRANCH IF NEEDED IS MORE THAN AVAILABLE
;HERE WHEN #WORDS NEEDED TO FILL BLOCK IS LESS THAN WE GOT IN THIS IOWD
;IN THIS CASE, WE FINISH OUT THE BLOCK AND START ANOTHER.
MOVE T4,T1 ;SAVE A COPY OF THE WORDS TAKEN FROM P3/P4
PUSHJ P,STOIOW ;STORE FINAL IOWD FOR THIS BLOCK
PUSHJ P,STOXFR ;INSERT A NEW COMMAND
SUBI P3,(T4) ;ADJUST DF10 COUNT
ADDI P4,(T4) ;ADJUST DF10 ADDRESS
SETZ M, ;NEXT BLOCK HAS 0 WORDS IN IT, SO FAR
JUMPE P3,MAPIO3
JRST MAPIO4
;HERE WHEN THE #WORDS IN THIS IOWD PAIR CANNOT FINISH THIS BLOCK.
;IN THIS CASE, WE INSERT ANOTHER PARTIAL SIOWD AND GET ANOTHER DF10 IOWD
MAPIO5: MOVE T1,P3 ;COPY THE ACTUAL COUNT FOR THIS IOWD
ADD M,T1 ;COUNT THESE WORDS
TLO T1,(1B0) ;TURN ON PARTIAL FLAG
PUSHJ P,STOIOW ;STORE PARTIAL IOWD FOR THIS BLOCK
JRST MAPIO3 ;...GO GET ANOTHER DF10 IOWD
;HERE IF BOTH COUNT AND ADDRESS FIELDS WERE 0 - MUST BE A HALT
MAPIOD: JUMPE M,MAPIOX ;EXIT NOW IF NO PENDING BLOCK
;*** IBM DOCUMENT SAYS THAT STORAGE-CONTROL WILL TAKE CARE OF
;*** PADDING WITH ZEROES IF WE FEED IT LESS THAN "COUNT AREA DL" WORDS.
;*** ALSO, UUOCON/MONIO WILL HAVE ALREADY MADE SURE WE'RE A MULTIPLE OF
;*** THE SIZE OF A SINGLE BLOCK ANYWAY.
;*** MOVEI T1,BLKSIZ ;GET SIZE OF A BLOCK
;*** SUBI T1,(M) ;COMPUTE REMAINING WORDS IN BLOCK
JUMPN M,MAPIOY ;BRANCH IF LAST BLOCK WASN'T FILLED
MAPIOX: MOVSI T1,(BMXEND) ;GET A HALT
MOVEM R,UNITCP(U) ;GO BACK TO TOP OF CURRENT GROUP
PUSHJ P,STODVC ;STORE THE END CMD
PJRST MPOPJ## ;RESTORE M AND EXIT
;HERE IF LAST BLOCK WASN'T FILLED.
MAPIOY: SOS UNITCP(U) ;BACK UP "PC" TO POINT AT PARTIAL IOWD
PMOVE T1,UNITCP(U) ;GET PARTIAL IOWD
TLO T1,(1B0) ;SET "LAST IOWD" AFTER ALL
PMOVEM T1,UNITCP(U) ;STORE PARTIAL IOWD BACK AS A "LAST IOWD" INSTEAD
AOS UNITCP(U) ;PUT PC BACK TO CORRECT PLACE
MOVE T1,BMXWRD ;GET A HALT
PUSHJ P,STODVC ;INSERT THE HALT
PJRST MPOPJ## ;RESTORE M AND EXIT
; ROUTINE TO INSERT THE I/O CMD INTO THE CHANNEL PROGRAM
STOXFR: PUSHJ P,SAVT## ;SAVE ACS
MOVE R,UNITCP(U) ;THIS LOCATION GETS "HALT" IF NO MORE TO DO
PUSHJ P,STOPOS ;GO INSERT ANY NEEDED POSITIONING
MOVE T1,W ;GET THE READ/WRITE COMMAND
TRO T1,1 ;1 BIT USED BY FIXCWA
PUSHJ P,STODVC ;STORE DEVICE COMMAND
AOS UNICBN(U) ;ADVANCE BLOCK #
POPJ P,
; ROUTINE TO INSERT SEEK, SET-SECTOR, OR SEARCH-ID CMDS AS NEEDED
STOPOS: MOVE T1,UNIDRB(U) ;POINT AT DRB
MOVE T1,DRBBLK(T1) ;GET 1ST BLOCK OF XFER
CAMN T1,UNICBN(U) ;SKIP IF NOT 1ST BLOCK OF XFER
JRST STOPO2 ;NEEDED IF 1ST XFER OF PROGRAM
TLNN S,IO ;SKIP IF WRITE-CMD
POPJ P, ;EXIT IF READ CUZ READ CAN JUST READ-MULTITRAK
PUSHJ P,GETSSS ;GET T1=C, T2=H, T3=R, T4=S
JUMPN T3,STOPO1 ;BRANCH IF NOT RECORD0 OF NEW TRACK
STOPO2: PUSHJ P,STOSEK ;STORE SEEK
PUSHJ P,STOSS ;STORE SET-SECTOR
STOPO1: PUSHJ P,STOSID ;ALWAYS STORE SEARCH-ID-EQUAL IF WRITE COMMAND
POPJ P, ;EXIT
; ROUTINE TO INSERT A SEEK
STOSEK: PUSHJ P,GETSSS ;GET SEEK/SS/SID DATA
MOVE T4,UNISDA(U) ;POINT AT SEEK/SS/SID DATA AREA
SUBI T4,2 ;WE WILL USE 1 WORDS
MOVEM T4,UNISDA(U) ;UPDATE BOTH T4 AND UNISDA
LSH T1,4 ;T1=BYTE(8)0,0,C,C
PMOVEM T1,T4 ;INSERT 1ST WORD OF SEEK DATA (0,0,C,C)
ADDI T4,1 ;SETUP POINTER TO 2ND WORD
ROT T2,-^D 16 ;POSITION SO T2=BYTE(8)H,H,0,0
PMOVEM T2,T4 ;INSERT 2ND WORD OF SEEK DATA (H,H,-,-)
MOVE T1,UNISEK(U) ;GET VIRGIN SEEK CMD
PUSHJ P,STODVC ;INSERT SEEK CMD
MOVE T1,UNISDA(U) ;GET ADDRESS OF DATA
TLO T1,(SIOW 6,0) ;...CREATE 6 BYTE IOWD FOR BYTE(8)Z,Z,C,C,H,H
PJRST STODVC ;INSERT IOWD TO SEEEK DATA
; ROUTINE TO INSERT A SET-SECTOR COMMAND AND IT'S DATA (BYTE(8)S,-,-,-)
STOSS: MOVE T1,UNISS(U) ;GET SET-SECTOR COMMAND
PUSHJ P,STODVC ;INSERT SET-SECTOR COMAND
PUSHJ P,GETSSS ;GET SEEK/SS/SID DATA
MOVE T1,UNISDA(U) ;POINT AT SECTOR DATA
SUBI T1,1 ;BACKUP 1
MOVEM T1,UNISDA(U) ;UPDATE UNISDA
DPB T4,[POINT 8,T2,7] ;T2=BYTE(8)S,?,?,?
PMOVEM T2,T1 ;STORE T2 INTO DATA AREA
TLO T1,(SIOW 1,0) ;GET "IOWD" FOR 1 BYTE OF DATA
PJRST STODVC ;STORE IOWD ROR SS DATA
;ROUTINE TO INSERT A SEARCH-ID-EQUAL COMMAND AND IT'S BACKWARDS-TIC
STOSID: PUSHJ P,GETSSS ;GET SEEK/SS/SID DATA
MOVE T4,UNISDA(U) ;POINT AT DATA BUFFER
SUBI T4,2 ;NEED 2 WORDS FOR S-I-E ARGS
MOVEM T4,UNISDA(U) ;UPDATE UNISDA
ROT T1,-^D 16 ;MAKE T1=C,C,0,0
DPB T2,[POINT 16,T1,31] ;MAKE T1=C,C,H,H
PMOVEM T1,T4 ;INSERT DATA INTO BUFFER
ADDI T4,1 ;ADVANCE TO 2ND WORD OF DATA
ADDI T3,1 ;MAKE T3'S "R" START AT 1 NOT ZERO
ROT T3,-^D 8 ;MAKE T3=R,0,0,0
PMOVEM T3,T4 ;INSERT R INTO DATA BUFFER
MOVE T1,UNISIE(U) ;GET VIRGIN SEARCH ID
PUSHJ P,STODVC ;STORE DEVICE COMMAND
MOVE T1,UNISDA(U) ;GET ADDRESS OF DATA
TLO T1,(SIOW 5,0) ;5 BYTE WORD COUNT (IE: C,C,H,H,R)
PUSHJ P,STODVC ;STORE IOWD FOR SEARCH-ID-EQUAL
MOVE T1,UNITCP(U) ;GET ADDRESS OF NEXT CMD
SUBI T1,2 ;BACK UP SO WE ARE POINTING AT SEARCH-EQUAL
TLO T1,(TIC) ;AND CREATE A TIC CMD THAT GOES TO SEARCH-EQUAL
PUSHJ P,STODVC ;INSERT TIC TO JUMP BACK TO SEARCH EQUAL
POPJ P, ;RETURN
;ROUTINES TO INSERT WORDS INTO THE CHANNEL PROGRAM
STOIOW: IMUL T1,[-100,,0] ;POSITION THE COUNT FIELD
TDO T1,P4 ;INSERT THE ADDRESS FIELD
STODVC: PMOVEM T1,UNITCP(U) ;STORE COMMAND IN THE CHANNEL PROGRAM
AOS UNITCP(U) ;POINT AT NEXT WORD
POPJ P, ;RETURN
; ROUTINE TO SETUP TO DO A SENSE
SETSNS: PUSHJ P,SETTCP ;SETUP UNITCP/UNISDA(U)
MOVE T1,UNISNC(U) ;GET SENSE CMD
PUSHJ P,STODVC ;STORE IT
MOVE T1,UNISNC+1(U) ;GET IOWD
PUSHJ P,STODVC ;STORE IT
PUSHJ P,STOHLT ;STORE A HALT
PJRST SETDVP ;SETUP DEVL ENTRY AND EXIT
; ROUTINE TO INSERT A NO-OP
STONOP: MOVE T1,UNINOP(U) ;GET THE PROTOTYPE
JRST STODVC ;INSERT IT AND EXIT
; ROUTINE TO INSERT A HALT
STOHLT: MOVE T1,BMXWRD ;GET THE HALT
PJRST STODVC ;INSERT IT AND EXIT
; ROUTINE TO INSERT A READ/WRITE-RECORD-0
STORC0: PUSHJ P,STORR0 ;STORE READ-RECORD-0
PUSHJ P,STOSR0 ;STORE SEARCH-RECORD-0
PUSHJ P,STOWR0 ;STORE WRITE-RECORD-0
POPJ P, ;EXIT
; ROUTINE TO INSERT R-R-0
STORR0: MOVE T1,UNIRR0(U) ;GET CMD
PUSHJ P,STODVC ;STORE IT
MAP T1,UNIR0D(U) ;FIND ADDRESS OF R0 BUFFER
TLZ T1,(MP.NAD) ;TURN OFF MAP BITS
TLO T1,(SIOW 8,0) ;TURN ON WORD COUNT FIELD
PJRST STODVC ;STORE R-R-0
; ROUTINE TO INSERT S-R-0
STOSR0: PUSHJ P,STOSID ;INSERT SEARCH-ID
MOVE T1,UNISDA(U) ;GET FREE ID WORD
ADDI T1,1 ;POINT AT "R" WORD
SETZ T2, ;RECORD 0 DATA
PMOVEM T2,T1 ;FORCE DATA TO BE C,C,H,H,0
POPJ P, ;
; ROUTINE TO INSERT W-R-0
STOWR0: PUSHJ P,DSXDVC ;GET A WRITE COMMAND
TDO T1,[F.BYTE] ;SPECIFY BYTE MODE
PUSHJ P,STODVC ;STORE THE WRITE COMMAND
MAP T1,UNIR0D(U) ;POINT AT R0 BUFFER
TLZ T1,(MP.NAD) ;TURN OFF MAP BITS
TLO T1,(SIOW 8,0) ;TURN ON WORD COUNT FIELD
PJRST STODVC ;INSERT IT AND EXIT
;ROUTINE TO GET SEEK, SET-SECTOR, AND SEARCH-ID INFO
; T1/ GETS CYLINDER
; T2/ GETS HEAD
; T3/ GETS RECORD BASED ON 0
; T4/ SECTOR
SIZGAP==^D135 ;BYTES IN GAPS OF NORMAL RECORD
SIZR0==^D237 ;BYTES IN GAPS FOR R0 RECORD
SECTRK==^D128 ;SECTORS FOR TRACK
BYTTRK==^D13440 ;MAX BYTES PER TRACK
;*** CAN'T ACTUALLY USE UNYBPY/UNYBPT DURING ONCE ONLY ATTACH!
GETSSS: MOVE T1,UNICBN(U) ;GET CURRENT BLOCK NUMBER
;*** LDB T2,UNYBPY## ;GET BLOCKS PER CYLINDER
MOVEI T2,^D342 ;***
IDIV T1,T2 ;COMPUTE T1=CYL#, T2=REMAINDER
;*** LDB T3,UNYBPT## ;GET BLOCKS PER TRACK
MOVEI T3,^D18 ;***
IDIV T2,T3 ;COMPUTE T2=TRACK/HEAD, T3=RECORD
PUSH P,T3 ;SAVE R
IMULI T3,SIZGAP+BLKBYT ;(REC_NUM-1) * (BYTES_DISK_BLOCK)
ADDI T3,SIZR0 ;+ SIZE_OF_R0 = BYTE_#_OF_START_OF_BLOCK
IMULI T3,SECTRK ;* SECTORS_PER_TRACK
IDIVI T3,BYTTRK ;/ BYTES_PER_TRACK = SECTOR#
MOVE T4,T3 ;GET INTO T4
POP P,T3 ;RESTORE R INTO T3
POPJ P, ;RETURN
;*** GETSSS PROBABLY DEPENDS TOO MUCH ON PHYSICAL CONSTANTS OF THE 3330/3331
;*** PACK TO BE USEFUL AS/IS FOR OTHER DRIVES.
;ROUTINE TO TAKE THE SA10 UNDONE PC AND RESIDUAL COUNT
; AND USE IT TO CALCULATE AND UPDATE THE "CONTROL WORD" DATA FOR THE "DF10"
;SCAN THE SA10 PROGRAM FORWARDS UNTIL SIMULATED PC IS BEYOND THE DONE PC.
;KEEP TRACK OF EACH COMMAND AND COUNT BLKSIZ WORDS FOR EACH COMMAND.
FIXCWA: JUMPE S,FIXGUD ;BRANCH IF NO ERRORS
FIXBAD: SKIPN UNIDRB(U) ;SHOULD BE DRB IF XFER OP
STOPCD .+1,INFO,DSXXWD, ;++XFER WITHOUT DRB
PUSHJ P,SAVT## ;SAVE T ACS IF INTERRUPT LEVEL
PUSHJ P,SAVR## ;SAVE
FIXCW0: LDB R,[POINT 22,UNITCA(U),35];GET THE UNDONE PC
MOVE T1,UNIPCP(U) ;GET THE PROGRAM POINTER
ADDI T1,4 ;MAKE IT POINT AT S-I-E CMD
SETZ T4, ;ASSUME 0 WORDS IF HEADER ERROR
FIXCW1: PMOVE T2,T1 ;PICK UP THE "THING" THERE
CAME T2,BMXWRD ;SKIP IF A HALT (IE: A COMMAND)
CAML T1,R ;SKIP IF NOT YET THE UNDONE PC
JRST FIXCC1 ;BRANCH IF UNDONE PC
TLNN T2,(F.XEC) ;SKIP IF EXECUTE
AOJA T1,[TLC T2,(TIC) ;TURN OFF TIC BIT IF TIC
CAML T2,T1 ;SKIP IF BACKWARD TIC
MOVE T1,T2 ;"EXECUTE" FORWARD TICS
JRST FIXCW1] ;
TRNE T2,1 ;CHECK FOR AN XFER COMMAND
JRST FIXCW2 ;BRANCH IF AN XFER COMMAND
ADDI T1,2 ;MUST BE S-I-E, SS, SEEK, ETC, SO SKIP
JRST FIXCW1 ;...OVER THEM AND TRY AGAIN
FIXCW2: MOVEM T1,UNILPC(U) ;REMEMBER LAST PC OF XFER CMD
FIXCW3: ADDI T1,1 ;STEP TO NEXT IOWD
PMOVE T2,T1 ;GET IOWD
CAMN T1,R ;SKIP IF NOT UNDONE PC
JRST FIXCR1 ;BRANCH IF UNDONE PC
MOVE T3,T2 ;COPY THE IOWD
TLO T2,(1B0) ;TURN ON SIGN BIT
ASH T2,-^D24 ;T2=RIGHT JUSTIFIED -VE WORD COUNT
SUB T4,T2 ;T4=+VE WORD COUNT SO FAR
JUMPG T3,FIXCW3 ;BACK FOR MORE IF THIS IS PARTIAL IOWD
AOJA T1,FIXCW1 ;FOUND LAST IOWD, NOW STEP TO NEXT CMD
;HERE IF WE FIND THE UNDONE PC POINTING AT AN IOWD, MUST BE A RESIDUAL
;T1=PC OF IOWD
;T2=THE IOWD
;T3=JUNK
;T4=TOTAL WORDS SO FAR
FIXCR1: TLO T2,(1B0) ;MAKE IT APPEAR -VE EVEN IF NOT
ASH T2,-^D24 ;...SO THIS ASH WORKS
LDB T3,[POINT 12,UNITCA(U),11] ;GET RESIDUAL FROM SUBCHANNEL BLOCK
ASH T3,-^D24 ;RIGHT JUSTIFY IT TOO
SUB T2,T3 ;COMPUTE +VE XFER'ED ON THIS IOWD
ADD T4,T2 ;ADD INTO TOTAL
JRST FIXCC1 ;JOIN COMMAND CODE
;HERE IF WE FIND THE UNDONE PC POINTING AT A COMMAND
;NO RESIDUAL SINCE WE'RE POINTING AT A COMMAND, NOT IOWD
; NOW, SCAN DF10 PROGRAM UNTIL WE ENCOUNTER T4 WORDS
FIXCC1:
FIXCW5: SKIPN T1,UNIDRB(U) ;POINT AT DRB
XCT DSXXWD ;++XFER WITHOUT DRB ??
MOVE T2,T4 ;COPY WORD COUNT
IDIVI T2,^O200 ;COMPUTE # OF GOOD BLOCKS
ADDM T2,DRBGOD##(T1) ;SAVE GOOD COUNT IN DRB
MOVE T1,DRBPRG(T1) ;POINT AT DF10 PROGRAM
;SCAN DF10 PROGRAM UNTIL WE "XFER" (T4) WORDS
FIXCW6: LDB T2,[POINT 14,(T1),13] ;T2=WORD_COUNT
LDB T3,[POINT 22,(T1),35] ;T3=ADDRESS
JUMPE T2,FIXCW8 ;BRANCH IF HALT OR GOTO
IOR T2,[-1,,740000] ;EXTEND THE SIGN OF T2 TO 36 BITS
MOVNS T2 ;MAKE T2=+VE COUNT
MOVE R,T3 ;COPY BASE ADDRESS OF THIS XFER
CAMG T2,T4 ;SKIP IF THIS IOWD IS MORE THAN EENOUGH
AOJA T1,[ADD R,T2 ;...IF NOT ENUF, COMPUTE FINAL XFER ADR
SUB T4,T2 ;...IF NOT ENUF, ADJUST RUNNING REMAIN
JRST FIXCW6] ;...IF NOT ENUF, GO GET ANOTHER IOWD
ADD R,T4 ;COMPUTE FINAL XFER ADDRESS
FIXCW7: MOVE T2,KDBICP(J) ;T2=POINTER TO "DF10 ICW PAIR"
DPB T1,[POINT 14,1(T2),13] ;INSERT FINAL CWAD
DPB R, [POINT 22,1(T2),35] ;INSERT FINAL XFER ADDRESS
POPJ P,
FIXCW8: JUMPE T3,FIXCW7 ;BRANCH IF WE FOUND A DF10 HALT
MOVE T1,T3 ;PERFORM A "JMP" IF ONE IS FOUND
JRST FIXCW6 ;LOOP FOR MORE IOWD
;HERE IF THERE WASN'T AN ERROR, JUST USE COMPUTED DF10 WORD AND DRBGUD
FIXGUD: PUSHJ P,SAVT## ;SAVE T ACS IF INTERRUPT LEVEL
SKIPN T1,UNIDRB(U) ;POINT AT DRB
XCT DSXXWD ;++XFER WITHOUT DRB ??
MOVE T2,DRBNUM(T1) ;GET EXPECTED BLOCKS
MOVEM T2,DRBGOD(T1) ;MAKE IT ACTUAL BLOCKS
MOVE T2,KDBCHN(J) ;GET CHANNEL
MOVE T3,KDBICP(J) ;WHERE TO PUT IT
MOVE T2,CHNTCW(T2) ;GET WHAT FILIO WANTS
MOVEM T2,1(T3) ;PUT IT WHERE FILIO LOOKS
POPJ P,
$LOW ;LOW SEG STUFF
BMXWRD: BMXEND ;MUST BE LOW SEG SO SA10 GETS ACTUAL ADDR
$HIGH
SUBTTL THE END
DSXLIT: $LIT
DSXEND: END