Google
 

Trailing-Edge - PDP-10 Archives - bb-jr93e-bb - 7,6/ap015/autcon.x15
There are 2 other files named autcon.x15 in the archive. Click here to see a list.
TITLE AUTCON DETERMINE HDWRE CNFIG WHEN A SYSTEM COMES UP  V066
	SUBTTL T.WACHS/TW/JMF		15 JULY 86

	SEARCH F,S,ICHPRM
	$RELOC
	$HIGH

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1981,1986>
;COPYRIGHT (C) 1981,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.

;
	XP VAUTCN,066
	ENTRY	AUTCON

;MASBUS DEVICE TYPES

TY.RU==020			;RP04
TY.RP5==021			;RP05
TY.RP6==022			;RP06
TY.RM3==24			;RM03
TY.RP7==42			;RP07
TY.RS4==002			;RS04 DRIVE TYPE
TY.T2L==010			;LOWEST TM02 TYPE
TY.T2H==017			;HIGHEST TM02 TYPE
TY.T3L==050			;LOWEST TM03 TYPE
TY.T3H==057			;HIGHEST TM03 TYPE
TY.T77==014			;TU77
TY.DXA==060			;DX20A TYPE (FOR TUXX TAPES)
TY.DXB==061			;DX20B TYPE (FOR RP20 DISKS)
TY.T78==101			;TM78


;HSC-50 DEVICE TYPES (PSEUDO CODES PASSED BY RAXKON/TAXKON)

IFN FTCIDSK,<
TY.R80==:400			;RA80
TY.R81==:401			;RA81
TY.R60==:402			;RA60
>; END IFN FTCIDSK
;HERE FROM FUNCTION 6 OF THE RECON UUO TO FORCE RECONFIGURATION OF DEVICES
; ON THIS CPU

