1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-01 01:19:17 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

2505 lines
82 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE AUTCON AUTOCONFIGURATION AND COMMON DEVICE I/O ROUTINES - V147
SUBTTL D. MASTROVITO/DPM 13-SEPTEMBER-88
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,147
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,<
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 - READ DRIVE TYPE REGISTER
;READ A DRIVE TYPE REGISTER
;CALL: SKIPA P1, MASSBUS UNIT,,0 ;IF AUTOCONFIGURING
; MOVE W, KDB ADDRESS ;IF NORMAL TIMESHARING
; PUSHJ P,RDDTR
; <RETURN>
;
;ON RETURN, T2 HAS THE DATAI RESULTS
;ALL ACS ARE PRESERVED
RDDTR::
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
POPJ P, ;AND RETURN
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