1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-05-04 15:26:07 +00:00
Files
PDP-10.stacken/files/stacken-tape-backup/dskb:10_7/unsmon/dsxkon.mac
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

1538 lines
57 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE DSXKON - CONTROLLER ROUTINE FOR 3330/3331 DISK - V5
SUBTTL JOSEPH A. DZIEDZIC/JAD (DEC) & JEFF GUNTER/JEG (ADP) 23-AUG-88
;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,5 ;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)
;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
UNYHNM: POINT UNSHNM,UNISCY+1(U),UNNHNM ;HEAD NUMBER (SEEK/SEARCH)
UNYRNM: POINT UNSRNM,UNISCY+1(U),UNNRNM ;RECORD NUMBER (SEEK/SEARCH)
UNYSSC: POINT UNSSEC,UNISEC(U),UNNSEC ;SECTOR NUMBER
;$$*** MAKE MORE EXTENSIVE USE OF THE ATTACH CODE SO THAT SENSE'S, LONG
;$$*** MULTI_TRACK XFERS AND THE LIKE CAN BELIEVE THAT THEY'RE DOING IT
;$$*** LINEARLY.
;$$***
;$$*** MAKE ECC CORRECTION WORK BY STASHING INFO AT INT LEVEL, AND THEN
;$$*** MAKE THE WORK HAPPEN AT xxxECC TIME, AND ALWAYS RETURNS 0S BACK TO
;$$*** FILIO SO HE DOESN'T DO ANYTHING ON HIS OWN.
;$$***
;$$*** MAKE DSXPOS DO A READ/WRITE OF RECORD ZERO AFTER THE SEEK SO THAT
;$$*** WE CAN SEE WRITE-LOCK STATUS. COPY INTERVENTION-REQUIRED AND LOCKED
;$$*** INTO UDB, AND THEN CHECK IT AT OPRED/OPWRT TIME SO WE DO A "CONECT"
;$$*** ROUTINE TO CATCH PROBLEMS AT "UUO LEVEL" ALA RPXKON ET AL.
SUBTTL DEVICE-DEPENDENT DEFINITIONS
;3330 DEVICE COMMANDS
O.SEEK==7 ;SEEK
O.SIE==61 ;SEARCH ID EQUAL
O.READ==6 ;READ
O.WRIT==5 ;WRITE
O.SNS==4 ;SENSE I/O
O.SFM==37 ;SET FILE MASK
O.RREL==244 ;READ, RESET ERROR LOG
O.SSEC==43 ;SET SECTOR
O.RCAL==23 ;RECALIBRATE
O.NOP==3 ;NO-OP
O.MTRD==206 ;MULTI-TRACK READ
O.MTOP==200 ;MULTI-TRACK OPERATION ('OR' WITH READ OR SEARCH)
FM.WRI==200 ;FILE MASK TO ALLOW WRITES AND SEEKS
FM.WRF==100 ;FILE MASK TO ALLOW WRITE HEADERS AND SEEKS
BLKMSK==777 ;THIS PART OF DEVICE COMMAND WORD IS IGNORED
;BY SA10 AND WE USE IT TO STORE RELATIVE BLOCK #,
;USED TO CALCULATE # BLOCKS XFER'ED UP TO ERROR PC
;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
SN.TWE==1B31 ;TERMINATION WORD ERROR
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
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
DSXOVR:!BLOCK 1 ;COUNT OF OVERRUNS REPORTED IN STATISTICS
; LH=COMMAND RETRIES RH=DATA RETRIES
DSXUCC:!BLOCK 1 ;COUNT OF UNCORRECTABLE DATA CHECKS
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
UNICHP:! ;BEGINNING OF CHANNEL PROGRAM
UNISEK:!BLOCK 2 ;SEEK PROGRAM(SEEK, IOWD TO DATA)
UNINOP:!BLOCK 1 ;NO-OP TO FORCE WAIT FOR DEV-END OF SEEK
UNISTP:!BLOCK 1 ;BMUX-HALT OR TIC.+1
UNISET:!BLOCK 2 ;SET-SECTOR, IOWD TO SECTOR-DATA
UNISIE:!BLOCK 1 ;SEARCH ID EQUALS
UNISID:!BLOCK 2 ;POINTER TO ID DATA, TIC TO UNISIE
UNIIOT:!BLOCK 1 ;TRANSFER TO XFER PART OF CHAN PROG
UNISNP:!BLOCK 3 ;SENSE I/O PROGRAM, BMXEND
UNIRWC:!BLOCK 1 ;PROTOTYPE DVW FOR CHANNEL PROGRAMS
UNISND:!BLOCK SNSLEN ;SENSE DATA
;UNIFMW:! ;FILE MASK IN BITS 0-7
; UNNFMW==^D7 ;RIGHTMOST BIT FOR FILE MASK
UNISEC:!BLOCK 1 ;SECTOR NUMBER IN BITS 16-23
UNSSEC==^D8 ;SIZE OF SECTOR NUMBER FIELD
UNNSEC==^D23 ;RIGHTMOST BIT
UNISCY:!BLOCK 2 ;CYLINDER, HEAD, RECORD NUMBER (SEEK, SEARCH)
SCYLSH==4 ;BITS TO SHIFT TO PUT CYLINDER NUMBER IN POSITION
UNSHNM==^D16 ;SIZE OF HEAD FIELD
UNNHNM==^D15 ;RIGHTMOST BIT (UNISCY+1)
UNSRNM==^D8 ;SIZE OF RECORD NUMBER FIELD
UNNRNM==^D23 ;RIGHTMOST BIT (UNISCY+1)
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
UNPCUE==10 ; BIT SET IF RECEIVE CONTROL-UNIT-END
; OTHER UNITS MAY HAVE RECEIVED BUSY
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
UNINUM:!BLOCK 1 ;NUMBER OF BLOCKS TO TRANSFER (LIKE CHNNUM)
UNICSW:!BLOCK 1 ;SAVED COPY OF SACSW FOR DEBUGGING
UNITCA:!BLOCK 1 ;SAVED COPY OF SATCA FROM BEFORE SENSE COMMAND
UNICBN:!BLOCK 1 ;CURRENT BLOCK NUMBER (USED WHILE BUILDING PROGRAM)
UNIECN:!BLOCK 1 ;ERROR COUNTER BETWEEN RECALIBRATES
UNIRCT:!BLOCK 1 ;RECALIBRATE COUNTER
UNILPC:!BLOCK 1 ;PHYSICAL PC OF FAILING XFER CMD
UNICOE:!BLOCK 1 ;COUNT OF CORRECTABLE ERRORS CORRECTED WITH ECC
UNITCW:!BLOCK 1 ;EXPECTED TERMINAL COUNT,ADDR WORD
UNITNM:!BLOCK 1 ;NUMBER OF GOOD BLOCKS IN PREVIOUS PARTS OF XFER
; USED IF ECC APPLIED IN MIDDLE OF XFER
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
UNISDA:!BLOCK 1 ;PHYSICAL ADDRESS OF SEARCH-ID DATA BUFFER
;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 UDB
DSXUDB: UDBBEG (UNI,DSXULN)
SETWRD (UNIRCL,<F.XEC!F.CC!F.NMT!<O.RCAL>B15!<000>B23>) ;*
SETWRD (UNISEK,<F.XEC!F.CC!F.BYTE!<O.SEEK>B15!<000>B23>) ;*
SETWRD (UNISEK+1,<BYTE (1)1(DCSSIZ)-6(DCSADR)UNISCY>) ;&
SETWRD (UNINOP,<F.XEC!F.CC!F.NMT!<O.NOP>B15>) ;*
SETWRD (UNISET,<F.XEC!F.CC!F.BYTE!F.OFP!<O.SSEC>B15!<000>B23>) ;*
SETWRD (UNISET+1,<BYTE (1)1(DCSSIZ)-1(DCSADR)UNISEC>) ;&
SETWRD (UNISIE,<F.XEC!F.CC!F.BYTE!F.OFP!<O.SIE>B15!<000>B23>) ;*
SETWRD (UNISID,<BYTE (1)1(DCSSIZ)-5(DCSADR)UNISCY>) ;&
SETWRD (UNISID+1,<TIC UNISIE>) ;&
SETWRD (UNIIOT,<TIC 0>)
SETWRD (UNISNP,<F.XEC!F.CC!F.BYTE!<O.SNS>B15!<000>B23>) ;*
SETWRD (UNISNP+1,<BYTE (1)1(DCSSIZ)-^D24(DCSADR)UNISND>) ;&
SETWRD (UNISNP+2,<BMXEND>)
SETWRD (UNIRWC,<F.XEC!F.CC!F.SLI!<O.MTRD>B15!<000>B23>) ;*
UDBEND
;ENTRIES TAGGED BY "*" HAVE THE DEVICE ADDRESS INSERTED BY DSXUNI (DSXCFG)
;ENTRIES TAGGED BY "&" HAVE THE UDB ADDRESS INSERTED BY DSXUNI (DSXCFG)
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
;RETURN CPOPJ IF ECC WASN'T POSSIBLE (EG: ECC BAD BITS NOT IN DATA FIELD)
; CPOPJ1 WITH ERROR ALREADY CORRECTED (BUT FILIO DOESN'T KNOW IT)
; AND WITH T1 = -1 SO FILIO THINKS ECC WASN'T REALLY REQUIRED
DSXECC: 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
JRST DSXEC2 ;TELL FILIO EVERYTHING ISOK
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 DSXEC2 ;BRANCH (WE WIN!) IF NO BAD DATA
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
SOJG P3,DSXEC1 ;LOOP FOR ALL NIBBLES NEEDING FIXING
DSXEC2: MOVEI T1,BLKSIZ##+1 ;MAKE FILIO BELIEVE ERROR IS OUTSIDE DATA
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 (?)
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
;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
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: PUSH P,M ;SAVE UUO
PUSHJ P,SETCHP ;SET UP CHANNEL PROGRAM
POP P,M ;RESTORE UUO
DSXGO1: MOVEI T2,SO.GO ;GO FLAG
PUSHJ P,CNOSET ;SET FLAG AND DO THE CONO
MOVE T1,UNIDRB(U) ;RESTORE DRB, IF ANY
PJRST CPOPJ1## ;GIVE OK (SKIP) RETURN
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 ;SEE IF ALREADY TRIED SETTING GO FLAG AGAIN
TDNE T1,UNIFNC(U) ;SKIP IF NO
JRST DSXST1 ;YES, DO THE RECOVERY THING
IORB T1,UNIFNC(U) ;NO, REMEMBER THAT WE HAVE
PUSHJ P,CUERS2 ;SET TO RESTART CHANNEL PROG
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,BMXWRD ;GET ADDR OF NULL CHANNEL 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
;$$ HERE WHEN SA10 IS SO "HUNG" IT WON'T EVEN START ANY CHANNEL PROGRAM
;$$ COME HERE TO PICK UP SOME USEFULL INFO, TAKE STOPCODE DUMP,
;$$ AND THEN RESET THE AFFLICTED CHANNEL.
;$$ ITEMS WITH "**" ARE SAVED IN THE ACS IN THE DUMP.
;$$ (MIGHT BE WIPED OUT ON RESET OR DURING I/O TO SA10 DISK)
PUSHJ P,SAVE1## ;SAVE P1
;$$ THIS CODE HERE IS INTENDED TO LOAD P1 WITH DEVL ENTRY
;$$ FOR WHATEVER UNIT LAST TALKED TO THE SA10.
;$$ TO DO THIS RIGHT, WE MUST FIND BEGINNING OF DEVL LIST FOR THE
;$$ APPROPRIATE SUBCHANNEL AND SCAN THE CU ADDRESS FIELD BY HAND FOR A
;$$ MATCH (AND REMEMBER THAT THERE MIGHT NOT BE A MATCH)
;$$ MOVE T1,@DSXCSW(J) ;GET CHANNEL STATUS WORD
;$$ LDB T1,[POINT CSSUNI,T1,CSNUNI] ;GET UNIT NUMBER
;$$ MOVE P1,@DSXCHP(J) ;** P1=DEVICE LIST ENTRY FOR UNIT OF LAST INT
DSXST2: TRO T2,SO.CLK+SO.SDR+SO.DT0+DSKCHN## ;SA10 CONO TO STOP CLOCK
; AND SET TO READ MICRO-PC
XCT DSXCO2(J) ;DO THE CONO
XCT DSXDTI(J) ;** T1=DATAI=SA10 MICRO-PC
HLRZ T2,T1 ;T2=SUBCHANNEL NUMBER FROM DATAI
HRRZ T3,DSXSCH(J) ;T3=SUBCHANNEL WE WANT
CAME T2,T3 ;SKIP IF OUR SUBCHANNEL
JRST DSXST2 ;STEP CLOCK TILL GET TO OUR SUBCHANNEL
XCT DSXCI2(J) ;DO CONI INTO T2
MOVE T4,T2 ;** T4=SA10 CONI
TRO T2,SO.CLK+SO.SET+DSKCHN## ;CONO TO START CLOCK AGAIN
XCT DSXCO2(J) ;START SA10 CLOCK AGAIN
MOVEI T2,@DSXCSW(J) ;T2=ADDR OF CHANNEL STATUS WORD
MOVE T3,1(T2) ;** T3=TERMINATING COUNT,ADDR WORD
MOVE T2,(T2) ;** T2=CHANNEL STATUS WORD
STOPCD .+1,DEBUG,SAH, ;++ SA10 HUNG
MOVEI T2,SO.RCH ;FUNCTION TO RESET SUBCHANNEL
PUSHJ P,CNOCLR ;DO IT - SHOULD GET SA10 STARTED AGAIN
MOVE T2,DSXGSN(J) ;GET GLOBAL SA10 SUBCHANNEL
MOVE T2,SAXDVP##(T2) ;GET START OF DEVICE LIST FOR SUBCHANNEL
MOVEI T3,DL.TRM ;MARK EVERYTHING TERMINATED SO WONT RESET AGAIN RIGHT AWAY
DSXST3: PMOVE T1,T2 ;GET ANOTHER DEVICE LIST ENTRY
JUMPE T1,DSXST4 ;BRANCH IF OUT OF DEVICE LIST ENTRIES
DPB T3,DSYDLC ;STORE TERMINATED CODE
CAME T2,DSXDVP(U) ;SKIP IF THIS IS THE AFFLICTED UNIT
PMOVEM T1,T2 ;STORE CHANGED CODE BACK INTO DEVICE LIST
AOJA T2,DSXST3 ;LOOP FOR DEVICE LIST FOR THIS SUBCHANNEL
DSXST4: PUSHJ P,DSXGO1 ;SET GO FLAG - WILL GET DISK INTERRUPT
JFCL ;IGNORE SKIP RETURN
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
MOVE T1,@DSXCSW(J) ;GET CHANNEL STATUS WORD
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
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 DEVERR ;CONSIDER THAT A DEVICE ERROR
TLNE T1,(S.CUE) ;SKIP UNLESS CONTROL-UNIT-END
JRST HCUE ;GO HANDLE THAT
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
CHNERR:
DEVERR: TRO S,IODERR ;SOME ERROR DECTECTED
TRO F,SN.CDE ;CHANNEL DETECTED ERROR
;FALL INTO DSXRET
DSXRET: MOVSI T1,UNPCUE ;GET CONTROL-UNIT-END BIT
TDNN T1,UNIFNC(U) ;SKIP IF CONTROL-UNIT-END AFTER BUSY
JRST NOTCUE ;NO, NORMAL CASE
ANDCAM T1,UNIFNC(U) ;CLEAR IT NOW THAT IT'S PROCESSED
PUSHJ P,CUECHK ;SET UP UNITS WAITING BECAUSE BUSY
JUMPE T1,NOTCUE ;JUMP IF NO SUCH UNITS
PUSHJ P,DSXGO1 ;RESTART THOSE UNITS
JFCL ;
NOTCUE: MOVE T1,UNIFNC(U) ;GET CURRENT FUNCTION
TLNE T1,UNPSNS ;SKIP IF NOT SENSE AFTER UNIT CHECK
JRST DSXSNS ;IT WAS
MOVE T2,@DSXCSW(J) ;GET CHANNEL STATUS WORD
MOVEM T2,UNICSW(U) ;SAVE FOR DEBUGGING
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
JRST HCUE1 ;UNIT WAS BUSY, RETRY
TRO S,IODERR ;FORCE RETRY
TRO F,SN.RTR ;RETRY REQUESTED BY CONTROLLER
NOTCU1: MOVEI T2,@DSXCSW(J) ;GET ADDR OF CHANNEL STATUS WORD
MOVE T2,1(T2) ;GET TERMINAL COUNT AND COMMAND ADDR
MOVEM T2,UNITCA(U) ;SAVE FOR LATER IN CASE ANOTHER UNIT FINISHES
PMOVE T1,UNIDVP(U) ;GET DEVICE LIST ENTRY INTO T1
LDB T4,DSYDLC ;GET TERMINATING ADDRESS FROM DEVICE LIST
CAME T4,T2 ;COMPARE WITH STATUS TERMINATING ADDR
JRST NOTCU2 ;SHOULD BE THE SAME
LDB T4,DSYDLO ;GET SA10 STATUS FROM DEVICE LIST
CAIE T4,DL.TRM ;SKIP IF MARKED TERMINATED
NOTCU2: AOS DSXFST ;COUNT FUNNY STATUS CONDITIONS
MOVE T2,@DSXICW(J) ;GET INITIAL COMMAND WORD
;*** WRONG?
;*** CAME T2,DSXSTA(J) ;SHOULDN'T HAVE CHANGED
;*** AOS DSXFST ;FUNNY STATUS
MOVE T1,UNIFNC(U) ;RESTORE T1 AGAIN
MOVE T2,UNIDES(U) ;GET UNIT DESCRIPTION
TLNE T2,UNPOFL ;SKIP UNLESS UNIT WAS OFF-LINE
JRST DSXRT4 ;MUST NOW BE ON-LINE
MOVE T2,UNISTS(U) ;GET UNIT STATUS
CAIL T2,OWCOD ;SKIP IF NOT OPERATOR WAIT
JRST DSXRT3 ;OPERATOR WAIT
JRST DSXRT2 ;SKIP THIS
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
DSXRT4: MOVSI T1,UNPONP ;BIT TO MARK POSITION FOR ON-LINE INTERRUPT
MOVEM T1,UNIFNC(U) ;SET UNIFNC TO HANDLE NEXT INTERRUPT
MOVEI T1,^D411 ;GET A LARGE CYLINDER NUMBER
LSH T1,SCYLSH ;SHIFT INTO POSITION FOR SEEK ARGS
MOVEM T1,UNISCY(U) ;STORE FIRST WORD OF SEEK ARG
SETZM UNISCY+1(U) ;ZERO SECOND WORD OF SEEK ARG
MOVEI T1,UNISND-1(U) ;ADDR-1 OF PLACE TO PUT SEEK COMMAND
PUSH T1,UNISEK(U) ;PUT IN SEEK COMMAND
PUSH T1,UNISEK+1(U) ;AND DCW
PUSH T1,BMXWRD ;END OF CHAN PROG
MOVEI T2,UNISND(U) ;ADDR OF CHAN PROG
PUSHJ P,CPYWAT ;SET UP, START CHAN PROG, RETURN AFTER INT
;HERE AFTER SEEK
TLNN T1,(S.UC) ;SKIP IF UNIT CHECK CAME UP
JRST DSXR4L ;NO, MUST BE 3331 - GOOD THING WE CHECKED
MOVEI T2,UNISNP(U) ;ADDR OF SENSE CHAN PROG
PUSHJ P,CPYWAT ;SET UP, START CHAN PROG, RETURN AFTER INT
;HERE AFTER SENSE AFTER SEEK
MOVE T1,UNISND(U) ;GET SENSE DATA
TLNN T1,(S00REJ+S00IRQ) ;SKIP IF ILLEGAL SEEK
JRST DSXR4L ;MUST HAVE FAILED FOR SOME OTHER REASON
;HERE IF UNIT IS 3330
MOVEI T2,.UT330 ;UNIT TYPE FOR 3330
JRST DSXR4A ;SET IT UP
;HERE IF UNIT IS 3331
DSXR4L: MOVEI T2,.UT331 ;UNIT TYPE FOR 3331
DSXR4A: MOVE T1,BLKPRU(T2) ;GET BLOCKS/UNIT BASED ON UNIT TYPE
MOVEM T1,UNIBPU(U) ;STORE BLOCKS PER UNIT
MOVEM T1,UNIBPM(U) ;AND INCLUDING MAINTENANCE CYLINDERS
DPB T2,UNYUTP## ;STORE NEW UNIT TYPE
SETZM UNIFNC(U) ;MAKE SURE NEW INTS DONT DISPATCH
PUSHJ P,SNSCLR ;CLEAR OUT SENSE DATA TO PREVENT CONFUSION
DSXRT3: MOVEI T1,OPPOS ;MAKE LOOK LIKE FREE INTERUPT SINCE NOW ON-LINE
MOVEI T2,400000 ;GET SIGN BIT
MOVN T4,T3 ;MINUS UNIT NUMBER
LSH T2,(T4) ;POSITION AN ATTENTION FLAG
TRO T3,(T2) ;SO LOOKS LIKE RP10 FREE INTERRUPT
DSXRT2: MOVE T2,F ;NO SENSE DATA, USE INTERNAL FLAGS FOR "CONI"
JRST DSXRT1
$LOW
DSXFST: 0 ;COUNT OF TIMES FUNNY STATUS CAME UP
;EITHER DEVICE NOT MARKED TERMINATED, OR
;TERMINATING ADDR IN DEVICE LIST NOT SAME AS STATUS
;ALSO IF INITIAL COMMAND WORD CHANGES
LOWZRO: 0 ;A WORD CONTAINING ZERO
$HIGH
; HERE WHEN SENSE COMMAND DONE
DSXSNS: MOVSI T2,UNPSNS ;BIT MARKING SENSE COMMAND
ANDCAM T2,UNIFNC(U) ;CLEAR THE BIT SINCE THE SENSE IS DONE
MOVE T2,UNISND+S02WRD(U) ;GET WORD WITH CORRECTION BIT
TLNE T2,(D02COR) ;SKIP IF NOT A KNOWN CORRECTABLE ERROR
TRO S,IOECCX ;LET FILIO KNOW ECC CORRECTION WOULD WORK
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
DSXRT1: TLZ T1,-1 ;CLEAR LH JUNK
CAIE T1,OPRED ;READ OR
CAIN T1,OPWRT ; WRITE OPERATION?
PUSHJ P,FIXCWA ;YES, FIXUP DF10'S ICWA+1 WORD
HRL T1,T3 ;UNIT NUMBER TO LH T1
MOVE T3,@DSXCSW(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
PUSH P,T1 ;SAVE T1
PUSH P,T2 ;SAVE CONI
PUSHJ P,STSCLR ;CLEAR STATUS FLAG
POP P,T2 ;RESTORE CONI
POP P,T1 ; AND INTERRUPTING UNIT,,FUNCTION
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 TO HANDLE UNIT CHECK - DO A SENSE I/O COMMAND
HUC: MOVSI T1,UNPSNS ;FLAG TO REMEMBER DOING A SENSE
IORM T1,UNIFNC(U) ;STORE IT
MOVEI T1,@DSXCSW(J) ;ADDR OF CHANNEL STATUS WORD
MOVE T1,1(T1) ;GET TERMINAL COUNT, ADDRESS WORD
MOVEM T1,UNITCA(U) ;SAVE FOR LATER SENSE PROCESSING
;SINCE SENSE COMMAND WILL DESTROY
MOVEI T2,UNISNP(U) ;ADDR OF SENSE CHANNEL PROGRAM
PUSHJ P,SETDVL ;SET UP DEVICE LIST
MOVEI T2,SO.GO ;SET GO FLAG
PUSHJ P,CNOSET ;SET IT UP AND DO THE CONO
STSCLR: MOVEI T2,SO.STS ;STATUS FLAG
PJRST CNOCLR ;CLEAR STATUS FLAG
;HERE TO HANDLY BUSY - SET A FLAG TO RETRY LATER
HBUSY: AOS CNTBSY ;COUNT NUMBER OF TIMES GOT BUSY
MOVSI T1,UNPBSY ;SET FLAG TO REMEMBER BUSY OCCURED
IORM T1,UNIFNC(U) ;STORE IT
PJRST STSCLR ;CLEAR STATUS FLAG AND DISMISS
$LOW
CNTBSY: 0
$HIGH
;HERE TO HANDLE CONTROL UNIT END - SET UP TO RETRY UNITS THAT GOT A BUSY
HCUE: AOS CNTCUE ;COUNT NUMBER OF TIMES GO CUE
MOVE T2,U ;SAVE ORIGINAL UNIT
TLNE T1,(S.UC) ;UNIT-CHECK ALSO?
JRST HUC ;CU END + UNIT CHECK MEANS ERROR AFTER CHAN END
TLNN T1,(S.BUSY) ;BUSY ALSO?
JRST HCUE5 ;NO, HANDLE CU END
MOVSI T1,UNPBSY ;YES, CU END + BUSY MEANS TEMPORARILY BUSY
IORM T1,UNIFNC(U) ;PRETEND NOT BUSY ANYMORE
HCUE5: LDB T1,UNYUST## ;GET STATE OF UNIT
CAIE T1,UNVDWN ;SKIP IF UNIT IS DOWN
JRST HCUE6 ;OK AS IS
MOVE U,UNIKON(U) ;DOWN UNITS NOT IN KONTROLLER RING
CAIE U,(T2) ;SKIP IF BACK TO ORIGINAL SOME HOW
JRST HCUE5 ;TRY TO FIND A UNIT IN THE RING
JRST HCUE7 ;OH WELL
HCUE6: PUSHJ P,UCCHK ;CHECK IF ANY UNIT WAITING FOR SENSE
JRST HCUE2 ;YES, START IT FIRST
MOVSI T1,UNPCUE ;BIT SET IF ALREADY GOT C-U-E
TDNN T1,UNIFNC(U) ;SKIP IF SECOND TIME AROUND
JRST HCUE3 ;NO, DO THE NORMAL THING
PUSHJ P,CUEONE ;TRY ONE OTHER UNIT IF ANY WAITING
JRST HCUE2 ;ONE UNIT SET UP
HCUE3: PUSHJ P,CUERES ;SET UP CHANNEL PROG FOR RESTART IF HAD BUSY
JRST HCUE1 ;YES, ONLY DO THIS UNIT NOW
HCUE4: PUSHJ P,CUECHK ;NO, SET UP ALL OTHERS
JUMPN T1,HCUE2 ;JUMP IF ANY OTHER UNITS HAD BUSY
HCUE7: AOS CNTCUN ;COUNT TIMES CUE FOUND NO UNITS
PJRST STSCLR ;NO, JUST CLEAR STATUS FLAG
$LOW
CNTCUE: 0 ;TIMES GOT CUE
CNTCUN: 0 ;TIMES CUE FOUND NO UNITS
$HIGH
HCUE1: MOVSI T1,UNPCUE ;GET CUE BIT
IORM T1,UNIFNC(U) ;NOTE CONTROL-UNIT-END
HCUE2: PUSHJ P,DSXGO1 ;START OPERATION AGAIN
JFCL ;FORGET PROBLEMS FOR NOW
PJRST STSCLR ;CLEAR STATUS FLAG AND DISMISS
;SUBROUTINE TO CHECK IF ANY UNIT WAITING FOR SENSE COMMAND
UCCHK: PUSH P,U ;SAVE FIRST UNIT
UCCHK1: MOVSI T1,UNPSNS ;GET BIT INDICATING WAITING FOR SENSE
PUSHJ P,CUERS1 ;SEE IF THIS UNIT WAITING FOR SENSE
JRST CUEON2 ;YES, NOTE OTHER UNITS MAY BE WAITING FOR CUE
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 SET UP ONE UNIT OTHER THAN THE ONE CAUSING THE INTERRUPT
CUEONE: PUSH P,U ;SAVE U
CUEON1: MOVE U,UNIKON(U) ;MOVE TO NEXT UNIT
CAMN U,(P) ;SKIP IF NOT BACK TO ORIGINAL UNIT
PJRST UPOPJ1## ;YES, NO OTHER UNITS
PUSHJ P,CUERES ;SEE IF WAITING
SKIPA ;YES
JRST CUEON1 ;NO, LOOP THROUGH UNITS ON CONTROLLER
CUEON2: MOVSI T1,UNPCUE ;GET CUE BIT
ORM T1,UNIFNC(U) ;SET FOR THAT UNIT
JRST UPOPJ## ;RESTORE U AND RETURN
;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 WAITING FOR BUSY ELSE SET UP CH PRG
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
CUERS1: TDNN T1,UNIFNC(U) ;SKIP IF SET FOR THIS UNIT
JRST CPOPJ1## ;NO, UNIT NOT WAITING AFTER BUSY
ANDCAB T1,UNIFNC(U) ;CLEAR BIT AND GET THE OTHERS
CUERS2: MOVEI T2,UNICHP(U) ;NORMAL CHANNEL PROGRAM ADDR FOR THIS UNIT
TLNE T1,UNPSNS ;SKIP UNLESS WAS DOING A SENSE COMMAND
MOVEI T2,UNISNP(U) ;IN WHICH CASE CHANNEL PROG IS DIFFERENT
TLNN T1,UNPONP ;SKIP IF POSITION FOR ON-LINE INTERRUPT
TLNE T1,UNPCPY ;SKIP UNLESS WAS IN CPY ROUTINE
MOVE T2,UNIACP(U) ;GET ADDR REMEMBERED
PJRST SETDVL ;SET UP DEVICE LIST AGAIN
;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, WILL CAUSE CONTROL ERROR
;NOTE NEXT REAL OP ON THIS UNIT WILL GET UNIT CHECK
;EQUIPMENT CHECK WILL BE UP, HOPEFULLY RETRY WILL WIN
;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 CHNERR ;RETURN CHANNEL ERROR
;HERE WHEN INTERRUPT FOR UNKNOWN UNIT - COUNT AND IGNORE
;UNIT NUMBER IN T3
DSXIIN: AOS CNTIIN ;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
PJRST STSCLR ;CLEAR STATUS AND RETURN
$LOW
CNTIIN: 0 ;TIMES GOT INT FOR UNKNOWN UNIT
$HIGH
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
MOVE T1,UNISNP(U) ;GET SENSE COMMAND
AND T1,[<377>B23] ;ISOLATE DEVICE ADDR
TLO T1,(F.NMT!F.XEC!F.SLI!<O.NOP>B15) ;MAKE NO-OP
MOVEM T1,UNISND(U) ;STORE IN AVAILABLE PLACE FOR THIS UNIT
MOVE T1,BMXWRD ;END OF CHAN PROG
MOVEM T1,UNISND+1(U) ;STORE THAT
MOVEI T2,UNISND(U) ;ADDR OF CHAN PROG
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
MOVEI T2,UNISNP(U) ;ADDR OF SENSE CHAN PROG
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
MOVEI T1,^D411 ;GET LARGE CYLINDER NUMBER
LSH T1,SCYLSH ;SHIFT INTO POSITION FOR SEEK CMD
MOVEM T1,UNISCY(U) ;STORE FIRST WORD OF SEEK ARGS
SETZM UNISCY+1(U) ;ZERO SECOND WORD OF SEEK ARGS
MOVEI T1,UNISND-1(U) ;ADDR-1 FOR PLACE TO PUT CHAN PROG
PUSH T1,UNISEK(U) ;STORE SEEK COMMAND
PUSH T1,UNISEK+1(U) ;AND DCW
PUSH T1,BMXWRD ;TERMINATE CHAN PROG
MOVEI T2,UNISND(U) ;ADDR OF CHAN PROG
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
MOVEI T2,UNISNP(U) ;ADDR OF SENSE CHAN PROG
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
PJRST STSCLR ;CLEAR THE STATUS FLAG 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: MOVEM T2,UNIACP(U) ;SAVE ADDR OF CHAN PROG IN CASE BUSY
PUSHJ P,SETDVL ;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
PUSHJ P,STSCLR ;CLEAR STATUS FLAG
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
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
DSXERR: MOVEI T1,3 ;GIVE UP
POPJ P, ;RETURN
DSXRDC:
DSXWTC:
DSXUNL: STOPCD .,STOP,DSX3IF, ;++ 3330 ISN'T FANCY
;SUBROUTINE TO CONSTRUCT CHANNEL PROGRAM
;ARGS: T1=ADDRESS OF DRB IF XFER, OR ZERO IF POS/RCL
; T4=FILSER OPCODE
; U=UNIT
; DATA CHAIN LIST ALREADY SET UP
SETCHP: HRRZM T4,UNIFNC(U) ;REMEMBER FILSER FUNCTION
MOVEM T1,UNIDRB(U) ;SAVE DRB ADDRESS (IF ANY)
MOVEI T2,UNICHP(U) ;ADDR OF NORMAL CHANNEL PROGRAM
PJUMPE T1,SETPOS ;SETUP A POSITIONING PROGRAM
PJRST SETXFR ;SETUP AN XFER PROGRAM
; ROUTINE TO SETUP A POSITION PROGRAM
SETPOS: MOVE T1,UNIBLK(U) ;PICK UP THE BLOCK NUMBER
PUSHJ P,SETSIE ;SETUP SEEK DATA
MOVE T1,[BMXEND] ;BMUX END
MOVEM T1,UNISTP(U) ;STOP PROGRAM AFTER SEEK
MOVEI T2,UNICHP(U) ;POINT AT SEEK PROGRAM
CAIN T4,OPCAL ;SKIP IF POSITION
MOVEI T2,UNIRCL(U) ;POINT AT RECAL PROGRAM
PJRST SETDVL ;SETUP TO RUN SEEK PROGRAM
; ROUTINE TO SETUP A DATA XFER PROGRAM
SETXFR:
;*** FROM DRB
MOVE T3,DRBNUM##(T1) ;T3=# OF BLOCKS TO XFER
SKIPN T3 ;SKIP IF WE FOUND SOMETHING TO DO
STOPCD SETDVL,INFORM,SETXF0, ;++ DRBNUM =0 IN DSXKON
PUSHJ P,MAPIO ;CALL LOCAL MAPIO TO CONVERT DF10C TO SA10B
MOVE T1,UNIPCP(U) ;GET ADDRESS OF CHANNEL PROGRAM AREA
TLO T1,(TIC) ;SET UP TRANSFER IN CHANNEL
MOVEM T1,UNIIOT(U) ;MAKE NORMAL CHANNEL PROGRAM BRANCH TO I/O PROG
MAP T1,UNISET(U) ;GET PHYSICAL ADDRESS OF SET-SECTOR CMD
TLZ T1,(MP.NAD) ;TURN OFF MAP ATTRIBUTE BITS
TLO T1,(TIC) ;FINALLY, T1="TIC .+1"
MOVEM T1,UNISTP(U) ;DON'T STOP PROGRAM AFTER SEEK!
MOVEI T2,UNICHP(U) ;RESET T2 TO POINT AT NORMAL CHANNEL PROGRAM
PJRST SETDVL ;SETUP TO RUN XFER PROGRAM
;FALL INTO SETDVL
;SUBROUTINE TO SET UP DEVICE LIST FOR A UNIT
;ARGS: T2=VIRTUAL ADDRESS OF CHANNEL PROGRAM
; STORE ADDRESS, THEN SET "START DEVICE" IN DEVICE LIST
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
TDO T3,T2 ;INSERT THE PROGRAM ADRESS
PMOVEM T3,UNIDVP(U) ;INSERT NEW DEVICE LIST ENTRY IN LIST
MOVEM T3,UNIDVL(U) ;SAVE FOR DEBUGGING
POPJ P, ;RETURN
;SUBROUTINE TO COMPUTE AND STORE SEEK AND SEARCH DATA
;ARGS T1=BLOCK NUMBER
SETSIE: LDB T2,UNYBPY## ;BLOCKS PER CYLINDER
IDIV T1,T2 ;T1=CYLINDER NUMBER, T2=REM
MOVEM T1,UNICYL(U) ;REMEMBER OUR CYLINDER
LSH T1,SCYLSH ;SHIFT FOR CHANNEL PROGRAM DATA
MOVEM T1,UNISCY(U) ;STORE IN CHANNEL PROGRAM
LDB T3,UNYBPT## ;GET BLOCKS PER TRACK
IDIV T2,T3 ;T2=TRACK (HEAD) NUMBER, T3=REC NUMBER
DPB T2,UNYHNM ;STORE HEAD NUMBER IN CHANNEL PROG
AOJG T3,SETSI1 ;RECORD ID (FIRST REC IS REC 1)
STOPCD .+1,DEBUG,IR0, ;++ I/O TO RECORD R0
MOVEI T3,1 ;SET A BETTER RECORD
SETSI1: DPB T3,UNYRNM ;STORE RECORD ID
POPJ P, ;RETURN
;SUBROUTINE TO COMPUTE AND STORE SECTOR NUMBER
;ARGS: T3=RECORD ID
SIZGAP==^D135 ;TOTAL NUMBER OF BYTES IN GAPS FOR A NORMAL RECORD
SIZR0==^D237 ;TOTAL NUMBER OF BYTES IN R0 INCLUDING ITS GAPS, HOME, ETC
SECTRK==^D128 ;SECTORS PER TRACK
BYTTRK==^D13440 ;TOTAL NUMBER OF BYTES PER TRACK
SECERR: STOPCD .+1,DEBUG,ISN, ;++ ILLEGAL SECTOR NUMBER
MOVEI T3,1 ;SET A BETTER SECTOR NUMBER
SETSEC: SOJL T3,SECERR ;JUMP IF ILLEGAL SECTOR NUMBER
IMULI T3,SIZGAP+BLKBYT ;(REC NUM -1) * (TOTAL BYTES FOR A NORMAL RECORD)
ADDI T3,SIZR0 ;PLUS BYTES FOR R0 = BYTE NUM OF BEGINNING OF REC
IMULI T3,SECTRK ;TIMES SECTORS PER TRACK
IDIVI T3,BYTTRK ;THUS GET (BYTE NUM/TOTAL BYTES PER TRACK) * SECTORS
DPB T3,UNYSSC ;STORE SECTOR NUMBER
POPJ P, ;RETURN
;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.WRIT>B15-<O.MTRD>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,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)
MOVSI T1,KOPECA ;GET THE "I KNOW HOW TO DO ECC" BIT
IORM T1,KONECA(J) ;...AND SET IT IN OUR KDB
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
ADDM U,UNISEK+1(U)
ADDM U,UNISET+1(U)
ADDM U,UNISID(U)
ADDM U,UNISID+1(U)
ADDM U,UNISNP+1(U)
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, UNISET(U), DVNDVA]
DPB T1,[POINT DVSDVA, UNISIE(U), DVNDVA]
DPB T1,[POINT DVSDVA, UNISNP(U), DVNDVA]
DPB T1,[POINT DVSDVA, UNIRWC(U), DVNDVA]
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
HRRZ T1,P2 ;GET DCU ADDRESS
LSH T1,WIDUNA ;POSITION
HRRZ T2,P3 ;GET PHYSICAL DRIVE NUMBER
IOR T2,T1 ;BUILD FAKE DRIVE S/N SINCE IT CAN'T BE READ
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: 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
;TABLES OF BLOCKS PER UNIT INDEXED BY UNIT TYPE
BLKPRU: DEC 18*19*411 ;TYPE 0 (3330)
DEC 18*19*815 ;TYPE 1 (3331)
; 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
; P2=POINTER TO CURRENT SA10B CHANNEL PROGRAM WORD, USED ONLY BY MAPIO
; 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
MOVE P1,UNIDRB(U) ;PICK UP POINTER TO DRB FOR THIS UNIT
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
MOVE P2,UNIPCP(U) ;PICK UP PHYSICAL POINTER TO SA10 PROGRAM
MOVE T2,P2 ;PICK UP COPY OF PHYSICAL ADDR OF PROGRAM
ADDI T2,CPALEN-2 ;COMPUTE FIRST AVAILABLE SID-DATA AREA
MOVEM T2,UNISDA(U) ;SAVE POINTER
PUSHJ P,SETSIE ;SETUP THE SEEK CMD IN THE UDB
PUSHJ P,SETSEC ;SETUP THE SET-SECTOR COMMAND IN THE UDB
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
MAPIO1:
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,MAPIO0 ;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 WHEN THE WORD COUNT WAS ZERO FOR A DF10 IOWD
MAPIO0:
;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
MOVE P2,R ;GO BACK TO THE BEGINNING OF THE CURRENT GROUP
PUSHJ P,STODVC ;STORE THE END CMD
POPJ P, ;ALL DONE
;HERE IF LAST BLOCK WASN'T FILLED.
MAPIOY: SUBI P2,1 ;BACK UP "PC" TO POINT AT PARTIAL IOWD
PMOVE T1,P2 ;GET PARTIAL IOWD
TLO T1,(1B0) ;SET "LAST IOWD" AFTER ALL
PMOVEM T1,P2 ;STORE PARTIAL IOWD BACK AS A "LAST IOWD" INSTEAD
ADDI P2,1 ;RESTORE PC TO CURRENT PLACE
MOVE T1,BMXWRD ;GET A HALT
PJRST STODVC
; ROUTINES TO INSERT NON-IOWD CHANNEL COMMANDS INTO THE 3330/3331 PROGRAM
STOXFR: MOVE R,P2 ;THIS LOCATION GETS "HALT" IF NO MORE TO DO
TROE W,1 ;SKI IF FIRST BLOCK
TLNN S,IO ;SKIP IF READ COMMANDS NEEDED
SKIPA
PUSHJ P,STOSID ;INSERT A SEARCH-ID-EQUAL FOR WRITES
MOVE T1,W ;GET THE READ/WRITE COMMAND
PUSHJ P,STODVC ;STORE DEVICE COMMAND
AOS UNICBN(U) ;ADVANCE BLOCK #
POPJ P,
STOSID: MOVE T1,UNISIE(U) ;GET VIRGIN SEARCH ID
TLZ T1,(F.OFP) ;TURN OFF "START AT BYTE 3" BIT
PUSHJ P,STODVC ;STORE DEVICE COMMAND
MOVSI T1,777300 ;-5 BYTE COUNT (IE: C C H H R)
OR T1,UNISDA(U) ;ADD IN ADDRESS OF SEARCH DATA
PUSHJ P,STODVC ;STORE IOWD FOR SEARCH-ID-EQUAL
PUSHJ P,SETSID ;SETUP SEARCH DATA, UPDATE UNISDA
MOVE T1,P2 ;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
STOIOW: IMUL T1,[-100,,0] ;POSITION THE COUNT FIELD
TDO T1,P4 ;INSERT THE ADDRESS FIELD
STODVC: PMOVEM T1,P2 ;STORE COMMAND IN THE CHANNEL PROGRAM
AOJA P2,CPOPJ## ;RETURN
;ROUTINE TO INSERT SEARCH ID DATA
SETSID: MOVE T1,UNICBN(U) ;GET CURRENT BLOCK NUMBER
LDB T2,UNYBPY## ;GET BLOCKS PER CYLINDER
IDIV T1,T2 ;COMPUTE T1=CYL#, T2=REMAINDER
ROT T1,-^D16 ;T1=LEFT JUSTIFIED CYL# IN 16 BIT FIELD
LDB T3,UNYBPT## ;GET BLOCKS PER TRACK
IDIV T2,T3 ;COMPUTE T2=TRACK/HEAD, T3=RECORD
ADDI T3,1 ;T3=RECORD NUMBER (START AT 1, NOT 0)
DPB T2,[POINT 16,T1,31];INSERT HEAD INFO INTO T1
MOVE T2,UNISDA(U) ;GET POINTER TO SEARCH DATA BUFFER
PMOVEM T1,T2 ;INSERT 1ST WORD OF IT
ADDI T2,1 ;POINT AT NEXT WORD
ROT T3,-^D8 ;LEFT JUSTIFY RECORD NUMBER IN 8 BIT FIELD
PMOVEM T3,T2 ;INSERT 2ND WORD OF IT
SUBI T2,3 ;UPDATE T2 TO NEW UNISDA
MOVEM T2,UNISDA(U) ;UPDATE UNISDA
POPJ P, ;RETURN
;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: PUSHJ P,SAVT## ;SAVE ACS - INTERUPT LEVEL CARES
JUMPE S,FIXGUD ;BRANCH IF NO ERRORS
PUSHJ P,SAVR## ;SAVE
FIXCW0: LDB R,[POINT 22,UNITCA(U),35];GET THE UNDONE PC
MOVE T1,UNIPCP(U) ;GET THE PROGRAM POINTER
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)
CAMN T1,R ;SKIP IF NOT THE UNDONE PC
JRST FIXCC1 ;BRANCH IF UNDONE PC
TRNE T2,1 ;CHECK FOR AN XFER COMMAND
JRST FIXCW2 ;BRANCH IF AN XFER COMMAND
ADDI T1,3 ;MUST BE SEARCH-ID, IOWD, TIC, 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: MOVE T1,UNIDRB(U) ;POINT AT DRB
MOVE T2,T4 ;COPY WORD COUNT
IDIVI T2,^O200 ;COMPUTE # OF GOOD BLOCKS
MOVEM 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: MOVE T1,UNIDRB(U) ;POINT AT DRB
MOVE T2,DRBBLK##(T1) ;GET EXPECTED WORDS
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
$LIT
DSXEND: END