Trailing-Edge
-
PDP-10 Archives
-
bb-bt99p-bb
-
autcon.x22
There are 2 other files named autcon.x22 in the archive. Click here to see a list.
TITLE AUTCON AUTOCONFIGURATION AND COMMON DEVICE I/O ROUTINES - V151
SUBTTL D. MASTROVITO/DPM 14-FEBRUARY-89
SEARCH F,S,DEVPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1986,1988>
XP VAUTCN,151
AUTCON::ENTRY AUTCON
SUBTTL AUTOCONFIGURATION -- AUTADN/AUTDDN - ALLOCATE/DEALLOCATE DEVICE NUMBER
;ALLOCATE THE NEXT AVAILABLE KONTROLLER OR DEVICE NUMBER FROM THE
;MONGEN'ED DEVICE TABLE
;CALL: PUSHJ P,AUTADN/AUTDDN
;
;ON RETURN, T1 HAS THE NEW NUMBER AND THE DATA BASE HAS BEEN UPDATED
;IF ALLOCATING. T1 INDETERMINATE IF DEALLOCATING.
AUTDDN::TDZA T1,T1 ;DEALLOCATE
AUTADN::MOVEI T1,1 ;ALLOCATE
PUSHJ P,SAVE3## ;SAVE SOME ACS
MOVEI P3,(T1) ;SAVE FLAG
MOVE P1,.CPCPN## ;START WITH OUR CPU NUMBER
PUSHJ P,ADNBPT ;FORM A BYTE POINTER
LDB T1,P1 ;GET NUMBER RESERVED PER-CPU
IFE FTXMON,<AOS P1> ;ADVANCE POINTER
IFN FTXMON,<AOS P2> ;ADVANCE POINTER
LDB T2,P1 ;GET ALLOCATED PER-CPU SO FAR
XCT ADNCNT(P3) ;COUNT UP OR DOWN
DPB T2,P1 ;UPDATE COUNTER
CAIL T2,0 ;KEEP IT A
CAILE T2,(T1) ; SMALL INTEGER
SKIPA ;MUST ADJUST
JRST AUTAD2 ;GO FINISH UP
;HERE WHEN A PER-CPU COUNTER OVERFLOWS
AUTAD1: SYSPIF ;INTERLOCK
IFE FTXMON,<MOVE T2,(P1)> ;GET SYSTEM-WIDE COUNT
IFN FTXMON,<MOVE T2,(P2)> ;GET SYSTEM-WIDE COUNT
LSH T2,-1 ;POSITION
XCT ADNCNT(P3) ;COUNT UP OR DOWN
CAIL T2,0 ;KEEP IT A
CAILE T2,(T1) ; SMALL INTEGER
ANDI T2,37 ;AVOID OVERFLOW OR UNDERFLOW
DPB T2,P1 ;UPDATE PER-CPU COUNT
SYSPIN ;RELEASE INTERLOCK
;HERE TO UPDATE THE HIGHEST NUMBER IN SYSTEM
AUTAD2: JUMPE P3,CPOPJ## ;RETURN IF DEALLOCATING
MOVEI P1,6 ;SPECIAL BYTE
PUSHJ P,ADNBPT ;GENERATE A BYTE POINTER
IFE FTXMON,<AOS P1> ;ONLY CARE ABOUT SECOND ENTRY
IFN FTXMON,<AOS P2> ;ONLY CARE ABOUT SECOND ENTRY
LDB T1,P1 ;GET HIGH VALUE SO FAR
CAILE T2,(T1) ;INCREMENTING
DPB T2,P1 ;UPDATE
AOS NUMKON ;COUNT A CONTROLLER
PUSH P,T2 ;SAVE COUNTER
PUSHJ P,ADNFIX ;FIXUP GLOBAL COUNTERS IF NECESSARY
POP P,T1 ;GET RESULT
SOJA T1,CPOPJ## ;START COUNTING FROM ZERO, AND RETURN
;INSTRUCTIONS TO COUNT
ADNCNT: SOS T2 ;COUNT DOWN
AOS T2 ;COUNT UP
SUBTTL AUTOCONFIGURATION -- AUTADP - GENERATE ALLOCATED DEVICE POINTER
;ROUTINE TO GENERATE THE ALLOCATED DEVICE BYTE POINTER TO THE
;PER-CPU COUNTERS
;CALL: MOVE T1, CPU NUMBER OR 6 FOR SYSTEM-WIDE COUNTER
; PUSHJ P,AUTADP
;
;ON RETURN, T1 & T2 CONTAIN A TWO-WORD BYTE POINTER FOR EXTENDED MONITORS,
;OR T1 CONTAINS A ONE-WORD BYTE POINTER FOR NON-EXTENDED MONITORS
AUTADP::PUSHJ P,SAVE2## ;SAVE P1 AND P2
MOVEI P1,(T1) ;COPY CPU NUMBER
PUSHJ P,ADNBPT ;GENERATE BYTE POINTER
DMOVE T1,P1 ;COPY RESULTS
POPJ P, ;AND RETURN
;ROUTINE TO COMPUTE A BYTE POINTER GIVEN A CPU NUMBER IN P1
ADNBPT: AOS P1 ;PRE-INCREMENT
MOVSI P2,(POINT 5,) ;5-BIT BYTES
ADJBP P1,P2 ;POINT TO THE BYTE FOR THIS CPU
MOVE P2,.CPDRV## ;DRIVER DISPATCH
IFE FTXMON,<
HRR P1,DRVMDT(P2) ;POINT TO TABLE
>; END IFE FTXMON
IFN FTXMON,<
MOVE P2,DRVMDT(P2) ;POINT TO TABLE
TLO P1,(1B12) ;TWO-WORD BYTE POINTER
TRZ P1,-1 ;CLEAR RH JUNK FOR AESTHETIC REASONS ONLY
>; END IFN FTXMON
POPJ P, ;RETURN
SUBTTL AUTOCONFIGURATION -- AUTAMR - ALLOCATE UNIBUS MAPPING REGISTERS
;ROUTINE TO ALLOCATE UNIBUS MAPPING REGISTERS
;CALL: MOVE T1, UNIBUS ADAPTER NUMBER
; MOVE T2, NUMBER OF REGISTERS DESIRED
; PUSHJ P,AUTAMR
; <NON-SKIP> ;INSUFFICIENT FREE REGISTERS
; <SKIP> ;T1 = UNIBUS ADDRESS OF FIRST REGISTER ALLOCATED
;T2 = NUMBER OF REGISTERS ALLOCATED
;T3 = INITIAL ELEVEN ADDRESS
IFN FTKS10,<
AUTAMR::SKIPE T1 ;MUST BE A VALID UBA NUMBER
CAILE T1,MAXUBA ;...
POPJ P, ;SORRY
MOVE T3,.CPUMR##-1(T1) ;GET HIGHEST MAPPING REGISTER ALLOCATED
ADD T3,T2 ;NUMBER THEY WANT
CAILE T3,UBAPGS ;EXCEEDED THE NUMBER OF MAPPING REGISTERS?
POPJ P, ;YES, RETURN
EXCH T3,.CPUMR##-1(T1) ;GET FIRST REGISTER FOR CALLER, RESET HIGHEST
MOVSS T1 ;PUT UBA NUMBER IN LEFT HALF
HRRI T1,UBAEXP(T3) ;GET UNIBUS ADDRESS OF FIRST MAPPING REGISTER
IMULI T3,UBAMUL ;COMPUTE INITIAL ELEVEN ADDRESS
JRST CPOPJ1## ;SKIP RETURN
>; END IFN FTKS10
SUBTTL AUTOCONFIGURATION -- AUTCHN - BUILD A CHANNEL DATA BLOCK
;BUILD A CHANNEL DATA BLOCK
;CALL: MOVE T1, CHANNEL BITS
; PUSHJ P,AUTCHN
; <NON-SKIP> ;NO CORE
; <SKIP> ;.CPCHA = CHANNEL ADDRESS
AUTCHN::PUSHJ P,SAVE2## ;SAVE P1 AND P2
XMOVEI P1,SYSCHN##-CHNSYS ;SET PREDECESSOR
MOVE P2,T1 ;COPY CHANNEL BITS
IFN FTCIDSK,<
TRNE P2,400000 ;SPECIAL CI DISK HACKERY?
JRST AUTCH2 ;YES, DON'T CHECK FOR DUPLICATES
>; END IFN FTCIDSK
AUTCH1: MOVE P1,CHNSYS(P1) ;GET CHANNEL ADDRESS
HLRZS P1 ;ADDRESS IN LH QUANTITY
JUMPE P1,AUTCH2 ;MUST CREATE ONE
MOVE T1,.CPDVC## ;GET <CPU>B2 + (<DEVICE CODE>/4 OR UBA ADDR)
CAME T1,CHNDVC(P1) ;KNOWN CHANNEL?
JRST AUTCH1 ;KEEP SEARCHING
MOVEM P1,.CPCHA## ;SAVE FOR DRIVERS THAT MIGHT CARE
JRST CPOPJ1## ;AND RETURN
AUTCH2: MOVEI T1,CHNLEN ;LENGTH OF A CHANNEL DATA BLOCK
PUSHJ P,GETCOR ;ALLOCATE CORE
POPJ P, ;NOT AVAILABLE
MOVE P1,T2 ;COPY ADDRESS
MOVEI T1,SYSCHN##-CHNSYS ;SET PREDECESSOR
SYSPIF ;INTERLOCK CHAIN SCANNING
AUTCH3: SKIPN T2,CHNSYS(T1) ;LINK TO NEXT CHANNEL
JRST AUTCH4 ;END OF CHAIN
HLRZ T1,T2 ;COPY
JRST AUTCH3 ;SEARCH FOR END OF CHAIN
AUTCH4: HRLM P1,CHNSYS(T1) ;SAVE CHANNEL DATA BLOCK ADDRESS
SYSPIN ;RELEASE INTERLOCK
MOVEM P1,.CPCHA## ;SAVE FOR DRIVERS THAT MIGHT CARE
SETOM CHNBSY(P1) ;INDICATE IDLE
MOVE T1,.CPDVC## ;GET <CPU>B2 + (<DEVICE CODE>/4 OR UBA ADDR)
MOVEM T1,CHNDVC(P1) ;SAVE FOR AUTOCONFIGURE LATER ON
HLLZM P2,CHNTYP(P1) ;SAVE CHANNEL BITS
MOVEI T1,CHVIFP##
HRRM T1,CHNIFP(P1)
MOVEI T1,CHVIFT##
MOVEM T1,CHNIFT(P1)
MOVEI T1,3 ;INITIAL FAIRNESS FOR SWAPPING
MOVEM T1,CHNIFS(P1)
IFN FTKS10,<
LDB T1,[POINT 3,.CPDVC##,17] ;GET UNIBUS ADAPTER NUMBER
HRLI T1,UNBSTW ;INSERT ADDRESS OF UNIBUS STATUS REGISTER
MOVSM T1,CHNUBA(P1) ;STORE IN CHN
>; END IFN FTKS10
MOVEI T1,CHNKTB(P1) ;GET ADDRESS OF TABLE OF KONTROLLERS
MOVEM T1,CHNTBP(P1) ;STORE IN CHN
AOS CNFCHN## ;ONE MORE CHANNEL IN THE SYSTEM
AOS T1,.CPASC## ;ONE MORE CHANNEL ON THIS CPU
DPB T1,CHYSCN ;STORE IN CHN
MOVN T2,T1 ;GET -CHANNEL NUMBER
MOVSI T1,(CP.CS0) ;BIT FOR CHANNEL 0
LSH T1,(T2) ;POSITION BIT
TLO T1,(CP.PXX) ;INCLUDE MEMORY SCAN BIT
MOVEM T1,CHNCSR(P1) ;SAVE FOR ERROR REPORTING
JRST CPOPJ1## ;SKIP RETURN
SUBTTL AUTOCONFIGURATION -- AUTCLK - QUEUE UP A CLOCK REQUEST
;QUEUE UP A CPU-SPECIFIC CLOCK REQUEST FOR AUTOCONFIGURE PROCESSING
;AT A LATER TIME. THE INTENT IS TO ALLOW DEVICE CONFIGURING TO OCCUR
;WHEN THE SYSTEM IS CONSIDERED UP AND TIMESHARING. IT IS HERE PRIMARILY
;TO ACCOMODATE RSX-20F DEVICES, BUT CAN BE USED ANY TIME A DRIVER CHOOSES
;TO DELAY CONFIGURING UNTIL A LATER TIME.
;CALL: MOVE T1, CALL-BACK ROUTINE
; MOVE T2, TICKS TO WAIT
; PUSHJ P,AUTCLK
; <RETURN>
;
;WHEN THE DRIVER ROUTINE IS CALLED, THE AUTCON DATA BASE WILL BE INTERLOCKED.
;IT IS THE RESPONSIBILITY OF THE DRIVER TO CALL AUTSET, AS THE NECESSARY
;INFORMATION TO DO THAT IS KNOWN ONLY TO THE DRIVER.
AUTCLK::PUSH P,T3 ;SAVE T3
MOVE T3,.CPCPN## ;CPU NUMBER
TLO T1,400000 ;WILL BE A CPU-SPECIFIC REQUEST
DPB T3,[POINT 3,T1,3] ;STORE CPU NUMBER
HRLI T2,CLOCKR ;INCLUDE OUR CLOCK PROCESSING ENTRY POINT
SYSPIF ;INTERLOCK QUEUE
SETZM CLKMIN##(T3) ;INDICATE NEW REQUEST IN QUEUE
IDPB T2,CLOCK## ;STORE ROUTINE,,#TICKS
IDPB T1,CLOCK## ;STORE CPU + DATA (DRIVER ROUTINE)
SYSPIN ;RELEASE INTERLOCK
POP P,T3 ;RESTORE T3
POPJ P, ;AND RETURN
;HERE WHEN CLOCK REQUEST TIMES OUT
CLOCKR: SE1ENT ;RUN IN SECTION ONE
MOVE T2,TICSEC## ;TIME TO WASTE INCASE CANNOT INTERLOCK
PUSHJ P,AUTLOK ;INTERLOCK THE DATA BASE
JRST AUTCLK ;AT INTERRUPT LEVEL, SO TRY AGAIN LATER
PUSHJ P,(T1) ;CALL DRIVER
JFCL ;IGNORE ERRORS
PJRST AUTULK ;RELEASE INTERLOCK AND RETURN
SUBTTL AUTOCONFIGURATION -- AUTCPU - CONFIGURE ALL DEVICES ON A CPU
AUTCPU::SE1ENT ;RUN IN SECTION ONE
PUSHJ P,SAVE4## ;SAVE SOME ACS
CONI PI,.CPATP## ;SAVE STATE OF PI SYSTEM
CONO PI,PI.TFP+177 ;TURN OFF ALL CHANNELS
MOVEI T1,^D30 ;NUMBER OF SECONDS PROTOCOL PAUSE WILL LAST
IMUL T1,TICSEC## ;COMPUTE TICKS AND STUFF IN OK
MOVNM T1,.CPOK## ; WORD SO CLOCK1 WON'T CALL BRKLOK
PUSHJ P,AUTLOK ;GET DATA BASE INTERLOCK
JRST .-1 ;REALLY WANT THE INTERLOCK
IFN FTKL10,<PUSHJ P,DTESPP##> ;ENTER PROTOCOL PAUSE
PUSHJ P,CTYERM## ;SET UP CTY TYPEOUT ROUTINE
IFN FTKL10,<MOVEI T1,<M.FDVC##/4>-1> ;INITIAL DEVICE CODE
IFN FTKS10,<MOVSI T1,1> ;START AT FIRST UNIBUS ADAPTER
MOVE T2,.CPCPN## ;INCLUDE CPU NUMBER
DPB T2,[POINT 3,T1,2] ; IN BITS 0-2
MOVEM T1,.CPDVC## ;SAVE
IFN FTKS10,<
AUTCP0: LDB T1,[POINT 3,.CPDVC##,17] ;GET UNIBUS ADAPTER NUMBER
HRLI T1,UNBSTW ;ADDRESS OF THE STATUS REGISTER
MOVSS T1 ;SWAP HALVES
PUSHJ P,UBGOOD## ;THIS UNIBUS ADAPTER EXIST?
JRST [MOVSI T1,1 ;NON-EXISTANT ADAPTER, BUMP ADAPTER NUMBER
ADDM T1,.CPDVC##
JRST AUTCP5] ;CONTINUE
HRRI T1,M.FDVC##-4 ; SYMBOLIZE - GET STARTING UNIBUS ADDRESS
HRRM T1,.CPDVC## ;RESET FOR THIS ADAPTER
>; END IFN FTKS10
;LOOP CALLING EACH DRIVER FOR EACH DEVICE THAT EXISTS
AUTCP1: MOVE T1,DRVLST ;INITIAL DRIVER DISPATCH
MOVEM T1,.CPDRV## ;SAVE
;SEARCH FOR AN EXISTANT DEVICE
AUTCP2:
IFN FTKL10,<
AOS T1,.CPDVC## ;GET PREVIOUS DEVICE CODE
HRRZS T1 ;ISOLATE <DEVICE CODE>/4
CAILE T1,M.LDVC##/4 ;CHECKED ALL DEVICE CODES?
>; END IFN FTKL10
IFN FTKS10,<
MOVEI T1,4 ;AMOUNT TO BUMP UNIBUS ADDRESS
ADDB T1,.CPDVC## ;ADVANCE TO NEXT UNIBUS ADDRESS
HRRZ T2,T1 ;ISOLATE UNIBUS ADDRESS
TRNE T2,-1 ;QUIT IF WE'VE GONE PAST THE END
CAILE T2,M.LDVC## ;CHECKED ALL ADDRESSES?
>; END IFN FTKS10
JRST AUTCP5 ;FINISH UP
MOVE T2,.CPDRV## ;REDUNDANT, BUT THAT'S OK
SETZ T3, ;NO CHANNEL DATA BLOCK YET
PUSHJ P,AUTSET ;SET UP CPU VARIABLES
PUSHJ P,CHKDEV ;SEE IF DEVICE REALLY EXISTS (SAVE PIA TOO)
JRST AUTCP2 ;IT DOESN'T
;LOOP OVER EACH DRIVER WHEN A DEVICE IS DETECTED
AUTCP3:
IFN FTKL10,<
XCT .CPCNI## ;CONI DEV,T1
MOVE T2,T1 ;COPY TO THE PROPER PLACE
HRRZ T1,.CPDVC## ;GET <DEVICE CODE>/4 AGAIN
>; END IFN FTKL10
IFN FTKS10,<LDB T1,[POINT 21,.CPDVC##,35]> ;GET UNIBUS ADDRESS
MOVE T3,.CPDRV## ;GET DRIVER DISPATCH
MOVEI T4,DR.SFT ;BIT TO TEST
TDNE T4,DRVCNF(T3) ;SOFTWARE DEVICE?
JRST AUTCP4 ;ON THIS PASS
PUSHJ P,@DRVCFG(T3) ;ELSE CALL DRIVER
JRST AUTCP1 ;CONFIGURED--NO MORE FOR THIS DEVICE
AUTCP4: MOVE T1,.CPDRV## ;GET DRIVER DISPATCH
SKIPN T1,DRVLNK(T1) ;AND LINK TO NEXT
JRST AUTCP1 ;NO MORE, SO ON TO THE NEXT DEVICE
MOVEM T1,.CPDRV## ;SAVE FOR NEXT TIME
JRST AUTCP3 ;TRY ANOTHER DRIVER
AUTCP5:
IFN FTKS10,<
LDB T1,[POINT 3,.CPDVC##,17] ;GET UNIBUS ADAPTER NUMBER
CAIG T1,MAXUBA ;DONE ALL 4 ADAPTERS?
JRST AUTCP0 ;NO, START OVER WITH THAT UNIBUS ADAPTER
>; END IFN FTKS10
MOVE T2,DRVLST ;HEAD OF CHAIN
AUTCP6: MOVEM T2,.CPDRV## ;SAVE DRIVER DISPATCH
MOVEI T1,DR.SFT ;BIT TO TEST
TDNE T1,DRVCNF(T2) ;SOFTWARE DEVICE?
PUSHJ P,@DRVCFG(T2) ;YES
JFCL ;IGNORE FOOLISHNESS
MOVE T2,.CPDRV## ;GET DRIVER DISPATCH
SKIPE T2,DRVLNK(T2) ;AND LINK TO NEXT
JRST AUTCP6 ;CHECK OUT NEXT DRIVER
IFN FTNET,<PUSHJ P,NETDEV##> ;UPDATE DEVICE COUNTS IN HOST NDB
IFN FTKL10,<PUSHJ P,DTERPP##> ;CLEAR PROTOCOL PAUSE
PUSHJ P,AUTULK ;GIVE UP DATA BASE INTERLOCK
MOVSI T1,(CR.ATO) ;GET OUR BIT
ANDCAM T1,.CPRUN## ;LET THE DRIVERS DO THEIR THING
MOVE T1,.CPATP## ;GET SAVED PI SYSTEM STATE
ANDI T1,177 ;ISOLATE CHANNELS
CONO PI,PI.TNP(T1) ;TURN THEM BACK ON AGAIN
POPJ P, ;RETURN
SUBTTL AUTOCONFIGURATION -- AUTCSO - LINK UP CONSO SKIP CHAIN
;ROUTINE TO LINK INTERRUPT CODE INTO THE CONSO SKIP CHAIN
;CALL: MOVE T1, INTERRUPT CODE ADDRESS
; MOVE T2, PI CHANNEL
; PUSHJ P,AUTCSO
IFN FTKL10,<
AUTCSO::PUSHJ P,SAVE1## ;SAVE P1
MOVE P1,T1 ;COPY ARGUMENT
MOVE T1,T2 ;COPY PIA
LSH T1,1 ;TIMES TWO
ADDI T1,40-1 ;COMPUTE INTERRUPT LOCATION
ADD T1,.CPEPT## ;INDEX INTO THE EPT
HRRZ T1,1(T1) ;XPCW ADDRESS
MOVE T2,4(T1) ;START OF CONSO SKIP CHAIN
MOVEI T3,(P1) ;COPY START OF INTERRUPT CODE
HRLI T3,(JRST) ;FORM INSTRUCTION
MOVEM T3,4(T1) ;LINK AT FRONT OF CHAIN
MOVEM T2,1(P1) ;LINK EXISTING CHAIN FOLLOWING THIS CODE
POPJ P, ;RETURN
> ;END IFN FTKL10
SUBTTL AUTOCONFIGURATION -- AUTDDB - BUILD A DDB
;ROUTINE TO CREATE A DDB
;CALL: MOVE T1, SIXBIT GENERIC DEVICE NAME,,PHYSICAL DRIVE NUMBER
; MOVE T2, STATION OR ZERO (IF LOCAL)
; PUSHJ P,AUTDDB
; <NON-SKIP> ;NO CORE AVAILABLE
; <SKIP> ;AC F = NEW KDB ADDRESS
AUTDDB::PUSHJ P,SAVE4## ;SAVE SOME ACS
MOVE T4,.CPDRV## ;DRIVER DISPATCH
MOVE P1,DRVDDB(T4) ;COPY PROTOTYPE DDB ADDRESS
MOVE P2,DRVDDL(T4) ;COPY PROTOTYPE DDB LENGTH
DMOVE P3,T1 ;COPY NAME & DRIVE, STATION
TRNN P4,-1 ;STATION NUMBER SUPPLIED?
HRR P4,JBTLOC## ;DEFAULT TO LOCAL
MOVE F,P1 ;SETUP F
LDB T1,PDVTYP## ;GET DEVICE TYPE INDEX
SKIPE DDBTAB(T1) ;TABLE ALREADY SETUP?
JRST AUTDD1 ;YES
MOVEM P1,DDBTAB(T1) ;REMEMBER PROTOTYPE DDB ADDRESS
MOVEM P2,DDBSIZ(T1) ;REMEMBER PROTOTYPE DDB LENGTH
AUTDD1: MOVE T1,P2 ;GET NUMBER OF WORDS
PUSHJ P,GETCOR ;ALLOCATE CORE
POPJ P, ;CAN'T DO IT
MOVE F,T2 ;COPY ADDRESS
IFE FTXMON,<
MOVSI T1,(P1) ;PROTOTYPE ADDRESS
HRRI T1,(F) ;DESTINATION
ADDI P2,(F) ;COMPUTE END OF BLT
BLT T1,-1(P2) ;COPY
> ;END IFE FTXMON
IFN FTXMON,<
MOVEI T1,(P2) ;LENGTH
MOVE T2,P1 ;PROTOTYPE ADDRESS
MOVE T3,F ;DESTINATION
EXTEND T1,[XBLT] ;COPY
> ;END IFN FTXMON
HRRZ T1,P3 ;PHYSICAL DRIVE NUMBER
MOVEI T2,DR.NET ;BIT TO TEST
TDNN T2,DRVCNF(T4) ;WANT ANF-10 STATION NUMBERS IN NAME?
JRST AUTDD2 ;NO
DPB P4,[POINT 6,T1,32] ;INCLUDE IT
JRST AUTDD3 ;FORCE OCTAL NUMBER
AUTDD2: MOVEI T3,DR.DDN ;BIT TO TEST
TDNE T3,DRVCNF(T4) ;WANT DECIMAL DEVICE NAME?
SKIPA T2,[EXP DECNAM] ;YES
AUTDD3: MOVEI T2,OCTNAM ;MAKE IT OCTAL
PUSHJ P,(T2) ;GENERATE SIXBIT NUMBER
MOVEI T2,DR.NET ;BIT TO TEST
TDNN T2,DRVCNF(T4) ;WANT ANF-10 STATION NUMBERS IN NAME?
JRST AUTDD4 ;NO
TRNE T1,7700 ;IF ONLY ONE CHARACTER,
TRNE T1,77 ;OR THREE,
JRST AUTDD4 ;THERE'S NOTHING TO FIX UP
LSH T1,-6 ;WRONG--RIGHT-ADJUST
TRO T1,'0 ' ;INSERT THE LEADING ZERO IN THE STATION NUMBER
AUTDD4: HLL T1,P3 ;INCLUDE GENERIC PORTION
MOVEM T1,DEVNAM(F) ;STORE
DPB P3,PUNIT## ;STORE PHYSICAL DRIVE NUMBER AS UNIT
DPB P4,PDVSTA## ;STORE STATION NUMBER FOR NETSER
IFN FTMP,<
LDB T1,DEYCPF## ;GET PROTOTYPE'S OWNING CPU
CAIGE T1,CPFBIT## ;LEAVE CPFBIT & CPFBOO ALONE
MOVE T1,.CPCPN## ;NO, GET OUR CPU NUMBER
DPB T1,DEYCPF## ;SAVE IN DDB
CAIL T1,CPFBIT## ;IN RANGE OF REAL CPU NUMBERS?
SETZ T1, ;NO, USE CPU0'S INTERLOCKS
LSH T1,3 ;OFFSET TO RIGHT BLOCK OF PI CHANNELS
HRRZ T2,DEVCPU(F) ;GET PI CHANNEL NUMBER
CAIL T2,100 ;IS IT STILL A CHANNEL?
SUBI T2,INTL0## ;NO, CONVERT TO AN OFFSET
ANDI T2,7 ;MAKE SURE JUST A PI CHANNEL
ADDI T1,INTL0##(T2) ;INDEX INTO TABLE
HRRM T1,DEVCPU(F) ;STORE
> ;END IFN FTMP
MOVE T4,.CPDRV## ;DISPATCH
MOVEM T4,DEVDRV(F) ;SAVE FOR DIAG. UUO, ETC.
MOVE T1,F ;DDB ADDRESS
MOVE T2,DRVDDL(T4) ;DDB LENGTH
MOVEI T3,DR.UCD ;BIT TO TEST
TDNE T3,DRVCNF(T4) ;WANT TO UNCACHE THE DDB?
PUSHJ P,UNCACH ;UNCACHE THE ADDRESS RANGE
AOS (P) ;WE'RE SUCCEEDING
PJRST LNKDDB ;LINK UP THE DDB & RETURN
SUBTTL AUTOCONFIGURATION -- AUTLNK - LINK A DDB
;SUBROUTINE TO LINK A DDB INTO ITS CANONICAL PLACE IN DEVLST
;CALL: MOVEI F,DDB-ADDRESS
; PUSHJ P,AUTLNK
; <RETURN>
AUTLNK::PUSHJ P,SAVE4## ;PRESERVE SOME REGISTERS
LNKDDB: LDB P1,PDVTYP## ;DEVICE TYPE
LDB P2,PUNIT## ;UNIT NUMBER
LDB T1,PDVSTA## ;STATION NUMBER
HRL P2,T1 ;MERGE WITH UNIT
MOVE P3,F ;SAVE NEW DDB ADDRESS
SETZ P4, ;NO KNOWN PREDECESSOR YET
DDBSRL ;INTERLOCK DDB SCANNING
SKIPE F,DDBTAB(P1) ;IF NO FIRST DDB OF THIS KIND,
SKIPE DEVNAM(F) ;OR IF IT'S NOT A PROTOTYPE,
TRNA ;WE HAVE TO LOOK FOR A PREDECESSOR
JRST LNKDD5 ;GO WITH THE PROTOTYPE
HLRZ T2,DEVNAM(P3) ;GET THE GENERIC NAME FOR THIS DDB
SKIPN T2 ;IF NONE,
SKIPN T2,DEVDRV(P3) ;CHECK THE DRIVER DISPATCH TABLE
TRNA ;SIGH
HLRZ T2,DRVNAM(T2) ;GET GENERIC NAME FROM DRIVER IF NONE IN DDB
SETZ F, ;NO STARTING POINT YET
SKIPL T1,GENPTR## ;AOBJN INDEXER FOR GENTAB
JRST LNKDD3 ;NOTHING YET--JUST LINK IN WHERE WE FIT
LNKDD1: CAMG T2,GENTAB##(T1) ;IS THIS STILL SOME SORT OF PREDECESSOR ENTRY?
JRST LNKDD2 ;NO--GO DO OUR THING
SKIPE GENTAB##+1(T1) ;IF THERE IS A POINTER,
MOVE F,GENTAB##+1(T1) ;UPDATE OUR G.L.B.
AOBJP T1,LNKDD2 ;ACCOUNT FOR TWO WORD ENTRIES
AOBJN T1,LNKDD1 ;AND TRY AGAIN
;FALL THROUGH
LNKDD2: JUMPE F,LNKDD3 ;IF NO STARTING POINT, USE BEG OF CHAIN
LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIN T1,(P1) ;IF ALREADY MATCHING,
JRST LNKDD5 ;JUST USE THIS AS THE PREDECESSOR
LNKDD3: SKIPN F ;FOUND STARTING POINT YET?
XMOVEI F,DEVLST##-DEVSER ;NO, USE START OF CHAIN
HLRZ P4,DEVSER(F) ;GET NEXT POSSIBLE CANDIDATE
JUMPE P4,LNKDD5 ;OFF THE END--GO INSERT HERE
EXCH P4,F ;GET PREDECESSOR & CURRENT
HLRZ T1,DEVNAM(F) ;GET GENERIC NAME FROM DDB
SKIPN T1 ;IF NOT THERE,
SKIPN T1,DEVDRV(F) ;TRY FOR A DRIVER DISPATCH TABLE
TRNA ;IN DDB OR NO DEVDRV
HLRZ T1,DRVNAM(T1) ;FETCH FROM DRIVER
CAMLE T2,T1 ;HAVE WE FOUND OUR NICHE?
JRST LNKDD3 ;NO--KEEP LOOKING
;YES--FALL INTO LNKDD4
LNKDD4: LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIE T1,(P1) ;MATCHING DEVICE TYPES?
JRST LNKDD6 ;NO--INSERT HERE
HLRZ T1,DEVNAM(F) ;GET GENERIC NAME
HLRZ T2,DEVNAM(P3) ;...
CAIE T1,(T2) ;MATCHING GENERIC NAMES?
JRST LNKDD5 ;NO--TRY THE NEXT DDB
LDB T1,PUNIT## ;GET UNIT NUMBER
LDB T2,PDVSTA## ;GET STATION NUMBER
HRL T1,T2 ;MERGE
CAMG P2,T1 ;MAINTAIN ASCENDING STATION AND UNIT ORDER
JRST LNKDD6 ;INSERT HERE
LNKDD5: SKIPE P4,F ;SAVE THIS ADDR AS PREVIOUS
HLRZ F,DEVSER(F) ;ADDR OF NEXT DDB
JUMPN F,LNKDD4 ;LOOP BACK
LNKDD6: JUMPN P4,LNKDD8 ;JUST GO LINK UP IF WE KNOW THE PREDECESSOR
XMOVEI P4,DEVLST##-DEVSER ;NO--GET PRE-CHAIN POINTER
LNKDD7: HLRZ P2,DEVSER(P4) ;GET NEXT DDB ADDRESS
CAIN P2,(F) ;IS THIS A MATCH?
JRST LNKDD8 ;YES--WE CAN LINK IT UP NOW
MOVE P4,P2 ;NO--ADVANCE PREDECESSOR POINTER
JRST LNKDD7 ;AND TRY AGAIN
LNKDD8: MOVEI T1,(P3) ;*** UNTIL REAL EXTENDED DDBS
CAIE T1,(P4) ;IF WE MATCH OUR PREDECESSOR
CAIN T1,(F) ;OR OUR SUCCESSOR
JRST [DDBSRU ;UNLOCK DEVICE CHAIN SCANNING AND
MOVE F,P3 ;RESTORE INCOMING DDB
POPJ P,] ;GET OUT NOW (REDUNDANT PROTOTYPE)
HRLM P3,DEVSER(P4) ;LINK NEW TO PREVIOUS
HRLM F,DEVSER(P3) ;LINK NEXT TO NEW
HRRZ T1,DDBTAB(P1) ;*** UNTIL REAL EXTENDED DDBS
CAIE T1,(F) ;IF SUCCESSOR WAS FIRST,
SKIPN DDBTAB(P1) ;OR IF THERE'S NOTHING BETTER,
MOVEM P3,DDBTAB(P1) ;THEN MAKE THIS THE FIRST OF ITS KIND
MOVE T1,DEVLST## ;GET START OF CHAIN
MOVEM T1,HNGLST## ;AND UPDATE SHADOW COPY
DDBSRU ;RELEASE INTERLOCK
MOVE F,P3 ;RESTORE F FOR CALLER
IFN FTNET,<
SKIPE T1,DEVDRV(F) ;SEE IF THERE'S A DRVDSP HERE
HRRZ T1,DRVDDB(T1) ;GET PROTOTYPE DDB IF SO *** NON-EXTENDED
CAIN T1,(F) ;IF A PROTOTYPE,
JRST LNKDD9 ;DON'T COUNT IT
LDB T1,PDVSTA## ;GET STATION NUMBER
CAME T1,ANFNUM## ;IF NOT LOCAL,
JRST LNKDD9 ;DON'T COUNT IT
AOS DDBCNT(P1) ;COUNT IT FOR NETSER
PUSHJ P,NETDEV## ;UPDATE COUNTS IN NETNDB
> ;END IFN FTNET
LNKDD9: PJRST GENADD ;UPDATE GENTAB IF NECESSARY, THEN RETURN
SUBTTL AUTOCONFIGURATION -- AUTDPU - CHECK FOR DUAL PORTED UNITS
;THIS ROUTINE WILL CHECK FOR AND OPTIONALLY LINK UP UDBS FOR DUAL
;PORTED UNITS.
;CALL: MOVE W, CURRENT KDB ADDRESS
; MOVE T1, DRIVE S/N (WORD 1)
; MOVE T2, DRIVE S/N (WORD 2)
; MOVE T3, PHYSICAL DRIVE NUMBER
; PUSHJ P,AUTDPU
; <NON-SKIP> ;DUAL PORTED UNIT
; <SKIP> ;SINGLE PORTED UNIT
;
;IF THE NON-SKIP RETURN IS TAKEN, THE KDB/UDB LINKS WILL BE FIXED
;UP AS PER DR.LDP IN DRVCNF OF THE DRIVER DISPATCH TABLE. WHEN THIS
;BIT IS SET, NO ADDITIONAL AUTOCONFIGURATION WORK IS NECESSARY AND
;THE CALLER MAY STEP TO THE NEXT POSSIBLE UNIT. THE SKIP RETURN
;MEANS ADDITIONAL PROCESSING IS NEEDED.
AUTDPU::MOVE T4,.CPDRV## ;DRIVER DISPATCH
SKIPN DRVCKT(T4) ;HAVE A COMPATIBLE KONTROLLER TYPE TABLE?
JRST CPOPJ1## ;NO
PUSHJ P,SAVE3## ;SAVE SOME ACS
PUSH P,W ;SAVE W
DMOVE P1,T1 ;COPY DRIVE S/N
MOVE P3,.CPDRV## ;DRIVER DISPATCH
LDB T1,[POINTR (DRVCNF(P3),DR.DVT)] ;DEVICE TYPE
SKIPN W,KDBTAB(T1) ;GET FIRST KDB ADDRESS
JRST AUTDP3 ;NONE THERE
AUTDP1: MOVE T1,KDBDSP(W) ;DRIVER DISPATCH
CAME W,(P) ;FOUND OUR OWN KONTROLLER?
SKIPN T1,DRVCKT(T1) ;NO--GET ITS COMPATIBLE KONTROLLER TABLE
JRST AUTDP2 ;SKIP THIS KDB
LDB T2,[POINTR (DRVCF2(P3),DR.KTY)] ;GET OUR KONTROLLER TYPE
PUSHJ P,MATCKT ;FIND A COMPATIBLE KONTROLLER
JRST AUTDP2 ;NOT HERE
PUSHJ P,MATDSN ;FIND A MATCHING DRIVE S/N
JRST AUTDP2 ;THERE ISN'T ONE
POP P,W ;RESTORE CURRENT KDB
MOVE U,T1 ;COPY ALTERNATE UDB ADDRESS
ADD T2,KDBIUN(W) ;COMPUTE UDB SLOT FOR CURRENT KDB
MOVEM U,(T2) ;POINT KDB AT UDB
MOVEI T3,DR.DPU ;BIT TO TEST
TDNN T3,DRVCNF(P3) ;WANT DUAL PORTED KDB/UDB LINK FIXUP?
POPJ P, ;NO--ALL DONE
PJRST LNKUDB ;GO DO IT
AUTDP2: SKIPE W,KDBNXT(W) ;LINK TO NEXT
JRST AUTDP1 ;LOOP BACK
AUTDP3: POP P,W ;RESTORE W
JRST CPOPJ1## ;CAN'T DUAL PORT THIS UNIT
;SCAN A COMPATIBLE KONTROLLER TABLE FOR A MATCH
;CALL: MOVE T1, TABLE ADDRESS
; MOVE T2, TYPE TO MATCH ON
; PUSHJ P,MATCKT
MATCKT: SKIPN T3,(T1) ;GET A KONTROLLER TYPE
POPJ P, ;END OF TABLE
CAIE T2,(T3) ;A MATCH?
AOJA T1,MATCKT ;TRY ANOTHER
JRST CPOPJ1## ;RETURN
;SCAN UDBS ON A KONTROLLER FOR A MATCHING DRIVE SERIAL NUMBER
;CALL: MOVE W, KDB ADDRESS
; MOVE P1, DRIVE S/N (WORD 1)
; MOVE P2, DRIVE S/N (WORD 2)
; PUSHJ P,MATDSN
MATDSN: MOVE T2,KDBIUN(W) ;POINTER TO UDB TABLE
MATDS1: SKIPN T1,(T2) ;GET A UDB
JRST MATDS2 ;NONE THERE
DMOVE T3,UDBDSN(T1) ;COPY S/N
CAMN P1,T3 ;MATCH?
CAME P2,T4 ;...
JRST MATDS2 ;TRY ANOTHER
SUB T2,KDBIUN(W) ;GET UDB TABLE OFFSET
JRST CPOPJ1## ;RETURN WITH T1 & T2 SETUP
MATDS2: CAMGE T2,KDBFUN(W) ;FINAL UDB?
AOJA T2,MATDS1 ;LOOP FOR MORE
POPJ P, ;GIVE UP
SUBTTL AUTOCONFIGURATION -- AUTDSN - CHECK DRIVE S/N FOR ZEROS
;FOR OLD-STYLE UNITS INCAPABLE OF RETURNING A DRIVE SERIAL NUMBER, BUT
;WHICH CAN BE DUAL PORTED, A SCHEME HAS BEEN DEVELOPED IN WHICH A SERIAL
;NUMBER MAY BE FAKED UP. THE S/N DOUBLE WORD IS CONJURED UP BY PUTTING
;THE DEVICE CODE IN THE HIGH WORD, THE MASSBUS UNIT & THE PHYSICAL DRIVE
;NUMBER IN THE LOW WORD. THIS IS AKIN TO THE IBM STANDARD OF SETTING THE
;SERIAL NUMBER TO THE CU+DRIVE NUMBER. THE RESTRICTIONS TO MAKE THIS WORK
;ARE QUITE SIMPLE. THESE DRIVES MUST EXIST ON KONTROLLERS WITH THE SAME
;DEVICE CODE AND MASSBUS UNIT NUMBERS. AGAIN, IN IBM TERMS, THE OTHER
;PORTS MUST BE ADDRESSED THE SAME (I.E. THE SAME CU).
;
;USING THIS SCHEME, THE MONITOR WILL TOLLERATE AT MOST, TWO UNITS WITH THE
;SAVE PHYSICAL DRIVE NUMBER PER COMPATIBLE KONTROLLER WHICH HAVE SERIAL
;NUMBERS OF ZERO. ATTEMPTS TO HAVE MORE THAN TWO UNITS WITH A SERIAL NUMBER
;OF ZERO WILL MOST LIKELY CAUSE THE MONITOR TO DIE A RAPID AND RABID DEATH.
;
;THIS ROUTINE WILL CHECK THE SPECIFIED DRIVE SERIAL NUMBER FOR ZEROS
;AND IF THE KONTROLLER HAS A COMPATIBLE KONTROLLER TABLE, WILL CREATE
;A UNIQUE SERIAL NUMBER.
;CALL: MOVE W, KDB ADDRESS
; MOVE T1, S/N WORD 1
; MOVE T2, S/N WORD 2
; MOVE T3, PHYSICAL DRIVE NUMBER
; PUSHJ P,AUTDSN
;
;ON RETURN, T1/T2 AND .CPTSN WILL ALWAYS BE SET WITH THE POSSIBLY
;NEW DRIVE SERIAL NUMBER
AUTDSN::MOVE T4,T1 ;HIGH PART
IOR T4,T2 ;LOW PART
JUMPN T4,AUTDS1 ;GO STORE IF NON-ZERO
MOVE T4,.CPDRV## ;DRIVER DISPATCH
SKIPN DRVCKT(T4) ;NO--COMPATIBLE KONTROLLER TABLE EXIST?
JRST AUTDS1 ;DON'T ALTER ANYTHING
HRRZ T1,.CPDRV## ;USE DEVICE CODE AS HIGH WORD
HLLZ T2,KDBUNI(W) ;GET MASSBUS UNIT (IF ANY)
HRR T2,T3 ;PLUS PHYSICAL DRIVE NUMBER FOR LOW WORD
AUTDS1: DMOVEM T1,.CPTSN## ;SAVE TEMPORARILY
POPJ P, ;RETURN
SUBTTL AUTOCONFIGURATION -- AUTDVC - FILL IN DEVICE CODES
;ROUTINE TO SET DEVICE CODES
;THIS DEPENDS ON I/O INSTRUCTIONS HAVING THE FORM
; INST 000,???
;
;WHERE INST ANY I/O INSTRUCTION
; 000 MUST BE ZERO AND WILL BE FILLED IN WITH
; THE DEVICE CODE
;
;CALL: MOVE T1, -LENGTH,,0
; XMOVEI T2, STARTING ADDRESS
; MOVE T3, DEVICE CODE
; PUSHJ P,AUTDVC
IFN FTKL10,<
AUTDVC::MOVE T4,(T2) ;GET POSSIBLE INSTRUCTION
TLNE T4,077400 ;DEVICE CODE ZERO?
JRST AUTDV1 ;NO--ASSUME NOT AN I/O INSTRUCTION
TLC T4,700000 ;REALLY AN I/O
TLCN T4,700000 ; INSTRUCTION?
DPB T3,[POINT 7,(T2),9] ;SET DEVICE CODE
AUTDV1: AOS T2 ;ADVANCE TO NEXT STORAGE
AOBJN T1,AUTDVC ;AND LOOP
POPJ P, ;RETURN
>; END IFN FTKL10
SUBTTL AUTOCONFIGURATION -- AUTEBD - HANDLE 18-BIT DF10/DF10C
;ROUTINE CALLED FROM DRIVERS WHICH DETECT AN 18-BIT DF10/DF10C TO PRINT
;AN ERROR MESSAGE AND IGNORE THE DEVICE. ALWAYS RETURNS CPOPJ (BACK TO
;AUTCON FROM CALL TO DRIVER'S CFG ROUTINE).
IFN FTKL10,<
AUTEBD::STOPCD CPOPJ##,INFORM,AUT18B,DIE18B, ;++18-BIT DF10/DF10C
;HERE FROM ERRCON ON AN AUT18B STOPCD
DIE18B: PUSHJ P,INLMES## ;PRINT SOME TEXT
ASCIZ .DF10/DF10C in 18-bit mode (device code .
HRRZ T1,.CPDVC## ;GET DEVICE CODE
LSH T1,2 ;POSITION IT
PUSHJ P,PRTDI8## ;PRINT IT
PJSP T1,CONMES## ;FINISH MESSAGE AND RETURN
ASCIZ .) - controller ignored.
>; END IFN FTKL10
SUBTTL AUTOCONFIGURATION -- AUTFND - FIND A DDB
;ROUTINE TO FIND A DDB GIVEN A DEVICE CODE. THIS WAS WRITTEN SPECIFICALLY
;FOR THOSE DEVICES (SUCH AS LPTS) WHICH HAVE NO WAY TO DETERMINE OF A GIVEN
;DATA STRUCTURE ALREADY EXISTS FOR THE DEVICE IN QUESTION.
;CALL: MOVE T1, DDB OFFSET CONTAINING I/O INSTRUCTION
; PUSHJ P,AUTFND
; <NON-SKIP> ;F = DDB
; <SKIP> ;NO DDB EXISTS
AUTFND::PUSHJ P,SAVT## ;SAVE SOME ACS
HRRZ T2,.CPDVC## ;DEVICE CODE
MOVE T3,.CPDRV## ;DRIVER DISPATCH
LDB T3,[POINTR (DRVCNF(T3),DR.DVT)] ;GET DEVICE TYPE
DDBSRL ;INTERLOCK
SKIPE F,DDBTAB(T3) ;GET HEAD OF CHAIN (PROTOTYPE DDB)
AUTFN1: HLRZ F,DEVSER(F) ;LINK TO FIRST REAL DDB
JUMPE F,AUTFN2 ;SOMEONE IS CONFUSED
LDB T4,PDVTYP## ;GET DEVICE TYPE
CAIE T4,(T3) ;MATCH?
JRST AUTFN2 ;NO DDBS OF THIS TYPE
MOVE T4,F ;COPY DDB ADDRESS
ADDI T4,(T1) ;OFFSET TO WORD CONTAINING I/O INSTRUCTION
IFN FTKL10,<LDB T4,[POINT 7,(T4),9]> ;GET DEVICE CODE
IFN FTKS10,<MOVE T4,(T4)> ;GET UNIBUS ADDRESS
CAME T4,T2 ;MATCH?
JRST AUTFN1 ;NO--TRY ANOTHER DDB
SKIPA ;NON-SKIP RETURN IF DDB EXISTS
AUTFN2: AOS (P) ;SKIP IF NO SUCH DDB
DDBSRU ;RELEASE INTERLOCK
POPJ P, ;RETURN
SUBTTL AUTOCONFIGURATION -- AUTICD - BUILD INTERRUPT CODE
;ROUTINE TO BUILD INTERRUPT CODE GIVEN A PROTOTYPE BLOCK
;CALL: MOVE T1, DATA BLOCK ADDRESS
; MOVE T2, INTERRUPT HANDLER ADDRESS
; PUSHJ P,AUTICD
; <NON-SKIP> ;NO CORE
; <SKIP> ;T1 = SKIP-CHAIN ADDRESS, T2 = VECTOR ADDRESS
AUTICD::PUSHJ P,SAVE4## ;SAVE SOME ACS
DMOVE P3,T1 ;SAVE ARGUMENTS
MOVE T1,.CPDRV## ;DRIVER DISPATCH
SKIPN T1,DRVICL(T1) ;GET LENGTH OF PROTOTYPE
JRST CPOPJ1## ;NO PROTOTYPE, NO INTERRUPT CODE
HRRZS T1 ;ISOLATE LENGTH
PUSHJ P,GETCOR ;ALLOCATE CORE
POPJ P, ;GIVE UP
MOVE P1,T2 ;COPY ADDRESS
MOVE T4,.CPDRV## ;DRIVER DISPATCH
IFE FTXMON,<
HRR T1,T2 ;COPY ADDRESS
HRL T1,DRVICD(T4) ;MAKE A BLT POINTER
MOVE T2,DRVICL(T4) ;NUMBER OF WORDS
ADDI T2,(P1) ;COMPUTE END OF BLT
BLT T1,-1(T2) ;COPY PROTOTYPE
> ;END IFE FTXMON
IFN FTXMON,<
MOVE T1,DRVICL(T4) ;NUMBER OF WORDS
MOVE T2,DRVICD(T4) ;PROTOTYPE
MOVE T3,P1 ;WHERE TO PUT IT
EXTEND T1,[XBLT] ;COPY
MOVEI T1,DR.XAD ;BIT TO TEST
TDNN T1,DRVCNF(T4) ;EXTENDED ADDRESSING DRIVER?
> ;END IFN FTXMON
HRRZS P4 ;STRIP OFF SECTION NUMBER (IF ANY)
MOVN P2,DRVICL(T4) ;-NUMBER OF WORDS
HRLZS P2 ;MAKE AN AOBJN POINTER
SETZ T4, ;WILL EVENTUALLY HAVE VECTOR ADDRESS
PUSHJ P,FIXINT ;FIX UP A WORD
AOBJN P2,.-1 ;LOOP FOR ALL WORDS
MOVE T1,P1 ;CONSO INTERRUPT ADDRESS
MOVE T2,T4 ;VECTOR INTERRUPT ADDRESS
JRST CPOPJ1## ;AND RETURN
;ROUTINE TO FILL IN A WORD OF EITHER A CONSO SKIP CHAIN CODE OR
;VECTORED INTERRUPT CODE.
;CALL: MOVE P1, INTERRUPT ROUTINE BASE ADDRESS
; MOVE P2, AOBJN POINTER TO INTERRUPT ROUTINE
; MOVE P3, DATA BLOCK ADDRESS
; MOVE P4, INTERRUPT HANDLER ADDRESS
; PUSHJ P,FIXINT
;
;THE RULES FOR ADJUSTING INSTRUCTIONS OR DATA WORDS WITHIN THE
;INTERRUPT CODE ARE:
; 1. ANY CONSECUTIVE PAIRS OF ZERO WORDS WILL BE INTERPRETED AS
; AN XPCW ENTRY POINT.
; 2. ANY INSTRUCTION WHOSE RIGHT HALF CONTAINS AN INTEGER WITH
; A VALUE LESS THAN THE LENGTH OF THE INTERRUPT ROUTINE WILL
; CAUSE THAT INSTRUCTION TO BE RELOCATED BY THE ADDRESS OF
; THE INTERRUPT ROUTINE.
; 3. A "JSR PIERR" INSTRUCTION WILL BE REPLACED BY A CALL TO THE
; PI CHANNEL SAVE ROUTINE FOR THE DEVICE BEING CONFIGURED.
; 4. A "DMOVEM AC,-1" OR AN "XJEN -1" INSTRUCTION WILL BE REPLACED
; BY A DMOVEM/XJEN TO THE APPROPRIATE PI CHANNEL INTERRUPT ADDRESS.
; 5. ALL I/O INSTRUCTIONS WILL HAVE THE APPROPRIATE DEVICE CODE
; STORED INTO THEM.
; 6. ANY SKIPA INSTRUCTION IS INTERPRETED AS MEANING THE ADDRESS
; OF THE DATA BLOCK WILL BE LOADED INTO THE SPECIFIED AC.
; 7. AN "XJRST .+1" (KL10) OR A "JRST @.+1" (KS10) WILL BE INTERPRETED
; AS A JUMP TO THE INTERRUPT HANDLER.
;
;NOTE: ON A KL10, THE START OF THE CONSO SKIP CHAIN MUST BE THE FIRST
; WORD IN THE INTERRUPT ROUTINE.
FIXINT: HRRZ T1,P2 ;OFFSET
ADD T1,P1 ;INDEX INTO BLOCK
;CHECK FOR XPCW ENTRY POINT
FIXIN1: MOVE T2,0(T1) ;GET WORD 1
IOR T2,1(T1) ;AND WORD 2
JUMPN T2,FIXIN2 ;MUST BE ZERO FOR XPCW ENTRY
MOVE T4,T1 ;SAVE VECTOR INTERRUPT ADDRESS
AOBJN P2,.+1 ;ADVANCE ONE
AOBJN P2,.+1 ;ONE MORE BEYOND THE NEW PC FLAGS
POPJ P, ;AND RETURN
;CHECK FOR AN I/O INSTRUCTION
FIXIN2: MOVE T2,(T1) ;FETCH A WORD
TLNE T2,077400 ;DEVICE CODE ZERO?
JRST FIXIN3 ;ASSUME NOT AN I/O INSTRUCTION
TLC T2,700000 ;REALLY AN I/O
TLCN T2,700000 ; INSTRUCTION?
SKIPA T2,.CPDVC## ;GET DEVICE CODE
JRST FIXIN3 ;TRY SOMETHING ELSE
IFN FTKL10,<DPB T2,[POINT 7,(T1),9]> ;COMPLETE INSTRUCTION
IFN FTKS10,<DPB T2,[POINT 21,(T1),35]> ;COMPLETE INSTRUCTION
POPJ P, ;DONE
;CHECK FOR RELOCATION
FIXIN3: HRRZ T2,(T1) ;GET RH OF POSSIBLE INSTRUCTION
HLRE T3,P2 ;GET RH
MOVNS T3 ;MAKE POSITIVE
ADDI T3,(P2) ;LENGTH OF ROUTINE
CAIL T2,0 ;AVOID NEGATIVE OFFSETS
CAILE T2,-1(T3) ;WANT TO RELOCATE?
SKIPA ;LEAVE IT ALONE
ADDM P1,(T1) ;RELOCATE ADDRESS
;CHECK FOR JSR TO SAVE ROUTINE
FIXIN4: MOVE T2,(T1) ;FETCH A WORD
CAME T2,[JSR PIERR##] ;NEED TO REPLACE?
JRST FIXIN5 ;NO
MOVE T2,.CPDRV## ;DRIVER DISPATCH
IFN FTMP,< MOVE T3,DRVCNF(T2) > ;GET CONFIG BITS
MOVE T2,DRVPIC(T2) ;GET PI CHANNEL
IFN FTMP,<
TRNN T3,DR.MCD ;IF A NORMAL DEVICE,
SKIPA T2,.CPSAV##-1(T2) ;GET ASSOCIATED SAVE ROUTINE
MOVS T2,.CPSAV##-1(T2) ;GET SPECIAL SAVE ROUTINE FOR MULTI-CPU DEVS
> ;END OF IFN FTMP
IFE FTMP,< MOVE T2,.CPSAV##-1(T2) > ;GET ASSOCIATED SAVE ROUTINE
HRRM T2,(T1) ;MAKE INSTRUCTION USEFUL
POPJ P, ;DONE
;CHECK FOR DMOVEM/XJEN TO PI CHANNEL INTERRUPT LOCATION
FIXIN5: MOVE T2,(T1) ;GET WORD
CAME T2,[XJEN -1] ;AC FIELD IS JRST CLASS OPCODE
TLZ T2,(Z 17,0) ;CLEAR OUT AC FIELD
CAME T2,[DMOVEM -1] ;MAGIC OPCODE?
CAMN T2,[XJEN -1] ;...
SKIPA T2,.CPDRV## ;YES--DRIVER DISPATCH
JRST FIXIN6 ;TEST SOMETHING ELSE
MOVE T2,DRVPIC(T2) ;GET PI CHANNEL
LSH T2,1 ;TIMES 2
ADDI T2,40-1 ;COMPUTE INTERRUPT LOCATION
ADD T2,.CPEPT## ;INDEX INTO EPT
HRRZ T2,1(T2) ;GET RH (XPCW CHXX)
HRRM T2,(T1) ;COMPLETE THE INSTRUCTION
POPJ P, ;DONE
;CHECK FOR SKIPA TO LOAD DATA BLOCK ADDRESS
FIXIN6: SKIPE T2,1(T1) ;FETCH POTENTIAL DATA BLOCK STORAGE
JRST FIXIN7 ;MUST BE ZERO
HLRZ T2,0(T1) ;GET POSSIBLE SKIPA
TRZ T2,(<Z 17,0>) ;CLEAR OUT AC FIELD
CAIE T2,<SKIPA>_-22 ;MAGIC OPCODE?
JRST FIXIN7 ;NO
MOVEM P3,1(T1) ;STORE DATA BLOCK ADDRESS
AOBJN P2,.+1 ;ADVANCE
POPJ P, ;DONE
;CHECK FOR XJRST/JRST FOR JUMP TO INTERRUPT HANDLER
FIXIN7: SKIPE T2,1(T1) ;FETCH POTENTIAL DATA BLOCK STORAGE
JRST FIXINX ;MUST BE ZERO
HLRZ T2,0(T1) ;GET POSSIBLE SKIA
IFE FTXMON,<CAIE T2,(JRST @)> ;MAGIC OPCODE?
IFN FTXMON,<CAIE T2,(XJRST)> ;MAGIC OPCODE?
JRST FIXINX ;NO
MOVEM P4,1(T1) ;STORE INTERRUPT HANDLER ADDRESS
AOBJN P2,.+1 ;ADVANCE
FIXINX: POPJ P, ;DONE
SUBTTL AUTOCONFIGURATION -- AUTINI - INITIALIZE AUTOCONFIGURATION
$INIT
;INITIALIZE AUTO-CONFIGURATION
;CALL: PUSHJ P,AUTINI
; <RETURN>
AUTINI::SE1ENT ;RUN IN NZS
PUSHJ P,SAVE1## ;SAVE P1
MOVSI P1,INTNUM## ;AOBJN POINTER TO INTTAB
AUTIN1: LDB F,PINTDB## ;GET DDB ADDRESS
SKIPE F ;MUST HAVE A DDB
SKIPE DEVNAM(F) ;AND MUST HAVE NO NAME
JRST AUTIN2 ;ELSE NOT A TRUE AUTOCONFIGURABLE DDB
LDB T1,PDVTYP## ;GET DEVICE TYPE
CAILE T1,TYPMAX ;REASONABLE CODE?
JRST AUTIN2 ;NO
LDB T2,PINTSZ## ;GET SIZE
MOVEM T2,DDBSIZ(T1) ;STORE IT AWAY
PUSHJ P,AUTLNK ;PUT THE DDB WHERE IT BELONGS
AUTIN2: AOBJP P1,.+1 ;ACCOUNT FOR TWO WORD ENTRIES
AOBJN P1,AUTIN1 ;ONTO THE NEXT INTTAB ENTRY
SKIPN T1,DRVLST ;INITIAL DRIVER DISPATCH
JRST AUTIN4 ;THERE ARE NONE
XMOVEI T2,DRVLST ;"PREVIOUS" DRVLST ENTRY
MOVEM T2,PRVLST ;SAVE
AUTIN3: PUSHJ P,INIDSP ;DO DISPATCH ADDRESS FIXUPS
MOVEM T1,.CPDRV## ;SAVE FOR THOSE ROUTINES WHICH MIGHT NEED IT
PUSHJ P,INIADN ;TALLY UP PER-CPU DEVICE COUNTERS
MOVE T1,.CPDRV## ;RELOAD DISPATCH
MOVE T2,DRVDDL(T1) ;PROTOTYPE DDB LENGTH
SKIPN F,DRVDDB(T1) ;PROTOTYPE DDB ADDRESS
JRST AUTIN4 ;NOTHING TO DO IF NO DDB
SKIPN DEVDRV(F) ;IF NO DISPATCH TABLE ADDRESS AS YET,
MOVEM T1,DEVDRV(F) ;GIVE IT ONE (SO LNKDDB WORKS)
LDB T3,PDVTYP## ;GET TYPE
MOVEM T2,DDBSIZ(T3) ;SAVE LENGTH
PUSHJ P,AUTLNK ;PUT THE DDB WHERE IT BELONGS
IFN FTMP,<
MOVE T1,.CPDRV## ;FROM DISPATCH TABLE,
MOVE T1,DRVPIC(T1) ;GET PI CHANNEL
PUSHJ P,DDBPIC ;FIXUP IN DEVCPU(F)
> ;END IFN FTMP
MOVE T1,.CPDRV## ;RESTORE DISPATCH TABLE ADDRESS
AUTIN4: MOVEM T1,PRVLST ;SAVE "PREVIOUS" DISPATCH ADDRESS
SKIPE T1,DRVLNK(T1) ;LINK TO NEXT DISPATCH
JRST AUTIN3 ;LOOP IF MORE
PUSHJ P,INIGCC ;FIX UP GLOBAL CPU COUNTERS
PUSHJ P,INICKT ;FIX UP COMPATIBLE KONTROLLERS FOR EACH OTHER
PUSHJ P,GENSRT ;SORT GENTAB AND SET GENPTR
POPJ P, ;RETURN
;MONGEN'ED DEVICE TABLE FIXUP
;ROUTINE TO TALLY UP THE HIGHEST RESERVED DEVICE COUNTERS PER-CPU
;AND STORE THE RESULT AS THE STARTING COUNTER FOR OVERFLOW ALLOCATION
INIADN: PUSHJ P,SAVE3## ;SAVE SOME ACS
SKIPE T4,@DRVMDT(T1) ;COPY RESERVED COUNTERS
AOJA T4,INIAD1 ;REMEMBER MONGEN-SPECIFIED
;SETUP DEFAULT MAXIMUM PER-CPU COUNTERS
LDB T2,[POINTR (DRVCF2(T1),DR.LIM)] ;GET SYSTEM-WIDE DEVICE LIMIT
SKIPN T2 ;LIMIT SPECIFIED?
MOVEI T2,^D26 ;NO--DEFAULT MAXIMUM (I.E. MTA TO MTZ)
IDIVI T2,M.CPU## ;COMPUTE HOW MANY PER CPU ALLOWED
SKIPE T3 ;REMAINDER?
SUBI T2,1 ;ADJUST
LSH T2,37 ;LEFT JUSTIFY
MOVEI T3,M.CPU## ;COUNTER
IOR T4,T2 ;SET A BYTE
LSH T2,-5 ;POSITION
SOJG T3,.-2 ;LOOP FOR ALL CPUS
MOVEM T4,@DRVMDT(T1) ;UPATE
;TALLY UP PER-CPU MAXIMUM COUNTS AND SYSTEM-WIDE COUNT
INIAD1: MOVE P1,[POINT 5,T4] ;BYTE POINTER TO MAXIMUM COUNTS
MOVSI P2,-6 ;AOBJN POINTER
SETZB P3,T3 ;ZERO SYSTEM-WIDE TOTAL, INITIAL COUNTERS
INIAD2: ILDB T2,P1 ;GET PER-CPU LIMIT
ADDI P3,(T2) ;ACCUMULATE
SKIPE T2 ;NON-ZERO?
DPB P3,P1 ;STORE MAXIMUM PER-CPU COUNT
AOBJN P2,INIAD2 ;LOOP FOR ALL COUNTS
DPB P3,[POINT 5,T3,34] ;STORE SYSTEM-WIDE COUNT
;SETUP INITIAL PER-CPU COUNTERS
MOVE P1,[POINT 5,T4] ;BYTE POINTER TO MAXIMUM COUNTS
MOVE P2,[POINT 5,T3] ;BYTE POINTER TO INITIAL COUNTS
MOVSI P3,-6 ;AOBJN POINTER
SETZB P4,T2 ;CLEAR TEMPORARY COUNTERS
INIAD3: ILDB T2,P1 ;GET A MAXIMUM COUNT FOR THIS CPU
IBP P2 ;POSITION FOR INITIAL COUNT STORAGE
JUMPE T2,INIAD4 ;ANY RESERVED ON THIS CPU?
DPB P4,P2 ;YES
MOVEI P4,(T2) ;GET NEXT VALUE TO STORE
INIAD4: AOBJN P3,INIAD3 ;LOOP
EXCH T3,T4 ;T3 = MAXIMUM COUNTS, T4 = INITIAL COUNTS
DMOVEM T3,@DRVMDT(T1) ;UPDATE
POPJ P, ;RETURN
;DISPATCH TABLE FIXUP
;THIS ROUTINE IS CALLED BY AUTINI TO DO SPECIAL DISPATCH TABLE FIXUPS
;SUCH AS ADJUSTING THE COMMON DISPATCH ENTERIES FOR THE SUBROUTINES
;WHEN THE DRIVER RUNS IN SECTION ONE, AND RESOLVING ADDRESSES OF DATA
;STRUCTURES THAT DO NOT EXIST ARE POINTED TO BY DUMMY IFIWS. NOTE
;THAT ALTHOUGH THE DRIVER DISPATCH TABLES RESIDE IN THE HIGH SEGMENT,
;CHANGES CAN STILL BE MADE BECAUSE THE HIGH SEGMENT IS WRITE ENABLED
;DURING SYSINI.
INIDSP:
IFN FTXMON,<
HRLI T1,(MCSEC1) ;.LINK PSEUDO OP ONLY DEALS WITH
MOVSI T2,(MCSEC1) ; 18-BIT ADDRESSES
HLLM T2,@PRVLST ; SO MUST FIXUP ALL
MOVE T2,T1 ;COPY DISPATCH ADDRESS
HRLI T2,-<DRVLEN-DRVADF> ;AOBJN POINTER
MOVSI T3,(MCSEC1) ;MONITOR CODE SECTION ONE
HLLM T3,@PRVLST ;ADJUST PREVIOUS LINK
INIDS1: MOVE T4,DRVADF(T2) ;GET AN ADDRESS
TLNN T4,-1 ;SECTION NUMBER ALREADY THERE?
HLLM T3,DRVADF(T2) ;MAKE GLOBAL ADDRESS
AOBJN T2,INIDS1 ;LOOP BACK
SKIPN T2,DRVKDB(T1) ;KDB
JRST INIDS2 ;NONE THERE
TLNN T2,-1
HRLI T2,(MCSEC1)
MOVEM T2,DRVKDB(T1)
INIDS2: SKIPE T2,DRVUDB(T1) ;UDB
TLNE T2,-1
SKIPA
HRLI T2,(MCSEC1)
MOVEM T2,DRVUDB(T1)
SKIPE T2,DRVDDB(T1) ;DDB
TLNE T2,-1
SKIPA
HRLI T2,(MCSEC1)
MOVEM T2,DRVDDB(T1)
SKIPE T2,DRVULP(T1) ;ULP
TLNE T2,-1
SKIPA
HRLI T2,(MCSEC1)
MOVEM T2,DRVULP(T1)
SKIPE T2,DRVMDT(T1) ;MDT
TLNE T2,-1
SKIPA
HRLI T2,(MCSEC1)
MOVEM T2,DRVMDT(T1)
SKIPE T2,DRVICD(T1) ;ICD
TLNE T2,-1
SKIPA
HRLI T2,(MCSEC1)
MOVEM T2,DRVICD(T1)
SKIPE T2,DRVDIA(T1) ;DIAG
SKIPN T3,(T2) ;PREPROCESSOR ROUTINE
JRST INIDS3 ;NO SUPPORT
TLNE T3,-1
SKIPA
HRLI T3,(MCSEC1)
MOVEM T3,(T2)
INIDS3: MOVEI T2,DR.XAD ;BIT TO TEST
TDNN T2,DRVCNF(T1) ;EXTENDED ADDRESSING DRIVER?
POPJ P, ;NO
SKIPE T2,DRVINT(T1) ;INTERRUPT SERVICE
TLNE T2,-1 ;NZS?
SKIPA ;NO FIXUP
HRLI T2,(MCSEC1) ;FORCE SECTION ONE DISPATCH
MOVEM T2,DRVINT(T1) ;UPDATE
SKIPE T2,DRVDIA(T1) ;DIAG. UUO DISPATCH TABLE
TLNE T2,-1 ;NZS?
SKIPA ;NO FIXUP
HRLI T2,(MCSEC1) ;FORCE SECTION ONE DISPATCH
MOVEM T2,DRVDIA(T1) ;UPDATE
> ;END IFN FTXMON
POPJ P, ;RETURN
;DRIVER DISPATCH TABLE FIXUP
;THIS ROUTINE IS CALLED BY AUTINI TO FIX UP VARIOUS UDB AND DDB PARAMETERS
;FOR COMPATIBLE KONTROLLER TYPES. IT MAXIMIZES THE LENGTHS OF THE UDB AND
;DDB, AND THE RESTRICTIONS ON WHETHER THE DDB NEEDS TO BE UNCACHED.
INICKT: PUSHJ P,SAVE4## ;NEED SOME ACS
XMOVEI P1,DRVLST ;WHERE TO START LOOKING
INICK1: SKIPN P1,DRVLNK(P1) ;GET NEXT DRIVER IN SYSTEM
POPJ P, ;DONE
SKIPE P2,DRVCKT(P1) ;DO WE HAVE COMPATIBLE KONTROLLERS?
SKIPN 1(P2) ;I MEAN REALLY?
JRST INICK1 ;NO, SKIP THIS ONE
XMOVEI P3,DRVLST ;YES, SET PREDECESSOR DRIVER TABLE
LDB P4,[POINTR (DRVCNF(P1),DR.DVT)] ;GET OUR DEVICE TYPE
INICK2: SKIPN P3,DRVLNK(P3) ;GET NEXT DRIVER TO EXAMINE
JRST INICK1 ;NONE, TRY OUTER LOOP SOME MORE
CAMN P3,P1 ;LOOKING AT MY OWN TABLE?
JRST INICK2 ;YES, AVOID EXPENSIVE NO-OPS
LDB T1,[POINTR (DRVCNF(P3),DR.DVT)] ;GET INNER DEVICE TYPE
CAIE T1,(P4) ;ARE WE LOOKING AT THE RIGHT TYPE OF DEVICE?
JRST INICK2 ;NO, LOOK FOR ANOTHER
MOVE T1,P2 ;YES, POINT TO MY COMPATIBLE KON TABLE
LDB T2,[POINTR (DRVCF2(P3),DR.KTY)] ;GET INNER KON TYPE
PUSHJ P,MATCKT ;SEE IF HE'S IN MY TABLE
JRST INICK2 ;NO, LOOK FOR ANOTHER VICTIM
MOVEI T1,DR.UCD ;UNCACHE DDB BIT
AND T1,DRVCNF(P3) ;ISOLATE FROM INNER'S TABLE
IORM T1,DRVCNF(P1) ;RESTRICT OUTER DRIVER IF NEEDED
MOVE T1,DRVDDL(P3) ;GET INNER'S DDB LENGTH NEEDS
CAMLE T1,DRVDDL(P1) ;IF LARGER THAN OUR OWN,
MOVEM T1,DRVDDL(P1) ;UPDATE OURS
MOVE T1,DRVULN(P3) ;GET INNER'S UDB LENGTH NEEDS
CAMLE T1,DRVULN(P1) ;IF LARGER THAN OUR OWN,
MOVEM T1,DRVULN(P1) ;UPDATE OURS
JRST INICK2 ;LOOP OVER ALL POTENTIAL MATCHES
;GLOBAL CPU COUNTER FIXUP
;THIS ROUTINE WILL SYNCHRONIZE ALL MDTS FOR DRIVERS WITH DR.GCC SET
INIGCC: PUSHJ P,SAVE1## ;SAVE P1
MOVE P1,DRVLST ;POINT TO START OF DRIVER CHAIN
INIGC1: MOVEI T1,DR.GCC ;BIT TO TEST
MOVEI T2,1 ;AND ANOTHER
TDNE T1,DRVCNF(P1) ;USING GLOBAL CPU COUNTERS?
TDNN T2,@DRVMDT(P1) ;MONGEN-SPECIFIED?
JRST INIGC2 ;NO
ANDCAM T2,@DRVMDT(P1) ;CLEAR SO WE DON'T FIND LATER
MOVEM P1,.CPDRV## ;SET DISPATCH FOR SUBROUTINE
PUSHJ P,ADNFIX ;FIXUP OTHER MDTS
INIGC2: SKIPE P1,DRVLNK(P1) ;LINK TO NEXT
JRST INIGC1 ;LOOP BACK
POPJ P, ;RETURN
$HIGH
SUBTTL AUTOCONFIGURATION -- AUTKDB - BUILD A KDB
;BUILD A KDB
;CALL: T1/ MASSBUS UNIT NUMBER (OR -1 IF MEANINGLESS)
; PUSHJ P,AUTKDB
; <NON-SKIP> ;NO CORE AVAILABLE
; <SKIP> ;AC W = NEW KDB ADDRESS
AUTKDB::PUSHJ P,SAVE3## ;SAVE SOME ACS
MOVE T4,.CPDRV## ;DRIVER DISPATCH
MOVE P1,DRVKDB(T4) ;COPY PROTOTYPE KDB ADDDRESS
MOVE P2,DRVKLN(T4) ;COPY PROTOTYPE KDB LENGTH
HRRZ P3,.CPDVC## ;<DEVICE CODE>/4
HRL P3,T1 ;MASSBUS UNIT NUMBER
PUSHJ P,FNDKDB ;KDB ALREADY EXIST?
JRST CPOPJ1## ;YES--NOTHING TO DO (KDB ADDRESS IN W)
IFN FTKL10,<
PUSHJ P,GETIOW ;GET ICCW
POPJ P, ;NO LOW CORE BLOCKS AVAILABLE
PUSH P,T1 ;SAVE ADDRESS OF ICCW
>; END IFN FTKL10
MOVE T1,P2 ;GET PROTOTYPE KDB LENGTH
PUSHJ P,GETCOR ;ALLOCATE CORE
SKIPA ;CAN'T DO IT
JRST AUTKD1 ;ONWARD
IFN FTKL10,<
POP P,T1 ;GET ICCW ADDRESS BACK
CAIL T1,PAGSIZ ;LOW CORE BLOCK?
POPJ P, ;YES, NOTHING TO RETURN
PJRST RTNIOW## ;RETURN LOW CORE BLOCK AND QUIT
>; END IFN FTKL10
IFN FTKS10,<POPJ P,> ;RETURN
AUTKD1: MOVE W,T2 ;COPY KDB ADDRESS
IFE FTXMON,<
HRR T1,T2 ;COPY KDB ADDRESS
HRLI T1,(P1) ;PROTOTYPE ADDRESS
ADD T2,P2 ;ADD IN LENGTH OF PROTOTYPE
BLT T1,-1(T2) ;COPY INTO WORKING STORAGE
> ;END IFE FTXMON
IFN FTXMON,<
MOVE T1,P2 ;PROTOTYPE LENGTH
MOVE T2,P1 ;PROTOTYPE ADDRESS
MOVE T3,W ;DESTINATION
EXTEND T1,[XBLT] ;COPY INTO WORKING STORAGE
> ;END IFN FTXMON
IFN FTKL10,<POP P,KDBICP(W)> ;STORE ICCW
MOVE T1,W ;DATA BLOCK ADDRESS
MOVE T2,.CPDRV## ;DRIVER DISPATCH
MOVE T2,DRVINT(T2) ;INTERRUPT SERVICE
PUSHJ P,AUTICD ;GENERATE INTERRUPT ROUTINES
SKIPA T1,P2 ;FAILED--GET KDB LENGTH
JRST AUTKD2 ;ONWARD
MOVE T2,W ;GET KDB ADDRESS
PJRST GIVWDS## ;RETURN CORE
AUTKD2: MOVEM T2,KDBVIN(W) ;SAVE VECTOR ADDRESS FOR CURIOUS EYES
IFN FTKL10,<
MOVEM T1,KDBCSO(W) ;DITTO FOR SKIP CHAIN ADDRESS
MOVE T2,.CPDRV## ;DRIVER DISPATCH
MOVE T2,DRVPIC(T2) ;PI CHANNEL
SKIPE T1 ;MAY NOT HAVE A SKIP CHAIN
PUSHJ P,AUTCSO ;LINK INTO CONSO SKIP CHAIN
MOVE T1,KDBICP(W) ;GET ICCW
ADDI T1,3 ;POINT TO VECTORED INTERRUPT WORD
HRLI T1,744002 ;ASSUME RH20 FLAVOR OF VECTOR
HRRZ T2,.CPDVC## ;GET DEVICE CODE
CAIL T2,FSTICD/4 ;AN RH20?
CAILE T2,LSTICD/4 ;...
HRLI T1,444002 ;RH10-STYLE VECTOR
MOVEM T1,KDBIVI(W) ;SAVE
>; END IFN FTKL10
IFN FTKL10,<HRRZ T1,.CPDVC##> ;GET DEVICE CODE
IFN FTKS10,<LDB T1,[POINT 21,.CPDVC##,35]> ;GET UNIBUS ADDRESS OF DEVICE
MOVEM T1,KDBDVC(W) ;SAVE
IFN FTKS10,<
PUSHJ P,AUTVII ;COMPUTE ADDRESS OF INTERRUPT INSTRUCTION
MOVEM T1,KDBIVI(W) ;SAVE IVAR
MOVE T2,KDBVIN(W) ;GET ADDRESS OF VECTOR ROUTINE
HRLI T2,(XPCW) ;INTERRUPT INSTRUCTION IS AN XPCW
MOVEM T2,0(T1) ;SAVE IN VECTOR INTERRUPT TABLE
>; END IFN FTKS10
MOVE T1,.CPDRV## ;DRIVER DISPATCH
MOVEM T1,KDBDSP(W) ;STORE
PUSHJ P,AUTADN ;ALLOCATE A PER-CPU DEVICE NUMBER
MOVE T2,KDBNAM(W) ;GET NAME SO FAR
PUSHJ P,AUTNAM ;GENERATE DEVICE NAME
MOVEM T1,KDBNAM(W) ;UPDATE
HLRE T1,P3 ;GET MASSBUS UNIT NUMBER
HRLM T1,KDBUNI(W) ;SET UNIT NUMBER OR -1
MOVE T2,T1 ;MAKE A COPY
MOVEI T3,1 ;GET A BIT
LSH T3,(T2) ;POSITION FOR PARTICULAR MASSBUS UNIT
SKIPL T1 ;NEGATIVE IF NON-MULTI UNIT KONTROLLER
HRRM T3,KDBUNI(W) ;STORE ATTENTION BIT
PUSHJ P,SETULB ;SET UP MICROCODE LOADER BLOCK
MOVE T1,.CPDRV## ;DRIVER DISPATCH
LDB T1,[POINTR (DRVCF2(T1),DR.DMX)] ;GET MAX NUMBER OF DRIVES
JUMPE T1,AUTKD3 ;JUMP IF DON'T SUPPORT ANY
ADDM W,KDBIUN(W) ;FIX UP INITIAL UDB POINTER
ADDM W,KDBCUN(W) ;FIX UP CURRENT UDB POINTER
SUBI T1,1 ;CUZ WE COUNT FROM 0 TO N-1
ADD T1,KDBIUN(W) ;COMPUTE FINAL UDB POINTER
MOVEM T1,KDBFUN(W) ;STORE ADDRESS
AUTKD3: MOVE T1,.CPBIT## ;GET BIT FOR THIS CPU
IORM T1,KDBCAM(W) ;SET ACCESSIBILITY MASK IN KDB
IFN FTKL10,<
MOVSI T1,-<KDBIOE-KDBIOB> ;NUMBER OF WORDS TO CHECK
XMOVEI T2,KDBIOB(W) ;STARTING WORD
HRRZ T3,.CPDVC## ;<DEVICE CODE>/4
PUSHJ P,AUTDVC ;SET DEVICE CODES
>; END IFN FTKL10
MOVE T1,W ;KDB ADDRESS
MOVE T4,.CPDRV## ;DISPATCH
MOVE T2,DRVKLN(T4) ;KDB LENGTH
MOVEI T3,DR.UCK ;BIT TO TEST
TDNE T3,DRVCNF(T4) ;WANT TO UNCACHE THE KDB?
PUSHJ P,UNCACH ;UNCACHE THE ADDRESS RANGE
PUSHJ P,LNKKDB ;LINK KDB TO CHN AND OTHER KDBS
JRST CPOPJ1## ;RETURN
;ROUTINE TO SEE IF A KDB ALREADY EXISTS
FNDKDB: MOVE T1,.CPDRV## ;DRIVER DISPATCH
LDB T1,[POINTR (DRVCNF(T1),DR.DVT)] ;DEVICE TYPE
XMOVEI W,KDBTAB-KDBNXT(T1) ;SET PREDECESSOR
MOVE T1,.CPBIT## ;CPU BIT
FNDKD1: SKIPN W,KDBNXT(W) ;KDB THERE?
JRST CPOPJ1## ;NO
IFN FTKL10,<
MOVE T3,KDBDVC(W) ;GET <DEVICE CODE>/4 FROM KDB
HLL T3,KDBUNI(W) ;AND UNIT NUMBER TOO
TDNE T1,KDBCAM(W) ;ON THE RIGHT CPU?
CAME P3,T3 ;AND DEVICE CODE & UNIT NUMBER MATCH?
>; END IFN FTKL10
IFN FTKS10,<
;*** KS10 CODE HERE
>; END IFN FTKS10
JRST FNDKD1 ;NO
POPJ P, ;RETURN WITH KDB ADDRESS IN W
;ROUTINE TO LINK UP KDBS
LNKKDB: MOVE T1,.CPCHA## ;CHANNEL DATA BLOCK ADDRESS
MOVEM T1,KDBCHN(W) ;LINK TO KDB
MOVSI T2,-1 ;MAKE CHANNEL'S LIST
ADDB T2,CHNTBP(T1) ; OF KDBS ONE LONGER
AOBJN T2,. ;MOVE TO END OF EXISTING KDBS
MOVEI T2,-1(T2) ;GET ADDRESS OF WHERE TO STORE KDB
CAIL T2,CHNLEN(T1) ;BETTER BE WITHIN THE CHANNEL DATA BLOCK!
STOPCD .,STOP,AUTTMK, ;++TOO MANY KDBS ON CHANNEL
MOVEM W,(T2) ;STORE KDB ADDRESS IN CHN
MOVE T1,.CPDRV## ;DRIVER DISPATCH
LDB T1,[POINTR (DRVCNF(T1),DR.DVT)] ;GET DEVICE TYPE
XMOVEI T1,KDBTAB(T1) ;POINT TO HEAD OF KDB CHAIN
SUBI T1,KDBNXT ;FAKE UP PREDECESSOR
SYSPIF ;INTERLOCK
LNKKD1: SKIPN T2,KDBNXT(T1) ;LINK THIS KDB INTO CHAIN
JRST LNKKD2 ;END OF CHAIN
MOVE T3,KDBNAM(T2) ;GET KDB NAME
CAML T3,KDBNAM(W) ;IN PROPER ASCENDING ORDER?
JRST LNKKD2 ;SPLICE NEW KDB HERE
MOVE T1,T2 ;COPY PREVIOUS
JRST LNKKD1 ;LOOP BACK
LNKKD2: MOVEM T2,KDBNXT(W) ;LINK NEXT TO NEW
MOVEM W,KDBNXT(T1) ;LINK THIS TO PREVIOUS
SYSPIN ;RELEASE INTERLOCK
POPJ P, ;RETURN
SUBTTL ENTRY POINT -- AUTKIL - KILL (DELETE) A DDB
;THIS ROUTINE WILL UNLINK A DDB FROM THE DEVLST CHAIN, DELETE THE DDB,
;AND CLEAN UP ANY GENTAB ENTRIES THAT MAY EXIST.
;CALL: MOVE T1, DDB LENGTH
; MOVE T2, DDB ADDRESS
; PUSHJ P,AUTKIL
; <RETURN>
AUTKIL::SE1ENT ;ENTER SECTION ONE
PUSHJ P,SAVE2## ;SAVE P1 AND P2
PUSH P,F ;SAVE F
DMOVE P1,T1 ;COPY ARGUMENTS
MOVE F,P2 ;GET DDB ADDRESS
PUSHJ P,GENDEL ;DELETE GENTAB ENTRY IF NECESSARY
MOVE F,P2 ;...
LDB T1,PDVTYP## ;GET DEVICE TYPE
DDBSRL ;INTERLOCK DDB SCANNING
SKIPE F,DDBTAB(T1) ;PICK UP PROTOTYPE DDB
SKIPE T1,DEVNAM(F) ;MAKE SURE IT IS A PROTOTYPE
TRNA ;NO PROTOTYPE--MUST SEARCH
JRST AUTKI2 ;GOT IT--GO DELETE OUR ARGUMENT
XMOVEI F,DEVLST##-DEVSER ;GET META-PROTOTYPE
HLRZ T2,DEVNAM(F) ;GET GENERIC PORTION OF NAME
SKIPE T2 ;IF ANY
SKIPL T1,GENPTR## ;GET AOBJN INDEX TO GENTAB
JRST AUTKI2 ;NONE THERE--JUST TAKE IT FROM THE TOP
AUTKI1: CAML T2,GENTAB##(T1) ;HAVE WE FOUND OUR NICHE?
JRST AUTKI2 ;YES--NOW SCAN THE CHAIN
SKIPE GENTAB##+1(T1) ;IF THERE IS A POINTER,
MOVE F,GENTAB##+1(T1) ;UPDATE OUR G.L.B.
AOBJP T1,AUTKI2 ;ACCOUNT FOR TWO-WORD ENTRIES
AOBJN T1,AUTKI1 ;LOOP OVER ALL LESSER NAMES IN GENTAB
;FALL THROUGH TO AUTKI2
AUTKI2: CAMN P2,F ;MATCH?
JRST AUTKI3 ;YES
MOVE T1,F ;COPY CURRENT TO PREVIOUS
HLRZ F,DEVSER(F) ;LINK TO NEXT DDB
JUMPN F,AUTKI2 ;KEEP SEARCHING
DDBSRU ;RELEASE INTERLOCK
JRST FPOPJ## ;GIVE UP
AUTKI3: HLRZ T2,DEVSER(F) ;GET POINTER TO NEXT DDB
SKIPE T1 ;HAVE A PREVIOUS?
HRLM T2,DEVSER(T1) ;YES--POINT PREVIOUS AT IT
LDB T1,PDVTYP## ;GET INCOMING DEVTYP
CAME F,DDBTAB(T1) ;SKIP OVERHEAD IF NOT FIRST OF ITS KIND
JRST AUTKI4 ;RIGHT
SKIPE F,T2 ;NO PROTOTYPE--MOVE SUCCESSOR
LDB T2,PDVTYP## ;GET ITS DEVTYP
CAIE T1,(T2) ;DO THEY MATCH?
SETZ F, ;NO--PUNT THIS HEADER
MOVEM F,DDBTAB(T1) ;UPDATE FOR DEVCHK
AUTKI4: MOVE T1,DEVLST## ;GET START OF CHAIN
MOVEM T1,HNGLST## ;UPDATE SHADOW COPY
IFN FTNET,<
MOVE F,P2 ;RESTORE INCOMING DDB ADDRESS
SKIPE T1,DEVDRV(F) ;IF A DRIVER,
HRRZ T1,DRVDDB(T1) ;POINT AT ITS PROTOTYPE *** NON-EXTENDED
CAIN T1,(F) ;IF A PROTOTYPE,
JRST AUTKI5 ;DON'T COUNT IT
LDB T1,PDVSTA## ;GET ITS NODE NUMBER
CAME T1,ANFNUM## ;IF NOT LOCAL,
JRST AUTKI5 ;DON'T COUNT IT
LDB T1,PDVTYP## ;GET DEVICE TYPE AGAIN
SOSGE DDBCNT(T1) ;COUNT A DEVICE LOST
SETZM DDBCNT(T1) ;SANITY CHECK
PUSHJ P,NETDEV## ;UPDATE COUNTS IN NETNDB
> ;END IFN FTNET
AUTKI5: DDBSRU ;RELEASE INTERLOCK
DMOVE T1,P1 ;GET ARGUMENTS BACK
SKIPE T1 ;IF SIZE WAS GIVEN,
PUSHJ P,GIVWDS## ;RELEASE CORE
JRST FPOPJ## ;RESTORE F AND RETURN
SUBTTL ENTRY POINT -- AUTKSN - PROCESS KONTROLLER SERIAL NUMBERS
;THIS ROUTINE WILL STORE KONTROLLER SERIAL NUMBERS
;CALL: MOVE W, KDB ADDRESS
; DMOVE T1, SERIAL NUMBER WORDS
; PUSHJ P,AUTKSN
AUTKSN::PUSHJ P,SAVT## ;SAVE SOME ACS
SETZ T3, ;NO DRIVE NUMBER STUFF
PUSHJ P,AUTDSN ;FIXUP S/N IF ZERO
DMOVEM T1,KDBSER(W) ;STORE SERIAL NUMBER WORDS
POPJ P, ;RETURN
SUBTTL ENTRY POINT -- AUTMDT - SCAN THE MONGEN'ED DEVICE TABLES
;SCAN MONGEN'ED DEVICE TABLE
;THIS ROUTINE WILL SCAN FIRST THE MONGEN'ED DEVICE TABLE AND THEN
;THE DEFAULT TABLE (FROM THE DRIVER) FOR A MATCH ON THE FOLLOWING
;FIELDS:
; 1. CPU (COMPARED WITH .CPDVC)
; 2. DEVICE CODE OR UNIBUS ADDRESS (COMPARED WITH .CPDVC)
; 3. MASSBUS UNIT NUMBER
; 4. PHYSICAL DRIVE NUMBER
;
;ON A SUCCESSFUL MATCH, T1 WILL CONTAIN THE CORRESPONDING DATA WORD
;FROM ONE OF THE TABLES. THIS DATA WORD IS VERY DEVICE-SPECIFIC.
;DEFINITIONS FOR THIS WORD SHOULD BE DEFINED AS GLOBALS IN THE DRIVER
;OR THE SERVICE ROUTINES.
;
;CALL: MOVE T1, ADDRESS OF MONGEN'ED DEVICE TABLE
; MOVE T2, ADDRESS OF DEFAULT TABLE
; MOVE T3, UNIT,,DRIVE
; MOVE T4, FLAGS
; PUSHJ P,AUTMDT
; <NON-SKIP>
; <SKIP>
;
;UNIT MAY BE:
; 1. AN MASSBUS UNIT NUMBER
; 2. -1 TO MATCH ON ANY MASSBUS UNIT
;
;DRIVE MAY BE:
; 1. A PHYSICAL DRIVE NUMBER
; 2. -1 TO MATCH ON ANY PHYSICAL DRIVE
;
;FLAGS MAY BE:
; ANY VALID MD.XXX BITS
;
;NOTE THAT SPECIFYING -1,,-1 WILL CAUSE A MATCH ON ONLY THE CPU AND
;KONTROLLER FIELDS.
IFN FTKL10,<
AUTMDT::PUSHJ P,SAVE4## ;SAVE SOME ACS
DMOVE P1,T1 ;COPY TABLE ADDRESSES
DMOVE P3,T3 ;COPY MASSBUS UNIT,,DEVICE AND FLAGS
HLRZS T1 ;GET POSSIBLE SECTION NUMBER
CAIN T1,(MCSEC1) ;SECTION ONE?
HRRZS P1 ;YES
SKIPE P1 ;ZERO (MAYBE EXCLUDING MONGEN'ED TABLE)?
CAML P1,SYSSIZ## ;TABLE FROM MONGEN?
SKIPA ;DON'T ADJUST
ADDI P1,2 ;SKIP OVER PER-CPU COUNTERS
HRL P1,T1 ;RESTORE POSSIBLE SECTION NUMBER
HLRZS T2 ;GET POSSIBLE SECTION NUMBER
CAIN T2,(MCSEC1) ;SECTION ONE?
HRRZS P2 ;YES
SKIPE P2 ;ZERO (MAYBE NOT USING INTERNAL TABLE)?
CAML P2,SYSSIZ## ;INCASE ARGUMENTS PASSED BACKWARDS
SKIPA ;DON'T ADJUST
ADDI P2,2 ;...
HRL P2,T2 ;RESTORE POSSIBLE SECTION NUMBER
AUTMD1: PUSHJ P,MDTSCN ;TRY THE MONGEN'ED TABLE
JRST AUTMD2 ;NO MATCH
JRST AUTMD3 ;MAKE SURE IT'S OK
AUTMD2: SKIPE P1,P2 ;GET DEFAULT TABLE
PUSHJ P,MDTSCN ;AND GIVE IT A WHIRL
POPJ P, ;GIVE UP
SETZ P2, ;AVOID RECURSION
AUTMD3: MOVE T1,1(P1) ;GET DATA FOR THIS ENTRY
LDB T2,PMDDVC ;AND DEVICE CODE
JUMPN T2,CPOPJ1## ;RETURN IF HAVE ONE
PUSHJ P,MDTDVC ;LOOK FOR A DEVICE CODE
POPJ P, ;NONE FOUND
JRST CPOPJ1## ;RETURN GOODNESS
PMDCPU: POINTR ((P1),MD.CPU) ;BYTE POINTER TO CPU
PMDDVC: POINTR ((P1),MD.DVC) ;BYTE POINTER TO DEVICE CODE
PMDUNI: POINTR ((P1),MD.UNI) ;BYTE POINTER TO MASSBUS UNIT
PMDDRV: POINTR ((P1),MD.DRV) ;BYTE POINTER TO PHYSICAL DRIVE
MDTSCN: SKIPN T1,(P1) ;END OF TABLE?
POPJ P, ;YES--NO MATCH
CAMN T1,[EXP -1] ;ENTRY TO BE PATCHED BY RUNNING MONITOR?
AOJA P1,MDTSC1 ;IGNORE IT
;CHECK CPU AND DEVICE CODE
LDB T1,PMDCPU ;GET CPU NUMBER
CAIN T1,7 ;ALL CPUS?
MOVE T1,.CPCPN## ;MAKE IT OURS
ROT T1,-3 ;PUT IN BITS 0-2
LDB T2,PMDDVC ;GET DEVICE CODE
CAIN T2,0 ;ANY DEVICE CODE?
HRRZ T2,.CPDVC## ;...
HRR T1,T2 ;MERGE THE TWO
CAME T1,.CPDVC## ;MATCH SO FAR?
AOJA P1,MDTSC1 ;NO
;CHECK KONTROLLER DEFINITION
MOVEI T1,MD.KON ;BIT TO TEST
TRNE P4,MD.KON ;WANT KONTROLLER DEFINITION?
TDNN T1,(P1) ;AND IS THIS ONE?
SKIPA ;NO
JRST CPOPJ1## ;FOUND A MATCH
;CHECK MASSBUS UNIT NUMBER
LDB T1,PMDUNI ;GET MASSBUS UNIT NUMBER
HLRZ T2,P3 ;GET POSSIBLE UNIT NUMBER
TLC P3,-1 ;MATCH ON
TLCN P3,-1 ; ALL UNITS?
MOVEI T2,(T1) ;YES
CAIE T1,(T2) ;COMPARE
AOJA P1,MDTSC1 ;TRY ANOTHER
;CHECK PHYSICAL DRIVE
LDB T1,PMDDRV ;GET DRIVE NUMBER
HRRZ T2,P3 ;GET POSSIBLE DRIVE NUMBER
TRC P3,-1 ;MATCH ON
TRCN P3,-1 ; ALL DRIVES?
MOVEI T2,(T1) ;YES
CAIE T1,(T2) ;COMPARE
AOJA P1,MDTSC1 ;TRY ANOTHER
;FINALLY HAVE A MATCH
JRST CPOPJ1## ;RETURN
MDTSC1: AOS P1 ;ADVANCE TO NEXT ENTRY
JRST MDTSCN ;LOOP BACK AND TRY AGAIN
MDTDVC: PUSH P,P1 ;SAVE ENTRY ADDRESS FOR A MOMENT
MDTDV1: MOVEI P4,MD.KON ;WANT A KONTROLLER DEFINITION
PUSHJ P,MDTSCN ;CONTINUE CHECKING THE TABLE
JRST MDTDV2 ;GO LOOK AT DEFAULT TABLE
LDB T2,PMDDVC ;GET DEVICE CODE
JUMPN T2,MDTDV3 ;RETURN IF ONE EXISTS
JRST MDTDV1 ;ELSE KEEP CHECKING THIS TABLE
MDTDV2: SKIPN P1,P2 ;POINT TO THE DEFAULT TABLE
JRST MDTDV4 ;ALREADY DID IT
SETZ P2, ;ONLY DO THIS ONCE
JRST MDTDV1 ;LOOP BACK AND TRY AGAIN
MDTDV3: AOS -1(P) ;SKIP
MDTDV4: POP P,P1 ;GET ORIGINAL ENTRY ADDRESS BACK
POPJ P, ;AND RETURN
>; END IFN FTKL10
;THE CROCKY KS EQUIVALENT
IFN FTKS10,<
AUTMDT::LDB T1,[POINT 21,.CPDVC##,35] ;*** GET CURRENT UNIBUS ADAPTER & ADDRESS
CAMN T1,1(T2) ;*** MATCH WHAT DRIVER IS LOOKING FOR?
PUSHJ P,UBGOOD## ;*** DOES DEVICE EXIST?
POPJ P, ;*** NO
LDB T1,[POINTR (0(T2),MD.IVI)] ;*** GET IVI FROM DRIVER
DPB T1,[POINT 7,.CPDVC##,9] ;*** STORE IN .CPDVC
JRST CPOPJ1## ;*** GIVE GOOD RETURN
>; END IFN FTKS10
SUBTTL AUTOCONFIGURATION -- AUTMSK - SET/CLEAR DRIVE BITS IN A KDB MAP
;ROUTINE TO TOGGLE THE STATE OF A DRIVE BIT IN A KDB BIT MAP
;CALL: MOVE W, KDB ADDRESS
; MOVE T1, PHYSICAL DRIVE NUMBER
; MOVE T2, STATE,,MASK OFFSET WORD
; PUSHJ P,AUTMSK
; <NON-SKIP> ;ILLEGAL DRIVE NUMBER
; <SKIP> ;STATE SET AS REQUESTED
;
AUTMSK::PUSHJ P,SAVE2## ;SAVE P1 AND P2
HLRZ P1,T2 ;SAVE ON/OFF STATE
HRRZ P2,T2 ;GET MASK OFFSET WORD
ADD P2,W ;INDEX INTO KDB
MOVE T2,KDBDSP(W) ;DRIVER DISPATCH
LDB T2,[POINTR (DRVCF2(T2),DR.HDN)] ;HIGHEST DRIVE ON KONT
CAILE T1,(T2) ;WITHIN RANGE?
POPJ P, ;NO
IDIVI T1,44 ;DRIVES MAPPED PER WORD
MOVE T2,BITTBL##(T2) ;TRANSLATE DRIVE NUMBER TO BIT
HRRZ T3,(P2) ;GET OFFSET TO MASK IN KDB
ADD T3,W ;INDEX TO START OF MAP
ADDI T3,(T1) ;INDEX INTO MAP
JUMPE P1,AUTMS1 ;GO IF CLEARING BIT
SYSPIF ;INTERLOCK
IORM T2,(T3) ;SET BIT FOR SPECIFIED DRIVE
HRROS (P2) ;SET FLAG TOO
SYSPIN ;RELEASE INTERLOCK
JRST CPOPJ1## ;RETURN
AUTMS1: DMOVE T3,T2 ;COPY BIT AND ADDRESS TO A SAFER PLACE
MOVE T1,KDBDSP(W) ;DRIVER DISPATCH
LDB T1,[POINTR (DRVCF2(T1),DR.HDN)] ;HIGHEST DRIVE ON KONT
ADDI T1,44 ;ROUND UP
IDIVI T1,44 ;COMPUTE WORDS IN MAP
HRRZ T2,(P2) ;OFFSET TO START OF MAP
ADD T2,W ;INDEX INTO KDB
SYSPIF ;INTERLOCK
ANDCAM T3,(T4) ;CLEAR BIT FOR SPECIFIED DRIVE
HRRZS KDBIUM(W) ;ASSUME NO OTHER IGNORED DRIVES
AUTMS2: SKIPE (T2) ;ANY BITS SET?
JRST AUTMS3 ;YES
AOS T2 ;ADVANCE TO NEXT WORD
SOJG T1,AUTMS2 ;LOOP THROUGH MAP
SKIPA ;NO OTHER DRIVES IGNORED
AUTMS3: HRROS (P2) ;FLAG OTHER DRIVES STILL MARKED IN MAP
SYSPIN ;RELEASE INTERLOCK
JRST CPOPJ1## ;RETURN
SUBTTL AUTOCONFIGURATION -- AUTNAM - SET UP A DEVICE NAME
;ROUTINE TO BUILD A DEVICE NAME
;CALL: MOVE T1, SIXBIT /NAME/
; MOVE T2, NUMBER
; PUSHJ P,AUTNAM
;
;ON RETURN, T1 HAS THE UPDATED NAME
AUTNAM::MOVE T4,.CPDRV## ;DRIVER DISPATCH
MOVE T4,DRVCNF(T4) ;GET CONFIG WORD
TRNE T4,DR.NMC ;NAME INCLUDE CPU NUMBER?
TROA T1,'0' ;YES
ADDI T1,'A' ;ELSE TRANSLATE NUMBER TO NAME
ROT T1,-6 ;LEFT JUSTIFY
MOVSI T3,770000 ;CHARACTER MASK
MOVSI T4,-6 ;AOBJN POINTER
AUTNA1: TDNN T3,T2 ;CHARACTER IN USE
JRST AUTNA2 ;NO
LSH T1,-6 ;SLIDE CHARACTER OVER
LSH T3,-6 ;AND MASK TOO
AOBJN T4,AUTNA1 ;LOOP BACK
POPJ P, ;FULL WORD NAME?
AUTNA2: IOR T1,T2 ;MERGE WITH CHARACTER
POPJ P, ;AND RETURN
SUBTTL AUTOCONFIGURATION -- AUTSET - SET UP CPU VARIABLES
;CALL: MOVE T1, <DEVICE CODE>/4 (OR <IVI>B9 + <UNIBUS ADDR>B35)
; MOVE T2, DISPATCH
; MOVE T3, CHANNEL DATA BLOCK
; PUSHJ P,AUTSET
; <RETURN>
AUTSET::MOVE T4,.CPCPN## ;GET CPU NUMBER
DPB T4,[POINT 3,T1,2] ;STORE IN BITS 0-2
MOVEM T1,.CPDVC## ;STORE <CPU>B2 + (<DEVICE CODE>/4 OR UBA ADDR)
MOVEM T2,.CPDRV## ;STORE DRIVER DISPATCH
MOVEM T3,.CPCHA## ;STORE CHANNEL DATA BLOCK ADDRESS
IFN FTKL10,<
DPB T1,[POINT 7,.CPCNI##,9] ;MAKE CONI
DPB T1,[POINT 7,.CPCNO##,9] ;MAKE CONO
DPB T1,[POINT 7,.CPDTI##,9] ;MAKE DATAI
DPB T1,[POINT 7,.CPDTO##,9] ;MAKE DATAO
DPB T1,[POINT 7,.CPBKI##,9] ;MAKE BLKI
DPB T1,[POINT 7,.CPBKO##,9] ;MAKE BLKO
>; END IFN FTKL10
POPJ P, ;RETURN
SUBTTL AUTOCONFIGURATION -- AUTSYS - SYSINI/ONCE ONLY DDB LINKAGE
$INIT
AUTSYS::PUSHJ P,SAVE4## ;SAVE SOME ACS
XMOVEI F,DEVLST##-DEVSER ;PRESET LINKAGE
MOVSI P1,INTNUM## ;AOBJN POINTER TO INTTAB
AUTSY1: LDB F,PINTDB## ;PROTOTYPE DDB ADDRESS
JUMPE F,AUTSY3 ;NOTHING TO DO IF NO DDB
LDB P3,PINTSZ## ;PROTOTYPE DDB LENGTH
LDB P4,PINTNO## ;NUMBER OF DDBS TO CREATE
MOVNS P4 ;NEGATE
HRLZS P4 ;MAKE AN AOBJN POINTER
AUTSY2: PUSHJ P,DDBCOP ;COPY PROTOTYPE DDB
JRST AUTSY3 ;NO CORE FOR DDB
PUSHJ P,DDBNAM ;FIX UP NAME
LDB T1,PINTCH## ;GET PI CHANNEL NUMBER
PUSHJ P,DDBPIC ;FIX UP INTERLOCK
MOVE T1,JBTLOC## ;LOCAL STATION NUMBER
DPB T1,PDVSTA## ;STORE FOR NETSER
PUSHJ P,AUTLNK ;LINK IT INTO DEVLST
AOBJN P4,AUTSY2 ;LOOP CREATING ALL NECESSARY DDBS
AUTSY3: AOBJN P1,.+1 ;ACCOUNT FOR TWO WORD ENTRIES
AOBJN P1,AUTSY1 ;ONTO THE NEXT INTTAB ENTRY
IFN FTNET,<PUSHJ P,NETDEV##> ;UPDATE DEVICE COUNTS IN HOST NDB
;LINK DEVICE SERVICE ROUTINES TOGETHER
MOVSI P1,INTNUM## ;NEGATIVE NUMBER OF SERVICE ROUTINES*2
AUTSY7: LDB T1,PINTCH## ;GET NEXT PI NUMBER
JUMPE T1,AUTSY9 ;DOES THIS DEVICE HAVE A PI CHANNEL (PTY)?
LSH T1,1 ;SHIFT LEFT ONE SO MATCH PI LOCATIONS
LDB T2,PINTCP## ;GET CPU NUMBER
IMULI T2,.CPLEN## ;OFFSET TO CDB
MOVE T2,.C0EPT##(T2) ;GET EPT ADDRESS
ADDI T2,(T1) ;OFFSET INTO INTERRUPT LOCS
MOVE T2,.EPIL(T2) ;GET INTERRUPT INSTRUCTION
ADDI T2,3 ;SKIP XPCW BLOCK
AUTSY8: HRRZ T1,T2 ;SAVE IT (EITHER JRST DEV'INT OR XJEN CH'N)
MOVE T2,1(T1) ;PICK UP INSTR. FOLLOWING INTERRUPT CONSO
TLNN T2,000740 ;IS IT AN XJEN?
JRST AUTSY8 ;NO, KEEP LOOKING
LDB T3,PINTIN## ;YES, LAST DEVICE SO FAR, GET DEV'INT
SKIPN (T3) ;DEV'INT=0?
JRST AUTSY9 ;YES, MUST BE VECTORED INTERRUPT DEVICE
HRLI T3,(JRST) ;MAKE JRST INSTR.
MOVEM T3,1(T1) ;CHANGE XJEN CH'N TO JRST DEV'NT
MOVEM T2,1(T3) ;MAKE DEV'NT+1 BE XJEN CH'N
AUTSY9: AOBJN P1,.+1 ;PICKUP EVERY OTHER WORD
AOBJN P1,AUTSY7 ;ANY MORE INTERRUPT SERVICE ROUTINES?
POPJ P, ;NO, RETURN
;COPY PROTOTYPE DDB
DDBCOP: SKIPE P4 ;ONLY WANT ONE DDB?
TRNN P4,-1 ;OR IS THIS UNIT ZERO?
JRST CPOPJ1## ;JUST RETURN GOODNESS
MOVEI T1,(P3) ;LENGTH OF DDB
PUSHJ P,GETCOR ;ALLOCATE CORE
POPJ P, ;NONE AVAILABLE
MOVE T4,T2 ;SAVE ADDRESS
IFE FTXMON,<
MOVSI T3,(F) ;PROTOTYPE DDB ADDRESS
HRR T3,T2 ;DESTINATION
ADDI T2,(T1) ;COMPUTE END OF BLT
BLT T3,-1(T2) ;COPY
> ;END IFE FTXMON
IFN FTXMON,<
MOVE T3,T2 ;DESTINATION
MOVE T2,F ;PROTOTYPE DDB ADDRESS
EXTEND T1,[XBLT] ;COPY
> ;END IFN FTXMON
MOVE F,T4 ;POSITION NEW DDB ADDRESS
JRST CPOPJ1## ;RETURN GOODNESS
;FIX UP DDB NAME
DDBNAM: HLLZ T1,DEVNAM(F) ;GENERIC NAME EXIST?
JUMPE T1,CPOPJ## ;CAN DO NOTHING WITHOUT IT
HRRZ T1,P4 ;GET UNIT NUMBER
DPB T1,PUNIT## ;STORE IN DDB
LDB T2,PDVTYP## ;***GET DEVICE TYPE
CAIN T2,.TYDTA ;***DTA?
JRST DDBNA2 ;***YES
SKIPN T4,DEVDRV(F) ;GET DRIVER DISPATCH
JRST DDBNA0 ;NO DRIVER DISPATCH, ASSUME STATION NUMBERS
; INCLUDED IN OCTAL DEVICE NAME
MOVEI T3,DR.NET ;BIT TO TEST
TDNN T3,DRVCNF(T4) ;WANT TO INCLUDE ANF-10 STATION NAMES?
JRST DDBNA1 ;NO
DDBNA0: MOVE T3,JBTLOC## ;LOCAL STATION NUMBER
DPB T3,[POINT 6,T1,32] ;SET FOR GENERATING NAME
TRO T1,1000 ;MAKE SURE OF LEADING ZERO
JRST DDBNA2 ;FORCE OCTAL
DDBNA1: MOVEI T3,DR.DDN ;BIT TO TEST
TDNE T3,DRVCNF(T4) ;WANT DECIMAL DEVICE NAME?
SKIPA T2,[EXP DECNAM] ;YES
DDBNA2: MOVEI T2,OCTNAM ;MAKE IT OCTAL
PUSHJ P,(T2) ;GENERATE SIXBIT NUMBER
HRRM T1,DEVNAM(F) ;STORE INTO NAME
POPJ P, ;RETURN
;FIX UP PI CHANNEL INTERRUPT INTERLOCK
DDBPIC:
IFN FTMP,<
LDB T2,DEYCPF## ;GET CPU NUMBER
CAIE T2,CPFBOO## ;GENERIC?
CAIN T2,CPFBIT## ;BIT MASKED DEVICE?
TDZA T2,T2 ;YES--USE CPU0 INTERLOCKS
LSH T2,3 ;(CPU * 10) + CHANNEL
ADDI T2,INTL0##(T1) ;OFFSET INTO TABLE
HRRM T2,DEVCPU(F) ;SAVE LOCATION OF INTERLOCK
>
POPJ P, ;RETURN
$HIGH
SUBTTL AUTOCONFIGURATION -- AUTUDB - BUILD A UDB
;BUILD A UDB
;CALL: MOVE W, KDB ADDRESS
; MOVE T1, PHYSICAL DRIVE NUMBER,,UDB TABLE OFFSET
; PUSHJ P,AUTUDB
; <NON-SKIP> ;NO CORE AVAILABLE
; <SKIP> ;AC U = NEW UDB ADDRESS
AUTUDB::PUSHJ P,SAVE3## ;SAVE SOME ACS
MOVE T4,.CPDRV## ;DRIVER DISPATCH
MOVE P1,DRVUDB(T4) ;COPY PROTOTYPE UDB ADDRESS
MOVE P2,DRVULN(T4) ;COPY PROTOTYPE UDB LENGTH
MOVE P3,T1 ;SAVE DRIVE NUMBER AND OFFSET
HRRZS T1 ;KEEP ONLY UDB TABLE OFFSET
ADD T1,KDBIUN(W) ;INDEX INTO TABLE
SKIPE U,(T1) ;SEE IF UDB ALREADY EXISTS
JRST AUTUD1 ;IT DOES SO NO CORE TO ALLOCATE
MOVE T1,P2 ;GET PROTOTYPE UDB LENGTH
PUSHJ P,GETCOR ;ALLOCATE CORE
POPJ P, ;CAN'T DO IT
MOVE U,T2 ;COPY UDB ADDRESS
JUMPE P1,AUTUD1 ;ONWARD IF NO PROTOTYPE
IFE FTXMON,<
HRLI T2,(P1) ;PROTOTYPE ADDRESS
BLT T2,-1(P2) ;COPY INTO WORKING STORAGE
> ;END IFE FTXMON
IFN FTXMON,<
MOVE T1,P2 ;PROTOTYPE LENGTH
MOVE T2,P1 ;PROTOTYPE ADDRESS
MOVE T3,U ;DESTINATION
EXTEND T1,[XBLT] ;COPY INTO WORKING STORAGE
> ;END IFN FTXMON
AUTUD1: HRRZ T1,P3 ;GET TABLE OFFSET
ADD T1,KDBIUN(W) ;INDEX INTO UDB TABLE
MOVEM U,(T1) ;SAVE UDB ADDRESS
HLRZ T1,P3 ;GET PHYSICAL DRIVE NUMBER
PUSHJ P,DECNAM ;CONVERT
IOR T1,KDBNAM(W) ;INCLUDE KONTROLLER DESIGNATION
SKIPN UDBKDB(U) ;DON'T OVERWRITE NAME IF HAVE A PRIMARY KDB
MOVEM T1,UDBNAM(U) ;SAVE
HLRZM P3,UDBPDN(U) ;STORE PHYSICAL DRIVE NUMBER
MOVE T1,.CPBIT## ;GET BIT FOR THIS CPU
IORM T1,UDBCAM(U) ;SET ACCESSIBILITY MASK IN UDB
PUSHJ P,LNKUDB ;LINK UP UDB TO KDB AND UNCACHE IF NEEDED
JRST CPOPJ1## ;RETURN
;ROUTINE TO LINK UP UDB TO KDB AND UNCACHE UDB IF NECESSARY
;CALL: MOVE U, UDB ADDRESS
; MOVE W, KDB ADDRESS
; PUSHJ P,LNKUDB
LNKUDB: XMOVEI T1,UDBKDB(U) ;POINT TO UDB'S TABLE
MOVSI T2,-MXPORT ;AOBJN POINTER
SETZ T3, ;CLEAR FREE SLOT ADDRESS
LNKUD1: CAMN W,(T1) ;FOUND EXISTING ENTRY?
JRST LNKUD3 ;NO NEED TO UPDATE TABLE
SKIPE (T1) ;FREE SLOT?
JRST LNKUD2 ;NO
SKIPN T3 ;ALREADY FOUND FIRST FREE ENTRY?
MOVE T3,T1 ;NO--REMEMBER ADDRESS
LNKUD2: AOS T1 ;ADVANCE POINTER
AOBJN T2,LNKUD1 ;KEEP SEARCHING
SKIPE T3 ;TABLE FULL??
MOVEM W,(T3) ;POINT UDB BACK TO KDB
LNKUD3: MOVE T3,KDBCAM(W) ;CURRENT KDB'S ACCESSIBILITY MASK
IORM T3,UDBCAM(U) ;UPDATE FOR UDB
MOVE T1,U ;UDB ADDRESS
MOVE T4,.CPDRV## ;DISPATCH
MOVE T2,DRVULN(T4) ;UDB LENGTH
MOVEI T3,DR.UCU ;BIT TO TEST
TDNE T3,DRVCNF(T4) ;WANT TO UNCACHE THE UDB?
PJRST UNCACH ;UNCACHE THE ADDRESS RANGE AND RETURN
POPJ P, ;RETURN
SUBTTL AUTOCONFIGURATION -- AUTVIA - COMPUTE VECTOR TABLE OFFSET
;COMPUTE VECTOR TABLE OFFSET FOR INTERRUPT INSTRUCTION(S)
;CALL: MOVE T1, UBA NUMBER
; MOVE T2, INTERRUPT VECTOR INDEX (BYTE INDEX)
; PUSHJ P,AUTVIA
; <RETURN> ;T1 = ADDRESS OF PRIMARY INTERRUPT INSTRUCTION
;CALL AUTVII TO USE DATA DIRECTLY FROM .CPDVC.
IFN FTKS10,<
AUTVIA::LSH T2,-2 ;CONVERT BYTE OFFSET TO WORD OFFSET
JRST AUTVI1 ;CONTINUE
AUTVII::LDB T1,[POINT 3,.CPDVC##,17] ;GET UBA NUMBER
LDB T2,[POINT 7,.CPDVC##,9] ;GET <INTERRUPT VECTOR INDEX>/4
AUTVI1: MOVE T3,.CPEPT## ;GET ADDRESS OF EXEC PROCESS TABLE
ADD T3,T1 ;OFFSET EPT ADDRESS BY UNIBUS ADAPTER NUMBER
MOVE T1,.EPVIT-1(T3) ;GET ADDRESS OF VECTOR TABLE
ADD T1,T2 ;COMPUTE INTERRUPT INSTRUCTION ADDRESS IN TABLE
POPJ P, ;RETURN
>; END IFN FTKS10
SUBTTL DATA BASE INTERLOCK CONTROL -- AUTOWN - CHECK INTERLOCK OWNERSHIP
;CHECK INTERLOCK TO SEE IF IT IS OWNED BY THE CALLER
;CALL: PUSHJ P,AUTOWN
; <NON-SKIP> ;NOT OWNED
; <SKIP> ;OWNED
$CSUB
AUTOWN::PUSH P,T1 ;SAVE T1
PUSHJ P,UUOLVL## ;AT UUO LEVEL?
TDZA T1,T1 ;NO
MOVE T1,.CPJOB## ;GET JOB ON THIS CPU
CAMN T1,.CPATO## ;COMPARE WITH INTERLOCK OWNER ID
AOS -1(P) ;WE ALREADY OWN IT
JRST TPOPJ## ;RESTORE T1 AND RETURN
$HIGH
SUBTTL DATA BASE INTERLOCK CONTROL -- AUTLOK - GET INTERLOCK
;GET PER-CPU INTERLOCK
;THIS ROUTINE CHECKS TO SEE IF THE DDB INTERLOCK IS AVAILABLE, BUT
;NEVER GETS THE INTERLOCK. THE REASON FOR THIS IS SIMPLE; QUITE OFTEN,
;THE CALLER WILL NEED THE DDB INTERLOCK (AUTDDB FOR EXAMPLE). IF THIS
;OCCURS AT CLOCK LEVEL, AND THE DDB INTERLOCK WASN'T AVAILABLE, DDBLOK
;WOULD SPIN AND MOST LIKELY CAUSE A KAF. IF THE CALLER IS AT UUO LEVEL,
;THIS ADDITIONAL OVERHEAD OF CHECKING IS NEGLIGIBLE AND THE POSSIBILITY
;OF BEING RESCHEDULED BECAUSE THE INTERLOCK IS NOT AVAILABLE IS NORMALLY
;EXPECTED.
;CALL: PUSHJ P,AUTLOK
; <NON-SKIP> ;INTERLOCK NOT AVAILABLE
; <SKIP> ;DATA BASE INTERLOCKED
AUTLOK::PUSH P,T1 ;SAVE T1
PUSHJ P,UUOLVL## ;AT UUO LEVEL?
TDZA T1,T1 ;NO
MOVE T1,.CPJOB## ;GET JOB ON THIS CPU
CAMN T1,.CPATO## ;DO WE ALREADY OWN THE INTERLOCK?
JRST TPOPJ1## ;YES--NOTHING TO DO HERE
AUTLO1:
IFN FTMP,<
SKIPL INTRDD## ;IS THE DDB INTERLOCK AVAILABLE?
JRST AUTLO2 ;NO
> ;END IFN FTMP
AOSE .CPATR## ;TRY TO GET AUTCON INTERLOCK
JRST AUTLO2 ;SPIN
MOVEM T1,.CPATO## ;STORE INTERLOCK OWNER
JRST TPOPJ1## ;RETURN
AUTLO2: JUMPE T1,TPOPJ## ;CAN'T SLEEP IF INTERRUPT LEVEL
PUSH P,T1 ;SAVE OWNER ID
MOVEI T1,1 ;ONE SECOND
PUSHJ P,SLEEPF## ;ZZZZZZ
POP P,T1 ;GET OWNER ID BACK
JRST AUTLO1 ;TRY AGAIN
SUBTTL DATA BASE INTERLOCK CONTROL -- AUTULK - GIVE UP INTERLOCK
;GIVE UP PER-CPU INTERLOCK
;CALL: PUSHJ P,AUTULK
AUTULK::SETOM .CPATO## ;RESET INTERLOCK OWNER ID
SETOM .CPATR## ;CLEAR INTERLOCK
POPJ P, ;RETURN
SUBTTL GENTAB MANAGEMENT -- GENADD - ADD A DDB
GENADD: MOVE T1,GENPTR## ;GET POINTER TO GENTAB
HLRZ T2,DEVNAM(F) ;GENERIC NAME
JUMPE T2,CPOPJ## ;CHECK FOR STRANGE DEVICES
GENAD1: CAMN T2,GENTAB##(T1) ;MATCH?
JRST GENAD2 ;YES--SEE IF THE ORDER IS CORRECT
AOBJN T1,.+1 ;ACCOUNT FOR TWO WORD ENTRIES
AOBJN T1,GENAD1 ;LOOP THROUGH TABLE
CAILE T1,GENLEN##-2 ;ROOM FOR MORE?
POPJ P, ;GIVE UP IF TABLE IS FULL
MOVEM T2,GENTAB##(T1) ;STORE NEW GENERIC NAME
MOVEM F,GENTAB##+1(T1) ;AND FIRST DDB OF ITS KIND
PJRST GENSRT ;GO SORT GENTAB, SET GENPTR, AND RETURN
GENAD2: SKIPN GENTAB##+1(T1) ;ABOUT TO ADD THE FIRST ENTRY?
JRST GENAD3 ;JUST STUFF DDB AT HEAD OF CHAIN
LDB T2,PUNIT## ;GET NEW UNIT
LDB T3,PDVSTA## ;AND NEW STATION
HRL T2,T3 ;MERGE
PUSH P,F ;SAVE F
MOVE F,GENTAB##+1(T1) ;POINT TO OLD DDB
LDB T3,PUNIT## ;GET NEW UNIT
LDB T4,PDVSTA## ;AND NEW STATION
HRL T3,T4 ;MERGE
POP P,F ;RESTORE F
CAMG T2,T3 ;SHOULD NEW DDB PRECEED OLD ONE?
GENAD3: MOVEM F,GENTAB##+1(T1) ;YES--UPDATE FIRST DDB OF ITS KIND
POPJ P, ;AND RETURN
SUBTTL GENTAB MANAGEMENT -- GENDEL - DELETE A DDB
GENDEL: MOVE T1,GENPTR## ;GET POINTER TO GENTAB
HLRZ T2,DEVNAM(F) ;GENERIC NAME
GENDE1: CAMN T2,GENTAB##(T1) ;MATCH?
JRST GENDE2 ;YES
AOBJN T1,.+1 ;ACCOUNT FOR TWO WORD ENTRIES
AOBJN T1,GENDE1 ;LOOP THROUGH TABLE
POPJ P, ;NOT IN THE TABLE??
GENDE2: CAME F,GENTAB##+1(T1) ;FIRST DDB OF ITS KIND?
POPJ P, ;NO--NOTHING TO DO
DDBSRL ;INTERLOCK DDB SCANNING
HLRZ T2,DEVSER(F) ;GET NEXT DDB
JUMPE T2,GENDE3 ;END OF CHAIN?
HLRZ T3,DEVNAM(T2) ;AND IT'S GENERIC NAME
CAME T3,GENTAB##(T1) ;SAME KIND?
TDZA T2,T2 ;NO--MUST DELETE ENTRY
MOVEM T2,GENTAB##+1(T1) ;MAKE DDB THE FIRST OF ITS KIND
GENDE3: DDBSRU ;RELEASE INTERLOCK
JUMPN T2,CPOPJ## ;RETURN IF JUST SWITCHED POINTERS
MOVEI T2,-1 ;ELSE FLAG ENTRY
SETZ T3, ; ABOUT TO BE FREED
DMOVEM T2,GENTAB##(T1) ;UPDATE
PJRST GENSRT ;GO SORT GENTAB, SET GENPTR, AND RETURN
SUBTTL GENTAB MANAGEMENT -- GENSRT - SORT GENTAB
GENSRT: PUSHJ P,SAVE2## ;SAVE P1 AND P2
DDBSRL ;INTERLOCK DDB SCANNING
GENSR1: MOVSI P1,-GENLEN##+2 ;AOBJN POINTER (TWO WORD ENTRIES)
SETZ P2, ;INIT CHANGE FLAG
GENSR2: DMOVE T1,GENTAB##(P1) ;GET NAME, FIRST DDB
DMOVE T3,GENTAB##+2(P1)
CAIG T1,(T3) ;IN THE PROPER ORDER?
JRST GENSR3 ;YES
EXCH T1,T3 ;SWAP
EXCH T2,T4 ;...
DMOVEM T1,GENTAB##(P1) ;REPLACE
DMOVEM T3,GENTAB##+2(P1)
AOS P2 ;FLAG THE CHANGE
GENSR3: AOBJN P1,.+1 ;ACCOUNT FOR TWO WORD ENTRIES
AOBJN P1,GENSR2 ;LOOP THROUGH TABLE
JUMPN P2,GENSR1 ;DO IT AGAIN IF SOMETHING CHANGED
MOVSI P1,-GENLEN##+2 ;AOBJN POINTER (TWO WORD ENTRIES)
GENSR4: HRRE T1,GENTAB##(P1) ;GET NAME
AOJE T1,GENSR5 ;FOUND LOGICAL END YET (0,,-1) ?
AOBJN P1,.+1 ;ACCOUNT FOR TWO WORD ENTRIES
AOBJN P1,GENSR4 ;LOOP THROUGH TABLE
GENSR5: MOVNI T1,(P1) ;-LENGTH
HRLZM T1,GENPTR## ;SAVE FOR DDB SCANNING
DDBSRU ;RELEASE INTERLOCK
POPJ P, ;RETURN
SUBTTL MASSBUS REGISTER I/O -- RDDTR/RDDTN - READ DRIVE TYPE REGISTER
;READ A DRIVE TYPE REGISTER OR NAME
;CALL: SKIPA P1, MASSBUS UNIT,,0 ;IF AUTOCONFIGURING
; MOVE W, KDB ADDRESS ;IF NORMAL TIMESHARING
; PUSHJ P,RDDTR/RDDTN
; <RETURN>
;
;ON RETURN, T2 HAS THE DATAI RESULTS
;ALL ACS ARE PRESERVED
RDDTR:: TDZA T2,T2 ;SIMPLE DATAI ENTRY POINT
RDDTN:: MOVEI T2,1 ;TRANSLATE DTR TO NAME
PUSH P,T2 ;SAVE FLAG
IFN FTKL10,<
PUSHJ P,AUTOWN ;DO WE OWN THE DATA BASE INTERLOCK?
JRST RDDTR1 ;NO
MOVE T2,T1 ;SAVE T1
MOVEI T1,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR RAE
XCT .CPCNO## ;CONO DEV,(T1)
MOVE T1,T2 ;RESTORE T1
RDDTR1:
>; END IFN FTKL10
IFN FTKL10,<MOVSI T2,(.DIDTR)> ;DRIVE TYPE REGISTER
IFN FTKS10,<MOVSI T2,.DODT> ;DRIVE TYPE REGISTER
PUSHJ P,RDMBR ;READ IT
ANDI T2,TR.TYP ;MASK OUT JUNK
SKIPN (P) ;WANT TO RETURN NAME INSTEAD?
JRST [POP P,(P) ;NO--PHASE STACK
POPJ P,] ;AND RETURN
MOVEM P1,(P) ;SAVE P1
PUSH P,P2 ;SAVE P2
MOVSI P1,-DTRLEN ;AOBJN POINTER
RDDTR2: HLRZ P2,DTRTBL(P1) ;GET A DRIVE TYPE CODE
CAIN P2,(T2) ;A MATCH?
JRST RDDTR3 ;YES
AOBJN P1,RDDTR2 ;KEEP SEARCHING
SKIPA P2,[[EXP 0]] ;NO MATCH
RDDTR3: HRRZ P2,DTRTBL(P1) ;GET ADDRESS OF NAME
MOVE T2,(P2) ;AND GET NAME
POP P,P2 ;RESTORE P2
POP P,P1 ;RESTORE P1
POPJ P, ;AND RETURN
;TABLE OF DRIVE TYPE REGISTER CODES AND ASSOCIATED NAMES
DTRTBL: XWD 000,['RS03 '] ;RH10 (4 US/WD XFER RATE)
XWD 001,['RS03 '] ;RH10 (8 US/WD XFER RATE)
XWD 002,['RS04 '] ;RH10 (4 US/WD XFER RATE)
XWD 003,['RS04 '] ;RH10 (8 US/WD XFER RATE)
XWD 010,['TM02 '] ;TM02
XWD 011,['TU16 '] ;TM02
XWD 012,['TU45 '] ;TM02
XWD 013,['TE16 '] ;TM02
XWD 014,['TU77 '] ;TM02
XWD 020,['RP04 '] ;RH10/RH11/RH20 (88 MB)
XWD 021,['RP05 '] ;RH10/RH11/RH20 (100 MB)
XWD 022,['RP06 '] ;RH10/RH11/RH20
; XWD 024,['RM02 '] ;RH10/RH11/RH20
; XWD 025,['RM03 '] ;RH10/RH11/RH20
XWD 024,['RM03 '] ;RH10/RH11/RH20
XWD 026,['XRM02X'] ;RH10/RH11/RH20
XWD 027,['XRM03X'] ;RH10/RH11/RH20
XWD 040,['RP07 '] ;RH10/RH20 (RP07-XX 300MB)
XWD 041,['RP07 '] ;RH10/RH20 (RP07-XX 300MB)
XWD 042,['RP07 '] ;RH10/RH20 (RP07+ 600MB)
XWD 043,['RP07 '] ;RH10/RH20 (RP07+ 600MB)
XWD 050,['TM03 '] ;TM03
XWD 051,['TU16 '] ;TM03
XWD 052,['TU45 '] ;TM03
XWD 053,['TE16 '] ;TM03
XWD 054,['TU77 '] ;TM03
XWD 060,['DX20-A'] ;DX20 V100 ADAPTER FOR TAPE SUBSYSTEM
XWD 061,['DX20-D'] ;DX20 V200 ADAPTER FOR DISK SUBSYSTEM
XWD 062,['DX20-M'] ;DX20 V400 ADAPTER FOR MASSBUS TO MASSBUS
XWD 063,['DX20-?'] ;DX20 (FUTURE)
XWD 063,['DX20-?'] ;DX20 (FUTURE)
XWD 064,['DX20-?'] ;DX20 (FUTURE)
XWD 065,['DX20-?'] ;DX20 (FUTURE)
XWD 066,['DX20-?'] ;DX20 (FUTURE)
XWD 067,['DX20-?'] ;DX20 (FUTURE)
XWD 070,['DX20-?'] ;DX20 (FUTURE)
XWD 071,['DX20-?'] ;DX20 (FUTURE)
XWD 072,['DX20-?'] ;DX20 (FUTURE)
XWD 073,['DX20-?'] ;DX20 (FUTURE)
XWD 074,['DX20-?'] ;DX20 (FUTURE)
XWD 075,['DX20-?'] ;DX20 (FUTURE)
XWD 076,['DX20-?'] ;DX20 (FUTURE)
XWD 077,['DX20-?'] ;DX20 (FUTURE)
XWD 100,['TM78 '] ;TM78
XWD 101,['TU78/9'] ;TM78
DTRLEN==.-DTRTBL ;LENGTH OF TABLE
SUBTTL MASSBUS REGISTER I/O -- RDMBR - READ REGISTER
;READ A DRIVE OR CONTROLLER REGISTER
;CALL: SKIPA P1, MASSBUS UNIT,,0 ;IF AUTOCONFIGURING
; MOVE W, KDB ADDRESS ;IF NORMAL TIMESHARING
; MOVE T2, REGISTER
; PUSHJ P,RDMBR
; <RETURN>
;
;ON RETURN, T2 HAS THE DATAI RESULTS
;ALL ACS ARE PRESERVED
IFN FTKL10,<
RDMBR:: PUSHJ P,SAVW## ;SAVE W
PUSH P,T1 ;SAVE T1
PUSH P,T3 ;SAVE T3
PUSHJ P,AUTOWN ;DO WE OWN THE DATA BASE INTERLOCK?
JRST RDMBR1 ;NO--DO NORMAL STUFF
XMOVEI W,.CPCNI##-KDBCNI ;FAKE KDB I/O INSTRUCTIONS
HLRZ T3,P1 ;MASSBUS UNIT NUMBER
SKIPA ;ENTER COMMON CODE
RDMBR1: HLRZ T3,KDBUNI(W) ;MASSBUS UNIT NUMBER
TLO T2,<(DO.DRE)>(T3) ;SET UNIT, NO RAE
MOVE T3,KDBDVC(W) ;GET DEVICE CODE
CAIL T3,FSTICD/4 ;INTERNAL
CAILE T3,LSTICD/4 ; CHANNEL?
TLZ T2,<(DO.DRE)> ;NO
PUSH P,T2 ;SAVE THE ARGUMENT
XCT KDBDTO(W) ;TELL MBC WHICH REGISTER WE WANT TO READ
IMULI P,1 ;WAIT FOR THINGS
IMULI P,1 ; TO SETTLE DOWN
XCT KDBDTI(W) ;READ THE VALUE
XCT KDBCNI(W) ;AND THE STATUS
TRNN T1,CI.RAE ;REGISTER ACCESS ERROR?
JRST RDMBR3 ;NO
MOVEI T3,^D10 ;RETRY OPERATION 10 TIMES
RDMBR2: MOVEI T1,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR RAE
XCT KDBCNO(W) ;CLEAR THE ERROR
MOVE T2,(P) ;GET DATAO ARGUMENT BACK
XCT KDBDTO(W) ;SETUP THE PREPARATION REGISTER AGAIN
IMULI P,1 ;WAIT FOR THINGS
IMULI P,1 ; TO SETTLE DOWN
XCT KDBDTI(W) ;READ THE VALUE
XCT KDBCNI(W) ;AND THE STATUS
TRNE T1,CI.RAE ;REGISTER ACCESS ERROR?
SOJG T3,RDMBR2 ;MUST TRY AGAIN
MOVEI T1,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR RAE
XCT KDBCNO(W) ;MAKE SURE RAE IS CLEARED
RDMBR3: POP P,(P) ;BRING STACK INTO PHASE
POP P,T3 ;RESTORE T3
POP P,T1 ;RESTORE T1
ANDI T2,DO.BAD ;RETURN ONLY DATA BITS
POPJ P, ;RETURN
> ;END IFN FTKL10
IFN FTKS10,<
RDMBR:: PUSH P,T1 ;SAVE AN AC
PUSH P,T3 ;SAVE ANOTHER
PUSHJ P,AUTOWN ;DO WE OWN THE DATA BASE INTERLOCK?
SKIPA T1,KDBDVC(W) ;NO, GET CSR ADDRESS FROM KDB
LDB T1,[POINT 21,.CPDVC##,35] ;YES, GET CSR ADDRESS FROM .CPDVC
PUSH P,T2 ;SAVE ARGUMENT
HLRZ T2,P1 ;ASSUME AUTCON IS RUNNING
PUSHJ P,AUTOWN ;DO WE OWN THE DATA BASE INTERLOCK?
HLRZ T2,KDBUNI(W) ;GET MASSBUS UNIT FROM KDB
MOVEI T3,CS.BAI ;BUS ADDRESS INHIBIT
TIOE T3,.DOCS2(T1) ;IS IT SET?
TRO T2,CS.BAI ;YES--THEN PRESERVE IT
WRIOB T2,.DOCS2(T1) ;SELECT UNIT
HLRZS (P) ;MOVE REGISTER OFFSET TO RH
ADD T1,(P) ;OFFSET FROM UNIBUS BASE ADDRESS
RDIO T2,(T1) ;READ REGISTER
POP P,(P) ;PHASE STACK
POP P,T3 ;RESTORE T3
JRST TPOPJ## ;POP OFF T1 AND RETURN
> ;END IFN FTKS10
SUBTTL MASSBUS REGISTER I/O -- SVMBR - SAVE REGISTER
;SAVE A DRIVE OR CONTROLLER REGISTER
;THIS CO-ROUTINE IS USED BY INTERRUPT LEVEL TO SAVE AND RESTORE THE
;CURRENT DRIVE/CONTROLLER REGISTER THAT MAY BE IN USE BY UUO LEVEL.
;CALL: MOVE W, KDB ADDRESS
; PUSHJ P,SVMBR
; <RETURN>
;
;ALL ACS ARE PRESERVED
IFN FTKL10,<
SVMBR:: PUSH P,W ;SAVE KDB ADDRESS
PUSH P,T2 ;SAVE T2
XCT KDBDTI(W) ;READ MBR THE CHANNEL WAS CONNECTED TO
EXCH T2,(P) ;SAVE MBR, GET T2 BACK
PUSHJ P,@-2(P) ;CALL THE CALLER
CAIA ;NON-SKIP RETURN
AOS -3(P) ;ADJUST RETURN PC
EXCH W,-1(P) ;SAVE W, GET KDB ADDRESS BACK
EXCH T2,(P) ;SAVE T2, GET OLD MBR BACK
AND T2,[DO.REG!DO.DRV] ;ISOLATE MASSBUS UNIT AND REGISTER
TLNN T2,(DO.REG) ;CAN'T WRITE REGISTER 0 SINCE THAT
TLO T2,(INSVL.(1,DO.REG)) ; MIGHT SIEZE SOME MASSBUS UNITS
XCT KDBDTO(W) ;SET THE CHANNEL BACK TO ORIGINAL MBR
POP P,T2 ;RESTORE T2
POP P,W ;RESTORE W
POP P,(P) ;PHASE STACK
POPJ P, ;RETURN
> ;END IFN FTKL10
SUBTTL MASSBUS REGISTER I/O -- WTMBR - WRITE REGISTER
;WRITE A DRIVE OR CONTROLLER REGISTER
;CALL: SKIPA P1, MASSBUS UNIT,,0 ;IF AUTOCONFIGURING
; MOVE W, KDB ADDRESS ;IF NORMAL TIMESHARING
; MOVE T2, REGISTER
; PUSHJ P,WTMBR
; <RETURN>
;
;ALL ACS ARE PRESERVED
IFN FTKL10,<
WTMBR:: PUSHJ P,SAVW## ;SAVE W
PUSH P,T1 ;SAVE T1
PUSH P,T2 ;SAVE T2
PUSH P,T3 ;SAVE T3
PUSHJ P,AUTOWN ;DO WE OWN THE DATA BASE INTERLOCK?
JRST WTMBR1 ;NO--DO NORMAL STUFF
XMOVEI W,.CPCNI##-KDBCNI ;FAKE KDB I/O INSTRUCTIONS
HLRZ T3,P1 ;MASSBUS UNIT NUMBER
SKIPA ;ENTER COMMON CODE
WTMBR1: HLRZ T3,KDBUNI(W) ;MASSBUS UNIT NUMBER
TLO T2,<(DO.LDR!DO.DRE)>(T3) ;SET UNIT, NO RAE, LOAD REGISTER
MOVE T3,KDBDVC(W) ;GET DEVICE CODE
CAIL T3,FSTICD/4 ;INTERNAL
CAILE T3,LSTICD/4 ; CHANNEL?
TLZ T2,<(DO.DRE)> ;NO
MOVE T3,T2 ;COPY ARGUMENTS
XCT KDBDTO(W) ;DATAO
XCT KDBCNI(W) ;CONI
TRNN T1,CI.RAE ;REGISTER ACCESS ERROR?
JRST WTMBR3 ;NO
PUSH P,T3 ;SAVE DATAO ARGUMENTS
MOVEI T3,^D10 ;RETRY OPERATION 10 TIMES
WTMBR2: MOVEI T1,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR RAE
XCT KDBCNO(W) ;CLEAR THE ERROR
MOVE T2,(P) ;GET ARGUMENTS BACK
XCT KDBDTO(W) ;RETRY THE OPERATION
XCT KDBCNI(W) ;CONI
TRNE T1,CI.RAE ;STILL HAVE AN ERROR
SOJG T3,WTMBR2 ;YES, LOOP BUT NOT TOO MANY TIMES
MOVEI T1,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR RAE
XCT KDBCNO(W) ;INSURE THAT RAE IS CLEARED
POP P,(P) ;PHASE STACK
WTMBR3: POP P,T3 ;RESTORE T3
POP P,T2 ;RESTORE T2
POP P,T1 ;RESTORE T1
POPJ P, ;RETURN
> ;END IFN FTKL10
IFN FTKS10,<
WTMBR:: PUSH P,T1 ;SAVE AN AC
PUSH P,T3 ;SAVE ANOTHER
PUSHJ P,AUTOWN ;DO WE OWN THE DATA BASE INTERLOCK?
SKIPA T1,KDBDVC(W) ;NO, GET CSR ADDRESS FROM KDB
LDB T1,[POINT 21,.CPDVC##,35] ;YES, GET CSR ADDRESS FROM .CPDVC
PUSH P,T2 ;SAVE ARGUMENT
HLRZ T2,P1 ;ASSUME AUTCON IS RUNNING
PUSHJ P,AUTOWN ;DO WE OWN THE DATA BASE INTERLOCK?
HLRZ T2,KDBUNI(W) ;GET MASSBUS UNIT FROM KDB
MOVEI T3,CS.BAI ;BUS ADDRESS INHIBIT
TIOE T3,.DOCS2(T1) ;IS IT SET?
TRO T2,CS.BAI ;YES--THEN PRESERVE IT
WRIOB T2,.DOCS2(T1) ;SELECT UNIT
HRRZ T2,(P) ;GET DATA TO WRITE
HLRZS (P) ;MOVE REGISTER OFFSET TO RH
ADD T1,(P) ;OFFSET FROM UNIBUS BASE ADDRESS
WRIO T2,(T1) ;WRITE REGISTER
POP P,(P) ;PHASE STACK
POP P,T3 ;RESTORE T3
JRST TPOPJ## ;POP OFF T1 AND RETURN
> ;END IFN FTKS10
;ROUTINE TO FIXUP THE COUNTS FOR DEVICES WHOSE COUNTS ARE GLOBAL
;AMONG DIFFERENT KONTROLLERS (SUCH AS MAGTAPES)
ADNFIX: MOVE T1,.CPDRV## ;DRIVER DISPATCH
MOVEI T2,DR.GCC ;BIT TO TEST
TDNN T2,DRVCNF(T1) ;THIS DRIVER USE GLOBAL COUNTERS?
POPJ P, ;NO
PUSHJ P,SAVE3## ;SAVE SOME ACS
DMOVE P1,@DRVMDT(T1) ;COPY THIS DRIVER'S ENTRY
MOVE P3,DRVCNF(T1) ;COPY INTERESTING BITS
AND P3,[DR.DVT!DR.GCC] ;KEEP ONLY THOSE OF INTEREST
MOVE T1,DRVLST ;POINT TO START OF DRIVER CHAIN
SYSPIF ;INTERLOCK
ADNFI1: MOVE T2,DRVCNF(T1) ;GET CONFIGURATION WORD
AND T2,[DR.DVT!DR.GCC] ;ISOLATE IMPORTANT STUFF
CAMN T2,P3 ;SAME?
DMOVEM P1,@DRVMDT(T1) ;YES--UPDATE
SKIPE T1,DRVLNK(T1) ;LINK TO NEXT
JRST ADNFI1 ;LOOP BACK
SYSPIN ;RELEASE INTERLOCK
POPJ P, ;RETURN
CHKDEV:
IFN FTKL10,<
XCT .CPCNI## ;READ DEVICE STATUS
TLNE T1,(CI.PPT) ;LIVE IPA DEVICE?
JRST CPOPJ1## ;YES
PUSH P,T1 ;SAVE TEMPORARILY
MOVEI T1,7 ;DUMMY PI CHANNEL
XCT .CPCNO## ;SET PI ASSIGNMENT
XCT .CPCNI## ;READ IT BACK
EXCH T1,(P) ;GET OLD CONI BACK, SAVE NEW
XCT .CPCNO## ;RESET DEVICE STATUS
POP P,T1 ;PHASE STACK
TRNE T1,7 ;IS DEVICE REALLY THERE?
AOS (P) ;YES
POPJ P, ;RETURN
>; END IFN FTKL10
IFN FTKS10,<
LDB T1,[POINT 21,.CPDVC##,35] ;GET UNIBUS ADDRESS
PUSHJ P,UBGOOD## ;DEVICE EXIST?
POPJ P, ;NO
PJRST CPOPJ1## ;YES
>; END IFN FTKS10
;CREATE A NAME
;CALL: MOVE T1, DRIVE NUMBER
; PUSHJ P,OCTNAM/DECNAM
; <RETURN> ;RH(T1) = SIXBIT NAME
DECNAM: SKIPA T2,[EXP 12] ;DECIMAL NAME
OCTNAM: MOVEI T2,10 ;OCTAL NAME
PUSH P,T3 ;SAVE T3
PUSH P,T4 ;SAVE T4
MOVEI T4,(T2) ;GET RADIX
SETZ T3, ;CLEAR OUT RESULT
CRENAM: IDIVI T1,(T4) ;DIVIDE BY RADIX
ADDI T2,'0' ;CONVERT TO SIXBIT
LSHC T2,-6 ;SHIFT IT OUT
JUMPN T1,CRENAM ;LOOP FOR ALL DIGITS
TRNE T3,770000 ;IF SPECIAL CASE FOR NODE NUMBERS,
LSH T3,6 ;DROP THE LEADING '1'
HLRZ T1,T3 ;COPY RESULTS
POP P,T4 ;RESTORE T4
POP P,T3 ;RESTORE T3
POPJ P, ;RETURN
;ROUTINE TO GET THE ICCW BLOCK
IFN FTKL10,<
GETIOW: HRRZ T1,.CPDVC## ;GET <DEVICE CODE>/4
CAIL T1,FSTICD/4 ;INTERNAL CHANNEL?
CAILE T1,LSTICD/4 ;...
JRST GETIO1 ;NO
SUBI T1,FSTICD/4 ;REDUCE TO RH20 NUMBER
LSH T1,2 ;POSITION
ADD T1,.CPEPT## ;INDEX INTO EPT
JRST CPOPJ1## ;RETURN
GETIO1: PUSHJ P,GCH4WD## ;GET LOW CORE BLOCK
POPJ P, ;NOT AVAILABLE
SKIPE .UONCE## ;USER MODE (TWICE)?
JRST CPOPJ1## ;THIS IS MEANINGLESS
MAP T2,(T1) ;GET PHYSICAL ADDRESS
TLZ T2,-1-MXSECN ;KEEP ONLY THE ADDRESS
CAIGE T2,PAGSIZ ;MUST RESIDE IN PAGE ZERO
JRST CPOPJ1## ;IT DOES
PJRST RTNIOW## ;IT DOESN'T, RETURN BLOCK AND RETURN
>; END IFN FTKL10
;SETUP MICROCODE LOADER BLOCK IN A KDB
SETULB: MOVE T1,.CPDRV## ;DRIVER DISPATCH
SKIPN T2,DRVULP(T1) ;PROTOTYPE UCODE LOADER BLOCK?
POPJ P, ;NO
MOVE T3,DRVULO(T1) ;GET STORAGE OFFSET
IFE FTXMON,<
HRLZS T2 ;PUT IN LH
ADDI T3,(W) ;DESTINATION
PUSH P,T3 ;SAVE FOR A MOMENT
HRR T2,T3 ;MAKE BLT POINTER
BLT T2,.ULLEN-1(T3) ;COPY INTO KDB
> ;END IFE FTXMON
IFN FTXMON,<
MOVEI T1,.ULLEN ;LENGTH OF BLOCK
ADD T3,W ;DESTINATION
PUSH P,T3 ;SAVE FOR A MOMENT
EXTEND T1,[XBLT] ;COPY INTO KDB
> ;END IFN FTXMON
IFN FTKL10,<
POP P,T2 ;GET ULB ADDRESS BACK AGAIN
HRLZ T3,.CPDVC## ;<DEVICE CODE>/4
LSH T3,2 ;POSITION DEVICE CODE
HLR T3,KDBUNI(W) ;GET MASSBUS UNIT NUMBER TOO
MOVEM T3,.ULDEV(T2) ;STUFF IN BLOCK
HLRZ T3,KDBUNI(W) ;GET MASSBUS UNIT NUMBER
HRRM T3,.ULDEV(T2) ;SAVE IT
POPJ P, ;RETURN
>; END IFN FTKL10
IFN FTKS10,<JRST T2POPJ##> ;RETURN
;ROUTINE TO UNCACHE PAGES
;CALL: MOVE T1, STARTING ADDRESS
; MOVE T2, LENGTH OF BLOCK
; PUSHJ P,UNCACH
; <RETURN> ;ADDRESS RANGE UNCACHED
UNCACH: ADD T2,T1 ;COMPUTE ENDING ADDRESS
LSH T1,W2PLSH ;STARTING PAGE NUMBER
LSH T2,W2PLSH ;ENDING PAGE NUMBER
MOVE T3,T1 ;COPY STARTING PAGE NUMBER
;SET UP TEMPORARY MAPPING
UNCAC1: MOVE T4,.CPMAP## ;SECTION ZERO MAP ADDRESS
PUSH P,.ECKSM/PAGSIZ(T4) ;SAVE TEMP SLOT INCASE ALREADY IN USE
MOVE T3,T1 ;COPY STARTING PAGE NUMBER
LSH T3,P2SLSH ;GET ITS SECTION NUMBER
MOVE T4,.CPEPT## ;EPT ADDRESS
ADDI T4,SECTAB(T3) ;INDEX TO SECTION MAP SLOT
MOVE T4,(T4) ;FETCH SECTION POINTER
ANDI T4,PM.PAG ;REDUCE TO ONLY A PAGE NUMBER
HRLI T4,(<PM.DCD>B2+PM.WRT+PM.PUB) ;DIRECT POINTER + WRITE + PUBLIC
PUSH P,T4 ;SAVE MAP ENTRY
MOVE T4,.CPMAP## ;SECTION ZERO MAP ADDRESS
POP P,.ECKSM/PAGSIZ(T4) ;STUFF POINTER INTO TEMP SLOT
CLRPT .ECKSM ;MAKE NEW MAPPING AVAILABLE TO HARDWARE
MOVE T3,T1 ;COPY STARTING PAGE NUMBER AGAIN
ANDI T3,PAGSIZ-1 ;KEEP ONLY THE INDEX WITHIN THE SECTION
XMOVEI T4,.ECKSM(T3) ;GET THE STARTING ADDRESS WITHIN MAP
;UNCACHE PAGES
UNCAC2: SKIPN T1,(T4) ;GET CONTENTS OF MAP SLOT
STOPCD .,STOP,DNM, ;++DATA NOT MAPPED
TLZ T1,(PM.CSH) ;CLEAR CACHE BIT
MOVEM T1,(T4) ;UPDATE
AOS T4 ;ADVANCE POINTER FOR NEXT TIME
ANDI T1,PM.PAG ;GET PHYSICAL PAGE NUMBER
SSX T1,MS.MEM ;SECTION NUMBER
EXCH T2,PAGTAB(T1) ;GET ENTRY, SAVE T2
TLZ T2,TNCSHB ;CAN NEVER CACHED (EVEN IF SPLIT)
EXCH T2,PAGTAB(T1) ;STORE NEW SETTING, RESTORE T2
CAIE T3,(T2) ;DID WE JUST DO LAST PAGE?
AOJA T3,UNCAC2 ;LOOP, WE HAVE MORE TO DO
MOVE T4,.CPMAP## ;SECTION ZERO MAP ADDRESS
POP P,.ECKSM/PAGSIZ(T4) ;RESTORE TEMP MAP SLOT FOR CALLER
CLRPGT ;MAKE HARDWARE NOTICE NEW MAPPING
POPJ P, ;RETURN
GETCOR: PUSH P,T1 ;SAVE WORDS TO GET
PUSH P,[EXP 0] ;PLACE HOLDER
PUSH P,T3 ;SAVE T3
PUSH P,T4 ;SAVE T4
MOVE T2,-3(P) ;GET REQUESTED NUMBER OF WORDS
PUSHJ P,GETWDS## ;ASK FOR THE CORE
JRST [POP P,T4
POP P,T3
JRST TTPOPJ##]
MOVEM T1,-2(P) ;SAVE ADDRESS OF ALLOCATED CORE
SETZM (T1) ;CLEAR FIRST WORD
IFE FTXMON,<
MOVSI T2,0(T1) ;START ADDRESS
HRRI T2,1(T1) ;MAKE A BLT POINTRE
ADD T1,-3(P) ;COMPUTE END OF BLT
BLT T2,-1(T1) ;CLEAR CORE
> ;END IFE FTXMON
IFN FTXMON,<
DMOVE T1,-3(P) ;WORD COUNT & START ADDRESS
SOS T1 ;WE ALREADY DID THE FIRST
MOVE T3,T2 ;DESTINATION
AOS T3 ;MAKE A BLT POINTER
EXTEND T1,[XBLT] ;CLEAR CORE
> ;END IFN FTXMON
POP P,T4 ;RESTORE T4
POP P,T3 ;RESTORE T3
POP P,T2 ;RESTORE ADDRESS
POP P,T1 ;RESTORE WORD COUNT
JRST CPOPJ1## ;RETURN
SUBTTL STATIC DATA OF INTEREST TO DRIVERS
$CSUB
;BYTE POINTERS INTO THE CHANNEL DATA BLOCK
CHYSCN::POINT CHSSCN,CHBSCN(P1),CHNSCN ;SOFTWARE CHANNEL NUMBER
CHYCPU::POINT CHSCPU,CHBCPU(P1),CHNCPU ;CPU NUMBER OWNING CHANNEL
$HIGH
$LOW
.LNKEN .LKDRV,DRVLST
DRVLST::XWD 0,0 ;DEVICE DRIVER DISPATCH LIST
PRVLST: BLOCK 1 ;PREVIOUS DISPATCH POINTER
KDBTAB::BLOCK TYPMAX+1 ;KDB CHAIN HEADERS
DDBTAB::BLOCK TYPMAX+1 ;PROTOTYPE DDB ADDRESSES
DDBSIZ: BLOCK TYPMAX+1 ;PROTOTYPE DDB LENGTHS
DDBCNT::BLOCK TYPMAX+1 ;NUMBER OF DDBS
NUMKON::BLOCK 1 ;TOTAL KONTROLLERS IN SYSTEM
$HIGH
AUTEND:!END