CPUATC::PUSHJ	P,SAVE4##	;SAVE VOLATILE ACS
	MOVE	T1,[POINT 12,.CPNUM##,23]
	LDB	T1,T1		;START RN NUMBER
	MOVEM	T1,NUMRNA##	;REQUIRED SINCE VALUE IS WHATEVER WAS SETUP BY LAST CPU
	MOVSI	R,CP.22B##	;INDICATE AN RH10
	MOVEI	P2,270/4	;FIRST RH10 DEVICE CODE
	PUSHJ	P,UCNFIG	;SEE IF THERE IS ANYTHING THERE
	MOVEI	P2,274/4	;2ND RH10 DEVICE CODE
	PUSHJ	P,UCNFIG	;DO IT
	MOVEI	P2,360/4	;3RD RH10
	PUSHJ	P,UCNFIG	;DO IT
	MOVEI	P2,220/4	;FIRST DX10 DEVICE CODE
	MOVSI	R,CP.DX1##!CP.22B## ;INDICATE A DX10
	PUSHJ	P,UCNFIG	;SEE IF WE HAVE ANY
	MOVEI	P2,224/4	;SECOND DX10
	PUSHJ	P,UCNFIG	;SEE IF IT EXISTS
	MOVEI	P2,034/4	;3RD DX10
	PUSHJ	P,UCNFIG	;SEE IF WE HAVE ONE
	MOVEI	P2,FSTICD/4	;FIRST INTERNAL CHANNEL DEVICE CODE
CPUAT1:	MOVSI	R,CP.RH2##!CP.22B## ;ASSUME AN RH20
	PUSHJ	P,UCNFIG	;SEE WHAT WE HAVE
	MOVEI	P2,1(P2)	;STEP TO NEXT INTERNAL CHANNEL
	CAIG	P2,LSTICD/4	;AT THE TOP?
	JRST	CPUAT1		;NO, DO THIS ONE
IFN FTNET,<
	MOVSI	T1,<.TYMTA/.TYEST> ;GET DEVICE TYPE
	HRR	T1,MTANUM	;GET NUMBER OF MAGTAPES CONFIGURED
	PUSHJ	P,NETDEV##	;STUFF COUNT IN OUR NDB
>
IFN FTMP,<
	PJRST	T1CINI		;MAKE SURE DX10 KDB STAY UNCACHED AND RETURN
>
IFE FTMP,<
	POPJ	P,
>
;SUBROUTINE TO CONFIGURE CDB, KDB, AND UDBS FOR DEVICE WITH DEVICE CODE IN P2
; RETURN IMMEDIATELY IF NO SUCH DEVICE
; BUILD CDB, KDB, AND UDBS IF NONE EXIST
; BUILD UDBS FOR NEW DRIVES IF CDB AND KDB ALREADY EXIST
;CHANNEL
UCNFIG:	PUSHJ	P,CKCHN		;CHANNEL EXIST?
	 POPJ	P,		;NO, RETURN IMMEDIATELY
	  JRST	CNFIPA		;IPA CHANNEL, GO ELSEWHERE

;NOW, SEE IF A KDB AND THEREFORE A CDB ALREADY EXIST FOR THIS DEVICE CODE

;DISKS
	HLRZ	J,SYSKON##	;START OF KONTROLLER CHAIN
UCNFI1:	LDB	T1,[POINT 7,-4(J),9] ;GET DEVICE CODE FROM CONSO INSTRUCTION
IFN FTMP,<
	MOVE	T2,KONCAM##(J)	;CPU(S) THIS KONTROLLER IS ON
	TDNE	T2,.CPBIT##	;ON THIS CPU?
>
	CAIE	T1,(P2)		;YES, SAME DEVICE CODE?
	JRST	UCNFI2		;NO
	HRRZ	P1,KONCHN##(J)	;YES, ADDRESS OF CHANNEL DATA BLOCK
	PUSHJ	P,HAVUNI	;ANY UNITS ON THE KDB?
	  JRST	UNILUP		;NO, CONFIGURE AS IF CREATING THE KDB
	TLO	P1,400000	;INDICATE FROM CPUATC
	JRST	UNILUP		;GO CONFIGURE UNITS
UCNFI2:	HLRZ	J,KONNXT##(J)	;NEXT KDB
	JUMPN	J,UCNFI1	;JUMP IF NOT LAST
;TAPES
	SKIPN	J,CNFMTK##	;ANY TAPES?
	JRST	CNFIG		;NO, GO CONFIGURE CDB, KDB, AND UDBS
UCNFI3:	LDB	T1,[POINT 7,TKBCIS##(J),9] ;GET DEVICE CODE FROM CONI
IFN FTMP,<
	LDB	T2,[POINT 3,TKBSTS##(J),2] ;CPU THAT THIS KONTROLLER IS ON
	CAMN	T2,.CPCPN##	;SAME CPU AS WE ARE ON?
>
	CAIE	T1,(P2)		;YES, ALREADY HAVE A KDB?
	JRST	UCNFI4		;NOT THIS ONE
	HRRZ	P1,TKBCDB##(J)	;YES, GET THE ADDRESS OF THE CDB
	TLO	P1,400000	;INDICATE FROM CPUATC
	MOVE	W,J		;TAPES WANT IT IN W TOO
	JRST	UNILUP		;AND GO ADD UNITS IF ANY NEW ONES
UCNFI4:	HRRZ	J,TKBKDB##(J)	;NEXT KDB
	JUMPN	J,UCNFI3	;AND LOOK AT NEXT IF NOT LAST
	JRST	CNFIG		;NO CDB OR KDB, GO CONFIGURE ALL

;SUBROUTINE TO SEE IF A DSK KDB HAS ANY UNITS, CPOPJ IF NO, CPOPJ1 IF IT DOES

HAVUNI:	MOVE	T4,KONTBP##(J)	;GET AOBJN POINTER TO UNITS
	SKIPN	(T4)		;UNIT ALREADY KNOWN?
	AOBJN	T4,.-1		;NO, ANY UNIT WILL DO
	JUMPGE	T4,CPOPJ##	;JUMP IF NONE FOUND
	JRST	CPOPJ1##	;SKIP IF AT LEAST ONE WAS FOUND
AUTCON::SKIPN	.CPACD##	;BEEN HERE BEFORE?
	POPJ	P,
	PUSHJ	P,SAVE4##
	PUSH	P,.CPTOA##	;SAVE ONCE TYPEOUT ADDRESS
	MOVEI	P4,CTYWAT##	;SETUP NEW TYPEOUT ADDRESS
	MOVEM	P4,.CPTOA##	;FOR TYPEOUT DURING AUTCON
	SETZ	P4,		;INITIALIZE
	PUSH	P,R
	MOVE	T1,.CPCPN##	;ARE WE ON THE BOOT CPU?
	CAMN	T1,BOOTCP##
	JRST	AUTCN2		;YES, START IMMEDIATELY
	HRLZ	T1,.CPCPN##	;NO, SET TIMER SO WE'LL DO THIS IN STRICT
	ADD	T1,[3,,0]	; ORDER OF CPUS
AUTCN1:	SKIPL	T2,LASCNF##	;SOMEONE CONFIGURUNG NOW?
	CAME	T2,.CPCPN##	;NO, IS IT OUR TURN?
	JRST	AUTCN3		;NO, WAIT A WHILE
AUTCN2:	SETOM	LASCNF##	;TELL THE WORLD SOMEONE IS DOING THIS
	JRST	AUTCN4		;AND FIGURE OUT WHAT WE HAVE
AUTCN3:	SOJGE	T1,AUTCN1	;WAIT FOR A WHILE
				;TIMED OUT. START NOW ANYWAY
AUTCN4:	MOVE	T1,[POINT 12,.CPNUM##]
	ILDB	T2,T1		;GET START RP LETTER
	MOVEM	T2,NUMRPA##
	ILDB	T2,T1		;GET START RN NUMBER
	MOVEM	T2,NUMRNA##
	ILDB	T2,T1		;GET START TAPE NUMBER
	MOVEM	T2,NUMTAP##
	SETZM	NUMRNC##	;CLEAR PER-CPU COUNTERS
	SETZM	NUMRPC##
	MOVSI	R,CP.22B##	;INDICATE AN RH10
	MOVEI	P2,270/4	;FIRST RH10 DEVICE CODE
	PUSHJ	P,CNFIG		;SEE IF THERE IS ANYTHING THERE
	MOVEI	P2,274/4	;2ND RH10 DEVICE CODE
	PUSHJ	P,CNFIG		;DO IT
	MOVEI	P2,360/4	;3RD RH10
	PUSHJ	P,CNFIG		;DO IT
	MOVE	T1,CORLOC	;SAVE 1ST DX10 LOC
	MOVEM	T1,TAPDST##	; FOR UNCACHING DATA BASE
	MOVEI	P2,220/4	;FIRST DX10 DEVICE CODE
	MOVSI	R,CP.DX1##!CP.22B## ;INDICATE A DX10
	PUSHJ	P,CNFIG		;SEE IF WE HAVE ANY
	MOVEI	P2,224/4	;SECOND DX10
	PUSHJ	P,CNFIG		;SEE IF IT EXISTS
	MOVEI	P2,034/4	;3RD DX10
	PUSHJ	P,CNFIG		;SEE IF WE HAVE ONE
	MOVE	T1,CORLOC	;SAVE LAST DX10 LOC
	MOVEM	T1,TAPDEN##	; FOR UNCACHING
	MOVEI	P2,FSTICD/4	;FIRST INTERNAL CHANNEL DEVICE CODE
AUTCN5:	MOVSI	R,CP.RH2##!CP.22B## ;ASSUME AN RH20
	PUSHJ	P,CNFIG		;SEE WHAT WE HAVE
	MOVEI	P2,1(P2)	;STEP TO NEXT INTERNAL CHANNEL
	CAIG	P2,LSTICD/4	;AT THE TOP?
	JRST	AUTCN5		;NO, DO THIS ONE
IFN FTNET,<
	MOVSI	T1,<.TYMTA/.TYEST> ;GET DEVICE TYPE
	HRR	T1,MTANUM	;GET NUMBER OF MAGTAPES CONFIGURED
	PUSHJ	P,NETDEV##	;STUFF COUNT IN OUR NDB
>
	SETZM	.CPACD##	;INDICATE WE'VE BEEN HERE BEFORE
	POP	P,R
	SKIPN	T1,.CPCPN##	;CPU 0?
	AOJA	T1,AUTCN6	;YES, TELL CPU1 TO GO NEXT
	CAMN	T1,BOOTCP##	;NO, BOOT CP?
	TDZA	T1,T1		;YES, TELL CPU0 TO GO NEXT
	ADDI	T1,1		;NO, TELL NEXT CPU IN ORDER
AUTCN6:	MOVEM	T1,LASCNF##	;TELL THE WORLD WHO SHOULD GO NEXT
	POP	P,.CPTOA##	;RESTORE ONCE TYPEOUT ADDRESS
	POPJ	P,
;HERE WHEN A NEW DISK OR TAPE DRIVE COMES ON LINE
;CALL WITH T1=CONTENTS OF DRIVE TYPE REGISTER, T2=SLAVE NO, T3=TUBCNF BITS
NEWTAP::PUSHJ	P,SAVE4##
	HRRO	P1,TKBCDB##(W)	;SET P1=-1,,CHN
	MOVE	J,W
	MOVE	P3,T2		;UNIT (SLAVE)
	MOVS	T4,TKBNAM##(W)
	SUBI	T4,'MT0'-1
	MOVEM	T4,NUMTAP	;SET TO MAKE RIGHT DDB NAME
	JRST	NEWUNI
NEWDSK::CAIN	T1,TY.DXB	;DOESN'T WORK
	POPJ	P,
	PUSHJ	P,SAVE4##
	HRRO	P1,KONCHN##(J)	;SET P1=-1,,CHN
	PUSHJ	P,HAVUNI	;KDB WITH NO UNITS?
	  SKIPA			;YES
	JRST	NEWDS1		;NO
	LDB	T4,KOYKTP##	;GET KONTROLLER TYPE
	CAIN	T4,TYPRN##	;RP20?
	JRST	 [LDB T4,[POINT 12,.CPNUM##,23] ;INITIALIZE KON NUMBER
		 MOVEM T4,NUMRNA;WHERE TO START
		 AOS NUMRNA##	;YES, COUNT A CONTROLLER
		 HRRZS P1	;CONFIGURE AS IF NO KDB
		 JRST NEWDS1]	;CONTINUE
IFN FTCIDSK,<
	CAIN	T4,TYPRA##	;CI DISK?
	TLZ	P1,400000	;CLEAR SIGN BIT SO FIRST UNICHN LINK GETS SET UP
>; END IFN FTCIDSK
NEWDS1:	MOVE	P2,T2		;UNIT IF RP04
	HLRZ	P3,T2		;UNIT GOES HERE IF RP20
	HRRZ	T4,KONMUN##(J)	;GET MAXIMUM UNIT NUMBER
	CAMLE	P3,T4		;UNIT NUMBER WITHIN RANGE?
	POPJ	P,		;NO, QUIT WHILE WE'RE AHEAD
NEWUNI:	ANDI	T1,777		;ISOLATE DRIVE TYPE
	JRST	NEWLUP		;GO MATCH DRIVE TYPE
;ROUTINE TO SEE IF A "CHANNEL" EXISTS.  REALLY CHECKS IF THE DEVICE
;WITH THE CODE PASSED IN P2 CAN ACCEPT A PI ASSIGNMENT.
;CALL:
;	P2/ DEVICE CODE/4
;	PUSHJ	P,CKCHN
;RETURN:
;	CPOPJ IF CHANNEL DOESN'T EXIST
;	CPOPJ1 IF AN IPA TYPE CHANNEL
;	CPOPJ2 IF CHANNEL EXISTS (BUT NOT IPA TYPE CHANNEL)

CKCHN:	DPB	P2,[POINT 7,AUTCNO##,9]
	DPB	P2,[POINT 7,AUTCNI##,9]
	DPB	P2,[POINT 7,AUTDTO##,9]
	DPB	P2,[POINT 7,AUTDTI##,9]
	CAIL	P2,FSTICD/4	;INTERNAL CHANNEL?
	CAILE	P2,LSTICD/4	;...
	JRST	CKCHN1		;NO
	XCT	AUTCNI##	;DO THE CONI
	.CREF	CI.PPT		;BIT WE'RE TESTING
	JUMPL	T1,CPOPJ1##	;IF SIGN BIT SET THIS IS AN IPA TYPE CHANNEL
CKCHN1:	MOVEI	T1,7
	CONO	PI,PI.OFF	;DON'T ALLOW INTERRUPTS
	XCT	AUTCNO##	;TRY TO GIVE IT A PI
	XCT	AUTCNI##
	MOVE	T2,T1
	MOVEI	T1,0		;SET PIA BACK TO 0
	XCT	AUTCNO##
	CONO	PI,PI.ON
	TRNE	T2,7		;IS IT THERE?
	JRST	CPOPJ2##	;YES
	POPJ	P,		;NO
;HERE TO CONFIGURE A WHOLE CHANNEL
CNFIG:	PUSHJ	P,CKCHN		;ANYTHING THERE AT ALL?
	 POPJ	P,		;NO, TRY NEXT
	  JRST	CNFIPA		;IPA CHANNEL, GO ELSEWHERE
	SETZB	P1,J		;P1=CDB ADDR, J=KDB ADR
UNILUP:	MOVE	T4,P4		;SAVE CURRENT UNIT TYPE IF NOT 1ST UNIT
	SETOB	P3,P4		;SUBUNIT 0, NO UNIT SEEN ON THIS CONTROLLER
	TLNE	R,CP.DX1##	;DX10?
	JRST	FNDDX1		;YES. WE NEED A KDB TO SEE IF UNITS EXIST
	PUSHJ	P,REDDTR	;READ DRIVE TYPE REGISTER
	ANDI	T1,777		;GET IMPORTANT BITS
	JUMPE	T1,NEXTUN	;FORGET IT IF NO REAL ANSWER
NEWLUP:	MOVEI	P4,TABLEN	;LENGTH OF TABLE (=TM02 INDEX)
	CAIL	T1,TY.T3L	;IS IT A TM03
	CAILE	T1,TY.T3H
	CAIA
	JRST	FNDCHN		;YES, SET THINGS UP FOR IT
	CAIL	T1,TY.T2L	;NO, IS IT A TM02?
	CAILE	T1,TY.T2H
	SOSA	P4
	JRST	FNDCHN		;YES, SET UP
SCAN:	MOVE	T2,TYPTAB(P4)	;TRY TO MATCH TYPE WITH TABLE
	CAIN	T1,(T2)		;MATCH?
	JRST	FNDCHN		;YES, WE HAVE A UNIT
	SOJGE	P4,SCAN		;NO, TRY NEXT
	MOVE	P4,T4		;PRESERVE LAST UNIT-TYPE
	JRST	NEXTUN		;NO MATCH, TRY NEXT UNIT


FNDDX1:	MOVEI	P4,DX1IDX
FNDCHN:	JUMPN	P1,HAVCHN	;BEEN HERE FOR THIS CHAN BEFORE?
	PUSHJ	P,BLDCHN	;NO, BUILD A CHANNEL DATA BLOCK
	  POPJ	P,		;NO MEMORY AVAILABLE, CAN'T DO ANYTHING
HAVCHN:	JUMPE	J,KDB1		;BEEN HERE FOR THIS KDB BEFORE?
	SKIPGE	KDBTAB(P4)	;YES, MULTI-UNIT CONTROLLER?
	CAIGE	P4,TAPIDX	;YES, A TAPE?
	JRST	HAVKDB		;NO, J IS RIGHT
	HLRZ	T1,P2		;CURRENT UNIT NUMBER
	MOVE	T3,J		;CURRENT KDB
KDB0:	HLRZ	T2,TKBUNI##(J)	;UNIT NUMBER FROM THE KDB
	CAMN	T1,T2		;SAME AS CURRENT UNIT NUMBER?
	JRST	 [MOVE W,J	;TAPES WANT IT IN W TOO
		  TLO P1,400000	;YES, INDICATE IN CPUATC
		  JRST TAPUDB]	;AND CONFIGURE SLAVES ON CURRENT KDB
	HLRZ	J,TKBCDB##(J)	;NEXT KDB IN THE RING
	CAME	J,T3		;BEEN ALL THE WAY AROUND THE RING?
	JRST	KDB0		;NO, SEE IF THIS IS THE CORRECT UNIT
;	SETZ	J,		;YES, KDB DOESN'T EXIST SO MAKE ONE
	HRRZS	P1		;PRETEND NOT DOING CPUATC
KDB1:	PUSHJ	P,BLDKDB	;NO, BUILD A KDB
	  POPJ	P,		;NO MEMORY AVAILABLE, FORGET IT
;	JRST	HAVKDB		;AND CONTINUE
HAVKDB:	CAIL	P4,TAPIDX	;TAPE?
	JRST	TAPUDB		;YES
	SKIPGE	KDBTAB(P4)	;MULTI-UNIT (RP20)?
	JUMPL	P3,UDB5		;YES, GO FIND FIRST UNIT ON KDB
	PUSHJ	P,GETUNN	;GET UNIT NUMBER
	ADD	T4,KONTBP##(J)	;OFFSET INTO KONTAB
	SKIPE	(T4)		;UNIT ALREADY EXIST? - CPUATC
	JRST	NEXTUN		;YES, LOOK ONWARD
	LDB	T2,[POINT 9,TYPTAB(P4),17] ;LENGTH OF UDB
	PUSHJ	P,UDBCTG	;ENSURE NECESSARY PARTS OF UDB ARE CONTIGUOUS
	PUSHJ	P,GETCOR	;GET THE CORE WE NEED
	  POPJ	P,		;NONE AVAILABLE. FORGET IT
	MOVE	U,T1		;SAVE UDB ADDRESS
	PUSHJ	P,MAKNAM	;MAKE UP A NAME FOR THE UNIT
	MOVEM	T1,(U)		;SAVE IT IN UDB
	ADD	T4,KONTBP##(J)	;POINT AT RIGHT KONTAB SLOT
	MOVEM	U,(T4)		;POINT KDB AT THIS UDB
	HRRZ	T1,J		;GO SEARCH FOR 1ST AND LAST UDBS IN SYSTEM
	PUSHJ	P,FSTLST	; ON THIS KDB
	MOVEM	J,UNIKON##(U)	;SET UP RH(UNIKON)
	SKIPGE	P1		;IF SYSTEM IS RUNNING
	HLL	T4,UNIKON##(T4)	; PRESERVE CURRENT LINKS
	HRLM	U,UNIKON##(T4)	;POINT PREVIOUS LAST AT THIS UDB
	JUMPGE	P1,UDB4		;IF A SINGLE UNIT
	SKIPE	T1		;IF ANY UNITS ON THE KDB
	HRRM	T4,LASUNI##	;LINK UNISYS AT END OF CURRENT KDB'S UNITS
UDB4:	HLLM	T4,UNIKON##(U)	;POINT THIS UDB AT 1ST
	HRRO	T1,P1		;SEARCH FOR 1ST AND LAST UDBS IN SYSTEM
	PUSHJ	P,FSTLST	; ON THIS CDB
	MOVEM	P1,UNICHN##(U)	;SET UP RH(UNICHN)
	SKIPGE	P1
	HLL	T4,UNICHN##(T4)
	HRLM	U,UNICHN##(T4)	;POINT PREVIOUS LAST AT THIS UDB
	HLLM	T4,UNICHN##(U)	;POINT THIS UDB AT LAST
	SKIPE	T1,LASUNI##	;GET FORMER LAST UNIT
	SKIPE	UNI2ND##(T1)	;(2ND PORT ISNT ON CHAIN)
	MOVEI	T1,SYSUNI##-UNISYS##
	MOVE	T2,UNISYS##(T1)	;GET ITS LINK (IN CASE SINGLE UNIT)
	HRLM	U,UNISYS##(T1)	;POINT AT US
	HLLM	T2,UNISYS##(U)	;LINK US TO FORMER NEXT
	MOVEM	U,LASUNI##	;SAVE LAST UDB CREATED
	LDB	T2,[POINT 6,(T4),17] ;GET CONTROLLER LETTER OF PREVIOUS
	SKIPGE	P1
	DPB	T2,[POINT 6,(U),17] ;AND SAVE AS THIS LETTER
	MOVSI	T1,777		;SET UP RANDOM UDB LOCS
	MOVEM	T1,UNICCT##(U)
	MOVE	T1,[LBNHOM##,,LB2HOM##]
	MOVEM	T1,UNIHOM##(U)
	SETOM	UNICYL##(U)
	SETZM	UNIDS2##(U)	;START AFRESH
	MOVE	T1,NUMRNC##	;COMPUTE ALL THE GARBAGE FOR UNIDES
	ADD	T1,NUMRPC##	; (DOES ANYONE REALLY CARE?)
IFN FTCIDSK,<
	ADD	T1,NUMRAC##	;
>; END IFN FTCIDSK
	SUBI	T1,1
	ANDI	T1,7
	LSH	T1,^D15
	CAIN	P4,RNAIDX	;RP20?
	JRST	[TRO  T1,TYPRN##*1000
		 MOVE T2,NUMRNC##
		 JRST .+1]
	CAIG	P4,RPXIDX	;RP04/05/06/07?
	JRST	[TRO  T1,TYPRP##*1000
		 MOVE T2,NUMRPC##
		 JRST .+1]
IFN FTCIDSK,<
	CAIL	P4,RAMIDX	;CI DISK?
	CAILE	P4,RAXIDX	;...
	SKIPA
	JRST	[TRO  T1,TYPRA##*1000
		 MOVE T2,NUMRAC##
		 JRST .+1]
>; END IFN FTCIDSK
	SUBI	T2,1
	DPB	T2,[POINT 3,T1,29]
	DPB	T2,UNYKNM##	;STORE KONTROLLER NUMBER
	LDB	T2,[POINT 3,TYPTAB(P4),8] ;GET UNIT TYPE CODE
	DPB	T2,[POINT 3,T1,32] ;STORE
	SKIPGE	KDBTAB(P4)	;MULTI-UNIT (RP20)?
	SKIPA	T2,P3		;YES, IGNORE UNIT-SLOT, JUST USE SLAVE NUMBER
	HLRZ	T2,P2		;COMPUTE UNIT NUMER
	DPB	T2,UNYKOF##	;SAVE KONTAB OFFSET
IFN FTCIDSK,<
	CAIL	P4,RAMIDX	;CI DISK?
	CAILE	P4,RAXIDX	;...
	SKIPA			;NO
	HRRZ	T2,P2		;YES, GET LAP PLUG NUMBER
>; END IFN FTCIDSK
	DPB	T2,UNYPUN##	;STORE PHYSICAL UNIT NUMBER
	ANDI	T2,7
	ADD	T1,T2
	TLO	T1,3000		;MARK DOWN (IN CASE NOT BOOT, SYSTEM ALREADY UP)
	MOVEM	T1,UNIDES##(U)	;SAVE ALL THE STUFF IN UNIDES
	MOVSI	T1,U2PNRM##	;GET NON-REMOVABLE MEDIA BIT
	CAIE	P4,RNAIDX	;NON-REMOVABLE DISK?
	CAIN	P4,RP7IDX
	IORM	T1,UNIDS2##(U)	;YES, LIGHT A BIT
IFN FTCIDSK,<
	CAIE	P4,R80IDX	;RA80?
	CAIN	P4,R81IDX	;RA81?
	IORM	T1,UNIDS2##(U)	;YES, LIGHT A BIT
>; END IFN FTCIDSK
	MOVE	T1,.CPBIT##	;GET BIT FOR THIS CPU
IFN FTCIDSK,<
	CAIL	P4,RAMIDX	;SOME FLAVOR OF CI DISK?
	CAILE	P4,RAXIDX	;DON'T SET ACCESSIBILITY MASK UNTIL DISK ONLINE
>; END IFN FTCIDSK
	IORM	T1,UNICAM##(U)	;SET ACCESSIBILITY MASK IN UDB
	SETOM	UNIAJB##(U)
	AOS	T1,SYSGEN##	;GET A UNIQUE UNIT GENERATION NUMBER
	HRRM	T1,UNIGEN##(U)
	TLNE	P1,377777	;A SINGLE UNIT?
	POPJ	P,		;YES, THEN DONE
	SKIPL	KDBTAB(P4)	;MULTIPLE "SLAVES" ON THIS UNIT (IE RP20)?
	JRST	NEXTUN		;NO, WE'RE DONE

;THIS WORKS ONLY FOR RP20S.
UDB5:	MOVE	T1,AUTRNX##	;LAST UNIT WE HAD
	HLRZ	T2,P2		;RH20 UNIT NUMBER
	PUSHJ	P,@KONCFG##(J)	;ASK DRIVER WHAT THE NEXT UNIT IS
	  JRST	UDB6		;NO MORE
	SKIPGE	P3		;IF FIRST TIME,
	AOS	NUMRNA##	;COUNT A KONTROLLER
	HRRZ	P3,T1		;UNIT
	MOVEM	T1,AUTRNX##	;SAVE FOR NEXT CALL
	JRST	HAVKDB		;GO SET UP UDB
UDB6:	SETOM	AUTRNX##	;DONE RESET FOR NEXT TIME
	POPJ	P,		;ONLY 1 RP20 PER RH. WE'RE DONE
TAPUDB:	TLNE	P1,377777	;CNFIG OR CPUATC?
	JRST	TUDB4		;NO, SINGLE UNIT
	JUMPL	P1,TUDB9	;GO IF KONTROLLER ALREADY HAS A NAME
TUDB1:	AOS	T1,NUMTAP##	;YES, COUNT A TAPE CONTROLLER
	SUBI	T1,1
	AOS	NUMKON##	;COUNT A CONTROLLER
	ADDI	T1,'MT0'
	MOVSS	T1		;MAKE NAME IN LH
	SKIPN	T2,CNFMTK##	;STARTING AT FIRST TAPE KDB IN SYSTEM,
	JRST	TUDB3		; LOOK FOR A MATCH WITH THE NAME WE'RE MAKING
TUDB2:	CAMN	T1,TKBNAM##(T2)	;MATCH?
	JRST	TUDB1		;YES, BUMP NAME AND TRY AGAIN
	SKIPE	T2,TKBKDB##(T2)	;NO, TRY NEXT KDB
	JRST	TUDB2
TUDB3:	MOVEM	T1,TKBNAM##(J)
	JRST	TUDB9		;FIND 1ST SLAVE IF 1ST TIME
TUDB4:	PUSHJ	P,GETUNN	;GET UNIT NUMBER
	ADD	T4,TKBIUN##(J)	;OFFSET INTO UNIT TABLE
	SKIPE	(T4)		;UNIT ALREADY EXIST? - CPUATC
	JRST	TUDB9		;YES, JUST LOOK AT NEXT UNIT
	LDB	T2,[POINT 9,TYPTAB(P4),17] ;GET LENGTH OF UDB
	PUSHJ	P,UDBCTG	;ENSURE NECESSARY PARTS OF KDB ARE CONTIGUOUS
	PUSHJ	P,GETCOR	;ALLOCATE THAT MUCH CORE
	  POPJ	P,		;NONE AVAILABLE. FORGET IT
	MOVE	U,T1		;UDB ADDR INTO U
	HRL	T1,TAPTAB-TAPIDX(P4) ;COPY THE RIGHT FLAVOR OF UDB
	BLT	T1,-1(T2)
	TRNE	T3,-1		;DID DRIVER DETERMINE POSSIBLE CNFIG CHANGE?
	HRRM	T3,TUBCNF##(U)	;YES, STORE NEW INFORMATION
	MOVEI	T3,TUCIRD##	;ALL UNITS INTERRUPT
	IORM	T3,TUBCNF##(U)	;UORV REW DONE
	PUSHJ	P,FNYNAM	;MAKE A NAME FOR THE UDB
	LDB	T2,[POINT 6,TKBNAM##(J),17] ;GET KONTROLLER NUMBER
	SKIPGE	P1		;IF SINGLE UNIT OR CPUATC,
	DPB	T2,[POINT 6,T1,23] ;STORE IT IN UNIT NAME
	MOVEM	T1,(U)
	MOVEM	T4,TUBADR##(U)	;SAVE UNIT NUMBER
	ADD	T4,TKBIUN##(J)	;POINT TO RIGHT KDB SLOT
	MOVEM	U,(T4)		;SAVE UDB IN KDB
	HRRZM	J,TUBKDB##(U)	;POINT UDB AT KDB
	MOVEI	T2,MT0DDS##	;GET CORE FOR A DDB
	PUSHJ	P,GETCOR
	  POPJ	P,		;NONE AVAILABLE. FORGET IT
	MOVE	F,T1		;SAVE DDB ADDRESS
	PUSHJ	P,MAKNAM	;MAKE UP A NAME
	SKIPE	CORLOC		;SYSTEM UP AND RUNNING?
	JRST	TUDB5		;NO, ONCE WILL DO ALL THE RIGHT STUFF
	HRRI	T1,'000'(T4)	;MAKE "MTA00n" AS NAME
IFN FTNET,<
	LDB	T2,[POINT 3,JBTLOC##,35]
	DPB	T2,[POINT 3,T1,29] ;SET LAST DIGIT OF STATION
	LDB	T2,[POINT 3,JBTLOC##,32]
	DPB	T2,[POINT 3,T1,23] ;SET 1ST DIGIT OF STATION
>
	HLRZ	T2,MT0DDB##+DEVSER ;WERE ANY MAGTAPES FOUND ON START UP?
	JUMPN	T2,TUDB5	;YES, LINK THIS TAPE TO THE END OF THOSE
	HRLM	F,MT0DDB##+DEVSER ;NO. POINT AT THIS DDB SO CNFMTA GETTAB WILL WORK
	MOVEI	T2,SWPDDB##	;LINK MAGTAPES INTO DEVICE CHAIN
	MOVEM	T2,TAPLNK##	; AT END OF SWAPPER
TUDB5:	LDB	T2,[POINT 6,TKBNAM##(J),17] ;KONTROLLER NUMBER
	ADDI	T2,"A"-"0"	;CHANGE INTO A LETTER
	SKIPGE	P1		;IF SINGLE UNIT OR CPUATC,
	DPB	T2,[POINT 6,T1,17] ;STORE LETTER IN NAME
	MOVEM	T1,(F)		;SAVE NAME IN DDB
	MOVE	T1,[<^D5*HUNGST>,,MTSIZ##]
	MOVEM	T1,DEVCHR(F)	;SET UP DEVCHR
	MOVEI	T1,TPMDSP##	;SET UP RH OF DEVSER
	MOVEM	T1,DEVSER(F)
	MOVE	T1,TAPLNK##
TUDB6:	HLRZ	T2,DEVSER(T1)	;FIND THE END OF THE MAGTAPES
	JUMPE	T2,TUDB7	;HAVE END
	HRRZ	T3,DEVSER(T2)	;IF SYSTEM IS ALREADY RUNNING (THIS ISNT BOOT CPU)
	CAIE	T3,TPMDSP##	;IS THE NEXT DDB NOT A TAPE?
	JRST	TUDB7		;NOT A TAPE - INSERT NEW DDB HERE
	MOVE	T1,T2
	JRST	TUDB6
TUDB7:	HRLM	F,DEVSER(T1)	;LINK PREVIOUS DDB TO THIS ONE
	HRLM	T2,DEVSER(F)	;PRESERVE THE LINK OF WHAT WE'RE INSERTING
	HLRZ	T4,W		;IS THIS THE 1ST UNIT ON THE KDB?
	SUBI	T4,(U)
	JUMPN	T4,TUDB8
	HLLZ	T1,DEVNAM(F)	;GET THIS DDB NAME
	MOVSI	T2,-GTLEN##	;AOBJN POINTER
	CAME	T1,GENTAB##(T2)	;MATCH?
	AOBJN	T2,.-1		;NO
	SKIPGE	T2		;POINTER RUN OUT?
	HRRM	F,GENTAB##(T2)	;SAVE ADDR FOR GENERIC DEVICE SEARCH
	MOVEM	F,TKBERB##(W)	;POINT TKBERB AT 1ST DDB ON CONTROL
TUDB8:	MOVE	T1,[1023,,154403+<1_BYTMOD>]
	MOVEM	T1,DEVMOD(F)	;SET UP DEVMOD
	MOVE	T1,[.TYMTA!DEPLEN,,DEPEVM]
IFN FTNET,<
	TDO	T1,JBTLOC##	;(NON-0 IF SYSTEM ALREADY UP)
>
	MOVEM	T1,DEVSTA(F)	;SAVE DEVSTA
	LDB	T1,[POINT 3,TUBADR##(U),35] ;ONLY LOW-ORDER PART OF NAME SO DDBFIX
	DPB	T1,PUNIT##	; WILL DO THE RIGHT THING
IFN FTMP,<
	HRLZ	T1,.CPCPN##
	LSH	T1,^D15		;SET UP DEVCPU
	TLO	T1,2000
	HRR	T1,.CPTIL##	;TAPE INTERLOCK WORD FOR THIS CPU
	MOVEM	T1,DEVCPU(F)
>
	HRLM	U,TDVKDB##(F)	;POINT DDB AT UDB
	HRRM	W,TDVKDB##(F)	;POINT DDB AT KDB
	HRLM	U,TDVUDB##(F)	;COUPLE DDB,TUB
	HRRZM	F,TUBDDB##(U)
	PUSHJ	P,TAPACT	;ACCOUNT FOR THE DRIVE, TELL QUASAR
	TLNE	P1,377777	;CNFIG OR CPUATC?
	POPJ	P,		;NO, SINGLE UNIT SO ALL DONE
TUDB9:	MOVE	T1,TKBDSP##(W)	;ASK THE DRIVER WHAT THE NEXT UNIT IS
	MOVE	T2,CORLOC	;FOR TX1KON
	PUSHJ	P,@TPKCFG##(T1)
	JUMPL	P3,NEXTUN	;GO IF NO MORE SLAVES ON UNIT
	MOVNI	T1,1(P3)	;ANOTHER UNIT
	HRLM	T1,TKBIUN##(W)	;SET UP TKBIUN, TKBCUN
	MOVE	T1,TKBIUN##(W)
	MOVEM	T1,TKBCUN##(W)
	JRST	TUDB4		;GO SET UP UDB FOR THIS SLAVE
TUDB10:	MOVSI	T1,1(P3)	;SET T1=-DRIVE NUMBER,,00
	MOVNS	T1
	CAML	T1,TKBIUN##(W)	;LARGER THAN CURRENT?
	POPJ	P,
	HLLM	T1,TKBIUN##(W)	;YES. RESET LH ACCORDINGLY
	HLLM	T1,TKBCUN##(W)
	POPJ	P,		;RETURN


; HERE TO ACCOUNT FOR THE DRIVE, TELL QUASAR, ETC.
TAPACT:
IFN FTNET,<AOS MTANUM>		;COUNT MAGTAPES FOR NETSER
IFE FTMDA,<POPJ P,>		;RETURN IF NO MDA
IFN FTMDA,<
	SKIPE	CORLOC		;ARE WE IN ONCE ONLY CODE?
	POPJ	P,		;YES, SIMPLY RETURN.
	PUSHJ	P,SAVT##	;IPCSER SMASHES T1-T4
	PJRST	MTAMPA##	;TELL MDA ABOUT THE NEW TAPE DRIVE
> ;END IFN FTMDA
NEXTUN:	MOVEI	T1,CO.RAE+CO.MBE;CLEAR POSSIBLE RAE
	XCT	AUTCNO##
	HLRZ	T2,P2
	ADDI	T2,1		;STEP TO NEXT UNIT
	TLNN	R,CP.DX1##
	CAILE	T2,7		;IS THERE ONE?
	POPJ	P,		;NO, WE'RE DONE WITH THIS RH
	HRLM	T2,P2		;YES, PUSH ON
	JUMPL	P4,UNILUP	;GO IF NO UNIT SEEN ON THIS KON YET (CPUATC)
	SKIPL	KDBTAB(P4)	;MULTI UNIT
	JRST	UNILUP		;GO SEE IF ANOTHER UNIT EXISTS
	CAIGE	P4,TAPIDX	;HAVCHN WILL FIND THE NEXT KDB
	SETZ	J,		;CNFIG, SET TO BUILD A NEW KDB FOR NEW UNIT
	JRST	UNILUP

;ROUTINE TO MAKE SURE DX10 KDBS ARE NEVER CACHED
IFN FTMP,<
T1CINI::SKIPN	W,CNFMTK##	;ANY MAGTAPES?
	POPJ	P,		;NO, NOTHING TO DO
T1CIN1:	PUSHJ	P,TX1TCF##	;IF A DX10, MAKE SURE KDBS ARE NEVER CACHED
	HRRZ	W,TKBKDB##(W)	;NEXT KDB
	JUMPN	W,T1CIN1	;IF NEXT, TRY IT
	POPJ	P,		;AND RETURN
>
;HERE ON AN IPA TYPE INTERNAL CHANNEL (CI20 OR NIA20)

CNFIPA:	MOVEI	T1,-FSTICD/4(P2) ;GET INTERNAL CHANNEL NUMBER
	SKIPE	.CPCHN##(T1)	;CHANNEL AREADY CONFIGURED?
	POPJ	P,		;YES, RETURN
;ACCORDING TO DOCUMENTATION THE CI20 AND NIA20 HAVE DIFFERENT TYPE
;FIELDS RETURN IN THE CONI.  UNFORTUNATELY, IN THE REAL WORLD THEY
;REALLY DON'T.  HERE WE ASSUME NIA20 IS ALWAYS IN CHANNEL 5, AND
;CI20 IS ALWAYS IN CHANNEL 7.
	SETO	P4,		;START WITH MISMATCH
IFN FTENET,<
	CAIN	T1,KNIICH	;NIA20 CHANNEL?
	MOVEI	P4,KNIIDX	;YES
>; END IFN FTENET
IFN FTSCA,<
	CAIN	T1,KLPICH	;CI20 CHANNEL?
	MOVEI	P4,KLPIDX	;YES
>; END IFN FTSCA
	MOVEI	T1,CO.CPT	;CONO TO CLEAR THE PORT
	XCT	AUTCNO##	;DO IT
	JUMPL	P4,CPOPJ##	;RETURN IF UNRECOGNIZED DEVICE
	SKIPN	IPAPCB(P4)	;DRIVER FOR THIS DEVICE LOADED?
	POPJ	P,		;NO, SORRY
IFN FTENET,<
	CAIN	P4,KNIIDX	;KLNI?
	MOVSI	R,CP.KNI##!CP.22B## ;YES
>; END IFN FTENET
IFN FTSCA,<
	CAIN	P4,KLPIDX	;KLIPA?
	MOVSI	R,CP.KLP##!CP.22B##!CP.MX## ;YES, MORE BITS TO SET
>; END IFN FTSCA
	PUSHJ	P,BLDCHN	;BUILD A CHANNEL DATA BLOCK
	  POPJ	P,		;SORRY, NO CORE
	LDB	T1,[POINT 9,IPAPCB(P4),17] ;GET OFFSET TO CONTIGUOUS AREA
	ADDI	T1,CSOINL	;OFFSET THAT BY LENGTH OF CONSO SKIP CHAIN
	LDB	T2,[POINT 9,IPAPCB(P4),26] ;GET LENGTH OF CONTIGUOUS AREA
	HRL	T1,T2		;LENGTH,,OFFSET  OF CONTIGUOUS AREA
	PUSHJ	P,CHKCTG	;ENSURE ALLOCATION WILL BE PHYSICALLY CONTIGUOUS
	LDB	T2,[POINT 9,IPAPCB(P4),8] ;GET LENGTH OF PORT CONTROL BLOCK
	ADDI	T2,CSOINL	;INCLUDE CONSO SKIP CHAIN IN AMOUNT TO ALLOCATE
	PUSHJ	P,GETCOR	;GET SOME ZEROED CORE
	  POPJ	P,		;SORRY, NOT AVAILABLE
	SE1XCT	<XMOVEI	T2,CSOINL(T1)> ;OFFSET TO PORT CONTROL BLOCK
	MOVEM	T2,CHNPCB##(P1)	;STORE FOR POSTERITY
	HRRZ	T2,T1		;COPY ADDRESS OF CHUNK FOR SKIP CHAIN
	HRLI	T2,CSOINT	;ADDRESS OF PROTOTYPE SKIP CHAIN
	BLT	T2,CSOINL-1(T1)	;COPY PROTOTYPE
	ADDM	T1,CSOJR2(T1)	;MAKE SECOND JRST JOIN THE XJEN/JRST
	ADDM	T1,CSOSA1(T1)	;FILL IN THE ADDRESS PORTION OF SAVE T1 INSTR
	ADDM	T1,CSOSA2(T1)	;...
	ADDM	T1,CSOSA3(T1)	;...
	ADDM	T1,CSOSA4(T1)	;...
	ADDM	T1,CSOJMP(T1)	;FILL IN THE JRST TO THE SAVE AC ROUTINE CALL
	MOVEI	T2,CHNBTS##(P1)	;ADDRESS OF BITS TO TEST FOR ON INTERRUPT
	HRRM	T2,CSOTST(T1)	;FILL IN THE ADDRESS
	DPB	P2,[POINT 7,CSOCNI(T1),9] ;FILL IN THE DEVICE CODE
	ADDM	T1,CSOPCB(T1)	;FILL IN THE ADDRESS OF THE PORT CONTROL BLOCK
IFN FTENET,<
	CAIN	P4,KNIIDX	;KLNI?
	JRST	[MOVE	T2,.CPNPS## ;YES, GET AC SAVE ROUTINE
		 MOVEI	T3,KNIINT## ;GET INTERRUPT HANDLER ADDRESS
		 JRST	CNFIP1]	;CONTINUE
>; END IFN FTENET
IFN FTSCA,<
	CAIN	P4,KLPIDX	;KLIPA?
	JRST	[MOVE	T2,.CPSAV## ;YES, GET AC SAVE ROUTINE
		 MOVEI	T3,KLPINT## ;GET INTERRUPT HANDLER ADDRESS
		 JRST	CNFIP1]	;CONTINUE
>; END IFN FTSCA
CNFIP1:	HRRM	T2,CSOSAC(T1)	;FILL IN THE ADDRESS OF THE AC SAVE ROUTINE
	HRRM	T3,CSOIRP(T1)	;FILL IN THE ADDRESS OF THE INTERRUPT HANDLER
IFN FTENET,<
	CAIN	P4,KNIIDX	;KLNI?
	MOVEI	T2,KNICHN##	;YES
>; END IFN FTENET
IFN FTSCA,<
	CAIN	P4,KLPIDX	;KLIPA?
	MOVEI	T2,DSKCHN##	;YES
>; END IFN FTSCA
	IMULI	T2,2		;PI CHANNEL TIMES TWO
	ADDI	T2,40		;OFFSET IN EPT FOR THE XPCW CH??
	ADD	T2,.CPEPT##	;ADD IN THE EPT ADDRESS
	MOVEI	T3,-FSTICD/4(P2) ;GET INTERNAL CHANNEL NUMBER
	IMULI	T3,4		;TIMES LENGTH OF CHANNEL LOGOUT AREA
	ADD	T3,.CPEPT##	;ADD IN EPT ADDRESS
	MOVE	T2,(T2)		;GET THE INTERRUPT INSTRUCTION
	MOVEM	T2,.CSIVI(T3)	;FILL IN VECTOR INTERRUPT INSTRUCTION
	HRRZ	T3,T1		;GET ADDRESS OF OUR SKIP CHAIN
	HRLI	T3,(JRST)	;BUILD A JRST
	EXCH	T3,4(T2)	;SWAP JRST/XJEN AT CH??+4 WITH JRST TO US
	MOVEM	T3,CSOJR1(T1)	;PUT THAT JRST/XJEN IN OUR SKIP CHAIN
	MOVE	T1,CHNPCB##(P1)	;GET ADDRESS OF PORT CONTROL BLOCK
IFN FTENET,<
	CAIN	P4,KNIIDX	;KLNI?
	PUSHJ	P,KNICFG##	;YES, TELL DRIVER
>; END IFN FTENET
IFN FTSCA,<
	CAIN	P4,KLPIDX	;KLIPA?
	PUSHJ	P,KLPCFG##	;YES, TELL DRIVER
>; END IFN FTSCA
	POPJ	P,		;RETURN
;THE FOLLOWING CODE IS REPLICATED AND INSERTED INTO THE CONSO SKIP CHAIN
;WHEN AN IPA CHANNEL DEVICE IS DETECTED.  THE INTERRUPT HANDLER IS CALLED
;WITH THE CONI BITS IN T1, AND THE PCB ADDRESS IN T2.

CSOINT:!PHASE	0		;ZERO ORIGIN
	SKIPA			;A LITTLE TROUBLE TO CHECK FOR PI FLAGS
CSOJR1:!JRST	.		;TRY NEXT DEVICE ON CHAIN
CSOSA1:!MOVEM	T1,CSOST1	;SAVE T1 A BIT
CSOCNI:!CONI	0,T1		;GET CONI BITS
CSOTST:!TDNE	T1,0		;INTERRUPT FOR THIS DEVICE?
CSOJMP:!JRST	CSOSA3		;YES
CSOSA2:!MOVE	T1,CSOST1	;GET SAVED T1
CSOJR2:!JRST	CSOJR1		;TRY NEXT DEVICE ON CHAIN

CSOSA3:!EXCH	T1,CSOST1	;GET SAVED T1 BACK, SAVE CONI STATUS BITS
CSOSAC:!JSR	PIERR##		;SAVE AC'S, SET UP PDL
CSOSA4:!MOVE	T1,CSOST1	;GET BACK CONI STATUS BITS
CSOPCB:!MOVEI	T2,CSOINL	;GET ADDRESS OF PCB
CSOIRP:!JRST	0		;CALL INTERRUPT HANDLER

CSOST1:!0			;HOLDS T1 WHILE TESTING CONI BITS
	DEPHASE			;END OF PHASED CODE
CSOINL==.-CSOINT		;LENGTH OF CONSO SKIP CHAIN CODE
;ROUTINE TO BUILD A KDB FOR AN HSC-50 DISK/TAPE CONTROLLER.
;CALL:
;	T1/ DISK/TAPE FLAG (ZERO/NON-ZERO) ,, CI NODE NUMBER
;	PUSHJ	P,AUTHSC
;RETURN:
;	CPOPJ IF CAN'T BUILD CHN AND KDB
;	CPOPJ1 IF CHN AND KDB BUILT WITH:
;	J/ DISK KDB ADDRESS
;	W/ TAPE KDB ADDRESS
;PRESERVES OTHER USEFUL REGISTERS
;NOTE: THE KONTROLLER NUMBER IS THE SAME AS THE CI NODE NUMBER.
;THIS MAKES THE DEVICES ON A PARTICULAR HSC-50 HAVE CONSISTENT
;KONTROLLER NAMES (E.G., RAF0) ACROSS RELOADS.

IFN FTCIDSK!FTCITAP,<
AUTHSC::PUSHJ	P,SAVR##	;SAVE R
	MOVSI	R,CP.KLP##!CP.22B##!CP.MX## ;THIS IS A KLIPA CHANNEL
	PUSHJ	P,SAVE4##	;SAVE P1-P4
	SETZ	P2,		;MAKE TESTS ON DEVICE CODE FAIL
IFN FTCIDSK,<
	MOVEI	P4,RAMIDX	;GET SOME HSC-50 DISK INDEX
>; END IFN FTCIDSK
IFN FTCITAP,<
	TLZE	T1,-1		;DISK KDB?
	MOVEI	P4,TAMIDX	;NO, GET SOME HSC-50 TAPE INDEX
>; END IFN FTCITAP
	HRRZM	T1,NUMRAA##	;MAKE SURE KDB10 GETS THE RIGHT NAME FOR THIS HSC-50
	PUSHJ	P,BLDCHN	;BUILD A CHANNEL DATA BLOCK
	  POPJ	P,		;NO CORE
	PUSHJ	P,BLDKDB	;BUILD KONTROLLER DATA BLOCK
	  POPJ	P,		;NO CORE
	JRST	CPOPJ1##	;SKIP RETURN
>; END IFN FTCIDSK!FTCITAP
;ROUTINE TO BUILD A CHANNEL DATA BLOCK.
;CALL:
;	P2/ DEVICE CODE/4
;	R/ CHANNEL TYPE BITS
;	PUSHJ	P,BLDCHN
;RETURN:
;	CPOPJ IF NO MEMORY AVAILABLE
;	CPOPJ1 IF SUCCESS WITH:
;	P1/ CHN ADDRESS

BLDCHN:	MOVEI	T2,LENCCB##	;LENGTH OF A CHANNEL DATA BLOCK
	PUSHJ	P,GETCOR	;GET THE SPACE
	  POPJ	P,		;NONE AVAILABLE. CAN'T DO ANYTHING
	MOVE	P1,T1		;P1 = CHAN ADDRESS
	MOVEI	T1,SYSCHN##-.CHSYS##
CDB1:	SKIPN	T2,.CHSYS##(T1)	;LINK THIS CDB ONTO THE SYSCHN CHAIN (AT END)
	JRST	CDB2
	HLRZ	T1,T2
	JRST	CDB1
CDB2:	HRLM	P1,.CHSYS##(T1)	;SAVE CHAN ADDR
	SETOM	CHNBSY##(P1)	;INDICATE IDLE
	HRRI	R,CHVIFP##
	MOVEM	R,CHNIFP##(P1)
	MOVEI	T1,CHVIFT##
	MOVEM	T1,CHNIFT##(P1)
	MOVEI	T1,3		;INITIAL FAIRNESS FOR SWAPPING
	MOVEM	T1,CHNIFS##(P1)
	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,.CHCSR##(P1)	;SAVE FOR ERROR REPORTING
	CAIL	P2,FSTICD/4	;NON-INTERNAL CHANNEL?
	CAILE	P2,LSTICD/4	;...
	JRST	CPOPJ1##	;YES, SKIP RETURN
	MOVEI	T1,-FSTICD/4(P2) ;COMPUTE INTERNAL CHANNEL NUMBER
	MOVEM	P1,.CPCHN##(T1)	;STORE CHN ADDRESS IN CDB
	JRST	CPOPJ1##	;SKIP RETURN
;ROUTINE TO BUILD A KONTROLLER DATA BLOCK.
;CALL:
;	R/ CHANNEL TYPE (CP.???),,0
;	P1/ CHN ADDRESS
;	P2/ DEVICE CODE/4
;	P4/ TYPTAB INDEX
;	PUSHJ	P,BLDKDB
;RETURN:
;	CPOPJ IF NO MEMORY AVAILABLE
;	CPOPJ1 IF SUCCESS WITH:
;	J/ KDB ADDRESS (IF DISK KDB)
;	W/ FIRST TUB ADDRESS,,TKB ADDRESS (IF TAPE KDB)

BLDKDB:	LDB	T2,[POINT 9,KDBTAB(P4),17] ;GET LENGTH OF THIS KDB
	JUMPE	T2,CPOPJ##	;GIVE UP NOW IF NO PROTOTYPE KDB
	PUSHJ	P,KDBCTG	;ENSURE NECESSARY PARTS OF KDB ARE CONTIGUOUS
	PUSHJ	P,KDBIOW	;GET ICCW
	  POPJ	P,		;NO LOW CORE BLOCKS AVAILABLE
	PUSH	P,T1		;SAVE ADDRESS OF ICCW
	LDB	T2,[POINT 9,KDBTAB(P4),17] ;GET KDB LENGTH AGAIN
	PUSHJ	P,CORGRB	;GET THE CORE
	  JRST	[POP	P,T1	;GET ICCW ADDRESS BACK
		 CAIL	T1,PAGSIZ## ;RH20?
		 POPJ	P,	;YES, NOTHING TO RETURN
		 PJRST	RTNIOW##] ;RETURN LOW CORE BLOCK AND QUIT
	MOVE	J,T1		;J = KDB ADDRESS
	MOVEI	W,4(J)		;IN CASE OF A MAGTAPE
	HRL	W,T2		; LH WILL BE ADDR OF FIRST UDB
	HRL	T1,KDBTAB(P4)	;COPY PROTOTYPE KDB
	BLT	T1,-1(T2)	; TO THE CORE WE JUST GOT
IFN FTCIDSK!FTCITAP,<
	TLNE	R,CP.KLP##	;KLIPA DEVICE TYPE?
	JRST	KDB3		;YES, SKIP INTERRUPT STUFF
>; END IFN FTCIDSK!FTCITAP
	MOVE	T1,.CPEPT##	;FIND JSR CH??
	CAIL	P4,TAPIDX
	TROA	T1,TAPCHN##*2+40-1
	TRO	T1,DSKCHN##*2+40-1
	MOVE	T1,1(T1)
	MOVE	T2,4(T1)	;START OF CONSO CHAIN
	MOVE	T3,J		;POINT START OF CHAIN TO THIS KDB
	HRLI	T3,(JRST)
	MOVEM	T3,4(T1)
	MOVEM	T2,1(J)		;MAKE THIS INTERRUPT LOC BE THE JEN
	MOVN	T1,KDBTAB(P4)	;GET LENGTH OF KDB
	TLO	T1,777000	;MAKE SURE IT'S NEGATIVE
	HRR	T1,J		;START OF KDB
KDB2:	LDB	T2,[POINT 10,(T1),9] ;GET AN INSTR IN THE KDB
	CAIN	T2,7650/4	;IS IT AN IO INSTRUCTION?
	DPB	P2,[POINT 7,(T1),9] ;YES, CHANGE IT TO THIS CHANNEL
	AOBJN	T1,KDB2		;AND LOOP
	TLNE	R,-1-CP.22B##	;RH10?
	JRST	KDB3
	MOVE	T1,[JFCL 350]	;YES, FIX UP INTERRUPT LOCS
	HRRM	T1,(J)		; WHICH GOT ASSEMBLED FOR RH20
	CAIGE	P4,TAPIDX
	HLLZM	T1,2(J)
KDB3:	CAIL	P4,TAPIDX	;TAPE?
	JRST	KDB4		;YES
	ADDI	T3,1		;NO, FIX UP REST OF INTERRUPT INST'S
	MOVEM	T3,4(J)
	MOVE	T1,.CPSAV##	;DISK PI SAVE ROUTINE
	HRRM	T1,5(J)		;INTO THE JSR
	ADDI	J,7		;POINT J AT REAL KDB (PAST SKIP-CHAIN INSTRS)
	JRST	KDB7		;CONTINUE
KDB4:	ADDI	J,4		;POINT J AT REAL KDB (PAST SKIP-CHAIN INSTRS)
KDB7:	MOVSI	T1,-1		;MAKE CHANNEL'S LIST OF KDBS ONE LONGER
	ADDB	T1,CHNTBP##(P1)	;...
	AOBJN	T1,.		;MOVE TO END OF EXISTING KDBS
	MOVEM	J,-1(T1)	;STORE KDB ADDRESS IN CHN
	POP	P,T1		;GET ICCW BACK
	CAIL	P4,TAPIDX	;TAPE?
	JRST	TAPKDB		;YES, FINISH UP
	MOVEM	T1,KONIOC##(J)	;DISK - STORE ICWA
	MOVEI	T1,DSKCHN##	;SET UP PI
	DPB	T1,KOYPI##	; IN KDB
	MOVEI	T1,SYSKON##-KONNXT##
KDB8:	HLRZ	T2,KONNXT##(T1)	;LINK THIS KDB INTO THE END OF THE CHAIN
	JUMPE	T2,KDB9
	MOVE	T1,T2
	JRST	KDB8
KDB9:	HRLM	J,KONNXT##(T1)
KDB10:	CAIG	P4,RPXIDX	;RP04/05/06/07?
	JRST	[AOS  T1,NUMRPA##
		 AOS  NUMRPC##
		 JRST .+1]
	CAIN	P4,RNAIDX	;RP20?
	AOS	NUMRNC##
IFN FTCIDSK,<
	CAIL	P4,RAMIDX	;CI DISK?
	CAILE	P4,RAXIDX	;...
	SKIPA
	JRST	[AOS  T1,NUMRAA##
		 AOS  NUMRAC##
		 JRST .+1]
>; END IFN FTCIDSK
	AOS	NUMKON##	;COUNT A CONTROLLER
	SUBI	T1,1		;SET UP KONTROLLER NUMBER
	HLRZ	T2,SYSKON##	;STARTING AT 1ST KDB IN SYSTEM
KDB11:	CAIN	T2,(J)		;LOOK FOR A MATCH WITH THE NAMES
	JRST	KDB13		; WE'RE ABOUT TO BUILD
	LDB	T3,KOZKNM##	;KONTROLLER NUMBER
	CAIE	T3,(T1)		;MATCH?
	JRST	KDB12		;NOT ON THIS ONE, TRY NEXT
	MOVE	T3,KDBTAB(P4)	;MAYBE CHECK TO SEE IF SAME TYPE
	HRRZ	T3,KONRDS##+7(T3)
	HRRZ	T4,KONRDS##(T2)
	CAIN	T4,(T3)		;SAME TYPE?
	JRST	KDB10		;YES. BUMP LETTER AND TRY AGAIN
KDB12:	HLRZ	T2,KONNXT##(T2)	;NO MATCH. TRY NEXT KDB
	JRST	KDB11
KDB13:	DPB	T1,KOYKNM##	;SAVE NUMBER IN THE KDB
	MOVE	T1,.CPBIT##	;GET BIT FOR THIS CPU
	IORM	T1,KONCAM##(J)	;SET ACCESSIBILITY MASK IN KDB
	HRRM	P1,KONCHN##(J)	;POINT KDB AT CDB
	HRRZ	T1,J		;GET KDB ADDRESS
	ADDB	T1,KONTBP##(J)	;INCLUDE KDB ADDRESS IN KONTBP
	HRRM	T1,KONPTR##(J)	;SET UP KONPTR
IFN FTKL10,<
	CAIE	P4,RNAIDX	;RP20?
	JRST	CPOPJ1##	;RETURN
	MOVEI	T1,CHNRSC##(P1)	;YES. SET UP SOME EXTRA STUFF
	MOVEM	T1,RNXRSC##(J)
>	;END IFN FTKL10
	JRST	HAVKDB
TAPKDB:	MOVE	T2,.CPSAV##	;GET PI SAVE LOCATION
	HLRM	T2,-2(J)	;SAVE IN INTERRUPT LOC (EG JSR SAV4)
	MOVEM	T1,TKBICP##(J)	;SAVE ICWA IN KDB
	ADDI	T1,3		;POINT TO VECTORED INTERRUPT WORD
	HRLI	T1,744002	;ASSUME RH20 FLAVOR OF VECTOR
	TLNN	R,-1-CP.22B##	;RH10?
	HRLI	T1,444002	;RH10-STYLE VECTOR
	TLNN	R,CP.DX1##	;NO IVI FOR DX10
	MOVEM	T1,TKBIVI##(J)
	MOVEI	T1,CNFMTK##-TKBKDB##
TKDB1:	SKIPN	T2,TKBKDB##(T1)	;LINK THIS KDB INTO CNFMTK/TKBKDB CHAIN
	JRST	TKDB2
	MOVE	T1,T2
	JRST	TKDB1
TKDB2:	MOVEM	J,TKBKDB##(T1)
	ADDM	J,TKBIUN##(J)	;POINT TKBIUN, TKBCUN AT RIGHT PART OF KDB
	ADDM	J,TKBCUN##(J)
	TLNE	R,CP.DX1##
	JRST	TKDB3		;IF NOT A DX10
	ADDM	J,TKBVIN##+5(J) ; SET UP TKBVIN
	HRRZ	T1,J
	ADD	T1,TKBVIN##+4(J)	;WORRY ABOUT OVERFLOW IN VIN+4
	HRRM	T1,TKBVIN##+4(J)	; (STARTS AS JRST -2)
	ADDM	J,TKBVIN##+3(J)
	ADDI	T1,1
	HRRM	T1,TKBVIN##+7(J)
TKDB3:	HRLZ	T1,.CPCPN##	;CPU NUMBER INTO KDB
	LSH	T1,^D15
	MOVEM	T1,TKBSTS##(J)
	MOVEM	P1,TKBCDB##(J)	;POINT KDB AT CDB
	MOVEI	T1,CNFMTK##-TKBKDB##
TKDB4:	SKIPE	T1,TKBKDB##(T1)	;FIND 1ST KDB ON THIS CHAN
	CAIN	J,(T1)
	JRST	TKDB7		;NO KDB WITH MATCHING CDB
	HRRZ	T3,TKBCDB##(T1)	;CHAN FOR THIS KDB
	CAIE	T3,(P1)		;SAME AS THE KDB WE'RE BUILDING?
	JRST	TKDB4		;NO, KEEP LOOKING
	MOVE	T3,T1		;NOW FIND LAST KDB ON CHAN
TKDB6:	HLRZ	T2,TKBCDB##(T3)
	CAIN	T2,(T1)
	JRST	TKDB8
	MOVE	T3,T2
	JRST	TKDB6
TKDB7:	SKIPA	T1,J		;1ST KDB IN SYSTEM. LINK TO ITSELF
TKDB8:	HRLM	J,TKBCDB##(T3)	;INSERT THIS KDB INTO RING
	HRLM	T1,TKBCDB##(J)
	HLLM	P2,TKBUNI##(J)	;SET UP TKBUNI
	MOVEI	T1,1
	HLRZ	T2,P2
	LSH	T1,(T2)
	HRRM	T1,TKBUNI##(J)
	SKIPL	KDBTAB(P4)	;MULTI UNIT
	HRROM	T1,TKBUNI##(J)	;NO. MAKE SURE IT IS NEGATIVE
	JRST	CPOPJ1##	;RETURN
;ROUTINE TO GET THE ICCW BLOCK
KDBIOW:	TLNE	R,-1-CP.22B##	;RH10?
	TLNE	R,CP.DX1##	;DX10?
	JRST	KDBIO1		;YES
IFN FTCIDSK,<
	TLNN	R,CP.KLP##	;KLIPA NEEDS REAL INITIAL CCW BLOCK
>; END IFN FTCIDSK
	JRST	KDBIO2		;NO (RH20)

				;REALLY SHOULD SET P1=0 HERE
KDBIO1:	PUSHJ	P,GCH4WD##	;GET LOW CORE BLOCK
	  POPJ	P,		;NOT AVAILABLE
	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

KDBIO2:	MOVEI	T1,-FSTICD/4(P2) ;RH20 - COMPUTE RIGHT ICWA
	LSH	T1,2
	ADD	T1,.CPEPT##
	JRST	CPOPJ1##	;RETURN
;ROUTINE TO READ THE DRIVE TYPE REGISTER
;CALL:
;	P2/ UNIT NUMBER,,DEVICE CODE/4
;	PUSHJ	P,REDDTR
;RETURN:
;	CPOPJ ALWAYS WITH:
;	T1/ CONTENTS OF DRIVE TYPE REGISTER

REDDTR:	MOVEI	T4,^D10		;HOW MANY TIMES WE WILL TRY
REDDT1:	MOVEI	T1,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR REGISTER ACCESS ERROR
	XCT	AUTCNO##	;...
	HLLZ	T1,P2		;GET UNIT NUMBER
	TLO	T1,(.DIDTR!DO.DRE) ;SET TO READ DRIVE TYPE REGISTER
	XCT	AUTDTO##	;DO IT
	IMULI	P,1		;STALL
	IMULI	P,1
	XCT	AUTDTI##	;READ IT BACK
	MOVE	T2,T1		;SAVE A COPY
	XCT	AUTCNI##	;GET CONI STATUS
	EXCH	T1,T2		;CONI STATUS TO T2, DRIVE TYPE REGISTER TO T1
	TRNN	T2,CI.RAE	;REGISTER ACCESS ERROR?
	POPJ	P,		;NO, RETURN
	SOJG	T4,REDDT1	;LOOP WHILE STILL RETRIES LEFT
	MOVEI	T1,CO.MBE!CO.RAE ;CLEAR REGISTER ACCESS ERROR
	XCT	AUTCNO##	;...
	SETZ	T1,		;GET A ZERO
	POPJ	P,		;RETURN
;ROUTINE TO ENSURE NECESSARY PARTS OF KDB WILL BE PHYSICALLY CONTIGUOUS.
;CALL:
;	P4/ TYPTAB INDEX
;	PUSHJ	P,KDBCTG
;RETURN:
;	CPOPJ ALWAYS
;PRESERVES T2 AND T3 FOR SUBSEQUENT CALL TO GETCOR/CORGRB

KDBCTG:	CAIGE	P4,TAPIDX	;MAGTAPE KDB?
	POPJ	P,		;NO, DISKS NEED NOTHING CONTIGUOUS
	MOVE	T1,[TKWCCL##,,TKBCCL##+4] ;# WORDS,,OFFSET TO CONTIGOUS AREA
	PJRST	CHKCTG		;MAKE SURE ALLOCATION WILL BE CONTIGUOUS


;ROUTINE TO ENSURE NECESSARY PARTS OF UDB WILL BE PHYSICALLY CONTIGUOUS.
;CALL:
;	P4/ TYPTAB INDEX
;	PUSHJ	P,UDBCTG
;RETURN:
;	CPOPJ ALWAYS
;PRESERVES T2 AND T3 FOR SUBSEQUENT CALL TO GETCOR/CORGRB

UDBCTG:	CAIGE	P4,TAPIDX	;MAGTAPE UDB?
	POPJ	P,		;NO, DISKS NEED NOTHING CONTIGUOUS
	MOVE	T1,TAPCTG-TAPIDX(P4) ;# WORDS,,OFFSET TO CONTIGUOUS AREA
;	PJRST	CHKCTG		;MAKE SURE ALLOCATION WILL BE CONTIGUOUS


;ROUTINE TO ENSURE CORE ALLOCATION WILL BE PHYSICALLY CONTIGUOUS.
;CALL:
;	T1/ # WORDS,,OFFSET TO CONTIGUOUS AREA
;	PUSHJ	P,CHKCTG
;RETURN:
;	CPOPJ ALWAYS
;PRESERVES T1-T4

CHKCTG:	TLNE	T1,-1		;ZERO WORDS IS ALWAYS CONTIGUOUS
	SKIPN	CORLOC		;ALLOCATING FROM ONCE ONLY CORE?
	POPJ	P,		;NO, MONITOR FREE CORE IS CONTIGUOUS
	PUSHJ	P,SAVT##	;MESSY BUT NECESSARY
	HLRZ	T2,T1		;LENGTH OF CONTIGUOUS AREA
	HRRZS	T3,T1		;START OF CONTIGUOUS AREA
	ADDI	T2,-1(T1)	;LAST WORD IN CONTIGUOUS AREA
	ADD	T1,CORLOC	;COMPUTE WHERE CONTIGUOUS AREA WILL RESIDE
	ADD	T2,CORLOC	;...
	LSHC	T1,W2PLSH##	;CONVERT TO PAGE NUMBERS
	CAIN	T1,(T2)		;CONTIGUOUS AREA RESIDE IN SAME PAGE?
	POPJ	P,		;YES, RETURN
	MOVE	T1,CORLOC	;ADJUST CORLOC SO ALLOCATE WILL BE CONTIGUOUS
	ADDI	T1,PG.BDY##	; BY ROUNDING UP TO NEXT PAGE
	TRZ	T1,PG.BDY##	; AND BACKING OFF BY THE OFFSET
	SUB	T1,T3		;SUBTRACT OFFSET FROM START OF NEXT PAGE
	MOVEM	T1,CORLOC	;GIVES US A NEW CORLOC
	POPJ	P,		;RETURN
;PRESERVES T3
AUTCOR::!			;EXTERNAL NAME
GETCOR:	PUSH	P,T3
	PUSHJ	P,CORGRB	;GET SOME CORE
	  JRST	T3POPJ##
	POP	P,T3
	MOVEI	T4,1(T1)
	HRLI	T4,(T1)
	SETZM	-1(T4)
	BLT	T4,-1(T2)
	JRST	CPOPJ1##	;SUCCESS


CORGRB:	SKIPN	T1,CORLOC	;ALLOCATING FROM ONCE ONLY CORE?
	JRST	CORGR1		;NO, GET CORE FROM MONITOR FREE CORE
	ADDB	T2,CORLOC	;GET TOP, BUMP FOR NEXT TIME
	CAMGE	T2,MONVFF##	;ABOVE FIRST FREE LOC?
	JRST	CORGRA		;NO, JUST MAKE SURE THE MAP IS RIGHT AND RETURN
	PUSHJ	P,SAVT##	;SAVE SOME ACS
	SUB	T2,MONVFF##	;NUMBER OF WORDS TO GET
	SKIPN	T2		;GET AT LEAST 1
	AOSA	T1,T2		;ONCMAP WANTS IT IN T1
	MOVE	T1,T2		; ...
	MOVSI	T2,(<PM.DCD>B2+PM.WRT+PM.PUB+PM.SWB)
	PUSHJ	P,ONCMAP##	;GET THE SPACE
CORGRA:
IFN FTMP,<
	PUSHJ	P,RDMAP		;COPY BOOTS MAP IF NOT THE BOOT CPU
>
	JRST	CPOPJ1##	;WIN RETURN

IFN FTMP,<
RDMAP:	PUSHJ	P,SAVT##	;ONLY REASON THIS IS A SUBROUTINE
	MOVE	T1,.CPCPN##	;OUR CPU NUMBER
	CAMN	T1,BOOTCP	;ARE WE THE BOOT?
	POPJ	P,		;YES, NOTHING TO DO
	PJRST	MAPINI##	;COPY BOOTS MAP SINCE MAY HAVE CHANGED
>

;HERE IF THE SYSTEM IS UP AND RUNNING
CORGR1:	TRZE	T2,3		;INTEGRAL NUMBER OF 4-WD BLOCKS?
	ADDI	T2,4		;NO, ROUND UP
	PUSH	P,T2		;SAVE NO OF WORDS TO GET
	PUSHJ	P,GETWDS##	;ASK FOR THE CORE
	  JRST	TPOPJ##		;CANT GET IT
	POP	P,T2		;GOT IT. RESTORE AMOUNT REQUESTED
	ADD	T2,T1		;PLUS START ADDR = END ADDR
	JRST	CPOPJ1##	;GIVE GOOD RETURN
;ROUTINE TO FIND FIRST AND LAST UDBS OF A CERTAIN TYPE IN SYSTEM
;CALL T1=0,,KDB  OR T1=-1,,CDB
;RETURNS T4=1ST,,LAST	(COULD BE THE SAME. IF NONE YET RETURNS T4=UDB,,UDB)
;RETURNS T1=0 IF FIRST SUCH UDB
FSTLST:	PUSHJ	P,SAVE1##
	MOVE	P1,T1		;SAVE ARGUMENT
	PUSHJ	P,FSTMAT	;FIND A MATCH
	  JRST	FSTLS2		;FOUND IT
FSTLS1:	MOVE	T4,U		;NO MATCH. 1ST=LAST=US
	HRL	T4,U
	POPJ	P,
FSTLS2:	HRL	T4,T3		;SAVE 1ST FOUND IN LH(T4)
FSTLS3:	HRR	T4,T3		;SAVE THIS AS LAST
	SETZ	T3,		;CLEAR T3 IN CASE LAST UNIT
	PUSHJ	P,FSTMA3	;NEXT UDB A MATCH?
	  JRST	FSTLS3		;YES, SAVE UDB ADDR
	POPJ	P,		;NO MORE MATCHES. DONE

;ROUTINE TO SEE IF WE HAVE A MATCH
;RETURNS CPOPJ IF YES, CPOPJ1 IF NO
FSTMAT:	HLRZ	T1,SYSKON##	;START AT FIRST KDB IN SYSTEM
FSTMA1:	MOVE	F,T1		;SAVE LOC OF KDB
	MOVE	T1,KONTBP##(T1)	;AOBJN POINTER TO UNITS ON KDB
FSTMA2:	SKIPN	T3,(T1)		;UDB THERE?
FSTMA3:	AOBJN	T1,.-1		;NO, TRY NEXT
	JUMPE	T3,FSTMA4	;FIND A UDB? NOT IF 0
	JUMPL	P1,[HRRZ T2,UNICHN##(T3)
		    JRST .+2]	;LOOKING FOR UNICHN IF NEGATIVE
	HRRZ	T2,UNIKON##(T3)	;POSITIVE - LOOKING FOR UNIKON
	CAIN	T2,(P1)		;MATCH?
	POPJ	P,		;YES, RETURN
	JUMPN	T2,FSTMA4	;NO. FOUND THIS UNIT?
	AOBJN	T1,FSTMA2	;YES. KEEP GOING IF NOT UNIT 7
FSTMA4:	HLRZ	T1,KONNXT##(F)	;STEP TO NEXT KDB
	JUMPN	T1,FSTMA1	;LOOK FOR UNIT MATCH IF IT EXISTS
	JRST	CPOPJ1##	;NO MATCH. SKIP
;RETURNS T4=UNIT NUMBER, T2=CONTROLLER "NUMBER"
FNYNAM:	PUSHJ	P,SETNAM	;SET UP T2=KDB NO, T4=UNIT NO
	TDC	T1,[61,,2000]	;CONVERT xxA0 TO xx000
	DPB	T3,[POINT 3,T1,17] ;3RD CHAR IS CDB NO
FNYNM1:	SUBI	T2,1
	DPB	T2,[POINT 3,T1,23] ;FINISH UP NAME
	DPB	T4,[POINT 3,T1,29]
	POPJ	P,		;AND RETURN

;SUBROUTINE TO MAKE UP A UNIT NAME
;RETURNS T4=UNIT NUMBER
MAKNAM:	PUSHJ	P,SETNAM	;SET ACS
	DPB	T2,[POINT 5,T1,17] ;STORE THE CONTROLLER LETTER
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSH	P,T4		;SAVE THE UNIT NUMBER
	MOVE	T2,T4		;GET THE UNIT NUMBER
IFN FTCIDSK,<
	CAIL	P4,RAMIDX	;CI DISK?
	CAILE	P4,RAXIDX	;...
	SKIPA			;NO
	HRRZ	T2,P2		;YES, GET PHYSICAL UNIT NUMBER (LAP PLUG NUMBER)
>; END IFN FTCIDSK
	MOVEI	P1,3		;NUMBER OF DIGITS
MAKNM1:	IDIVI	T2,^D10		;SPLIT OFF A DIGIT
	ADDI	T3,'0'		;CONVERT TO SIXBIT
	LSHC	T3,-6		;POSITION IN T4
	SOJG	P1,MAKNM1	;LOOP FOR REMAINDER
	TLNN	T4,170000	;FIRST DIGIT SIGNIFICANT?
	LSH	T4,6		;NO, TOSS IT
	TLNN	T4,170000	;FIRST DIGIT STILL SIGNIFICANT?
	LSH	T4,6		;NO, TOSS IT
	HLR	T1,T4		;STORE THE UNIT NUMBER
	JRST	T4POPJ##	;RESTORE T4 AND RETURN
SETNAM:	CAIL	P4,TAPIDX	;TAPE?
	JRST	[MOVE T1,[SIXBIT /MTA0/]
		 MOVE T2,NUMTAP## ;SET UP T1, T2 FOR TAPE
		 JRST SETNM1]
	CAIN	P4,RNAIDX	;RP20?
	JRST	[MOVE T1,[SIXBIT /RNA0/] ;GET BASE KONTROLLER NAME
		 MOVE T2,NUMRNA## ;GET KONTROLLER NUMBER
		 JRST SETNM1]	;CONTINUE
	CAIG	P4,RPXIDX	;RP04/05/06/07?
	JRST	[MOVE T1,[SIXBIT /RPA0/] ;GET BASE KONTROLLER NAME
		 MOVE T2,NUMRPA## ;GET KONTROLLER NUMBER
		 JRST SETNM1]	;CONTINUE
IFN FTCIDSK,<
	CAIL	P4,RAMIDX	;CI DISK?
	CAILE	P4,RAXIDX	;...
	SKIPA
	JRST	[MOVE T1,[SIXBIT /RAA0/] ;GET BASE KONTROLLER NAME
		 MOVE T2,NUMRAA## ;GET KONTROLLER NUMBER
		 JRST SETNM1]	;CONTINUE
>; END IFN FTCIDSK
SETNM1:	MOVE	T3,.CPCPN	;RETURN T3= CPU NUMBER
;SUBROUTINE TO RETURN CURRENT UNIT NUMBER
GETUNN:	HLRZ	T4,P2		;T4 = UNIT NUMBER
	SKIPGE	KDBTAB(P4)	;MULTI-UNIT?
	HRRZ	T4,P3		;YES. USE SLAVE NUMBER
	POPJ	P,		;AND EXIT
;RP04/05/06/07 MUST BE FIRST IN TYPTAB
;FOR DISKS, BITS 6-8 ARE UNIT TYPE CODE AS RETURNED BY DSKCHR UUO

TYPTAB:	0*1000+RPULEN##,,TY.RU
	1*1000+RPULEN##,,TY.RP6
	1*1000+RPULEN##,,TY.RP5
	3*1000+RPULEN##,,TY.RP7
RP7IDX==.-TYPTAB-1
RPXIDX==.-TYPTAB-1		;MAXIMUM RPXKON INDEX
	0*1000+RNULEN##,,TY.DXB
RNAIDX==.-TYPTAB-1
IFN FTCIDSK,<
RAMIDX==.-TYPTAB		;MINIMUM RAXKON INDEX
	0*1000+RAULEN##,,TY.R80
R80IDX==.-TYPTAB-1
	1*1000+RAULEN##,,TY.R81
R81IDX==.-TYPTAB-1
	2*1000+RAULEN##,,TY.R60
RAXIDX==.-TYPTAB-1		;MAXIMUM RAXKON INDEX
>; END IFN FTCIDSK
TAPIDX==.-TYPTAB
	TXULEN##,,TY.DXA
	DXULEN##,,1
DX1IDX==.-TYPTAB-1
	T8ULEN##,,TY.T78
T78IDX==.-TYPTAB-1
	T2ULEN##,,TY.T2L		;MUST BE LAST IN TYPTAB
TABLEN==.-TYPTAB-1

MULUNI==400000
KDBTAB:	RPKLEN##,,RPXKDB##
	RPKLEN##,,RPXKDB##
	RPKLEN##,,RPXKDB##
	RPKLEN##,,RPXKDB##
	MULUNI+RNKLEN##,,RNXKDB##
IFN FTCIDSK,<
	RAKLEN##,,RAXKDB##
	RAKLEN##,,RAXKDB##
	RAKLEN##,,RAXKDB##
>; END IFN FTCIDSK
	MULUNI+TXKLEN##,,TX2KDB##
	DXKLEN##,,DX1KDB##
	MULUNI+T8KLEN##,,T78KDB##
	MULUNI+T2KLEN##,,TM2KDB##

TAPTAB:	TX2UDB##
	DX1UDB##
	T78UDB##
	TM2UDB##

TAPCTG:	EXP TX2CTG##
	EXP DX1CTG##
	EXP T78CTG##
	EXP TM2CTG##
	$LOW

;TABLE OF  BYTE (9) PCB LENGTH , OFFSET TO CONTIG. AREA, LENGTH OF CONTIG. AREA

IPAPCB:
IFN FTENET,<
KNIIDX==.-IPAPCB		;KLNI INDEX
	EXP	KNIPCB##	;LOAD THE GLOBAL
>; END IFN FTENET
IFN FTSCA,<
KLPIDX==.-IPAPCB		;KLIPA INDEX
	EXP	KLPPCB##	;LOAD THE GLOBAL
>; END IFN FTSCA

CORLOC::0
IFN FTNET,<
MTANUM:	BLOCK	1		;COUNT OF MAGTAPES CONFIGURED
>

	$HIGH
	END