mirror of
https://github.com/PDP-10/stacken.git
synced 2026-05-04 15:26:07 +00:00
1538 lines
57 KiB
Plaintext
1538 lines
57 KiB
Plaintext
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
|