Google
 

Trailing-Edge - PDP-10 Archives - klad_sources - klad.sources/config.mac
There are 2 other files named config.mac in the archive. Click here to see a list.
TITLE	CONFIGURATION MODULE

	SEARCH	DEFINS,MONSYM
	ENTRY	CONFIG,ASKRP,GETVER,MCODEP
	ENTRY	DXCFG,INCRH,QSTART
	ENTRY	SELECT,DEVSEL
	INTERN	MBCMAX,MBCMIN,RHTBL,DEVTBL

;These are found in mainline

	EXTERN	FULLI,BUF1A,BUF2A,FREE,SHMODE,STARTQ,USEPI
	EXTERN	BSYCNT,SCPPC,ERCNT,SELFLG,NORET,NORPT
	EXTERN	SCPPC,ERCNT,..CONO,..CONI,..RDR6

;These are found in mainline suport file

	EXTERN	ATAWT,CLRATA,CLRERR,DUMPDR,IDENT,IDENTF,MSTCLR
	EXTERN	SENSIN,SNAPA,SNSDMP,SNAPDR,OPRACT,DRVCLR,.IDLE,.NOP,.SNSE
	EXTERN	.TIO,IOWAIT,XFSTRT,DUMPS,.REL,.REQ,UREQ,UREL
	EXTERN	.PION,.PIOFF

;These are found in common disk parameter file

	EXTERN	CWHD,CWRWD,TYPN,TYPA,DRVNAM,DRVTYP
	EXTERN	HOMCHK,HOMPNT,BATCHK,BATPNT,MNTTST
	EXTERN	ADCON

;These are found in the general utilities

	EXTERN	QSTN,TSCAN,.GTCOR,POCDEC

;These are found in controller support file

	EXTERN	CHSEL,DSETUP,LDRG04,RDRG01,RDRG06
	EXTERN	REGPNT,.CONI,.CONO,DIAGCR,LOGPNT,FFF
	EXTERN	ENABLE,USRION,USRIOF,CCSET,CCCLR,CCCHK

;These are found in the console package

	EXTERN	ST,LDUP,FILEXT,FILNAM,SUBEXT,SUBFIL,CADDR,SP,RCR

;These are found in the mapout module

	EXTERN	BATDSB

	XLIST
	BOX	<CONSTANTS AND VAIRIABLES FOR CONFIGURATION MODULE>,<
	BIT MEANINGS FOR RHTBL
	----------------------

	BITS 0-2	HOLD LOGICAL CHANNEL #
	BITS 3-5	HOLD DX DRIVE #
	BIT 6		SET IF U-CODE IS RELOADED AT CONFIG TIME
	BIT 7		SET IF SPINDLE IS TOPS20 FORMATTED
	BIT 8		SET TO 1 IF WE'RE USING THIS TABLE SLOT
	BIT 9		SET IF SPINDLE NOT USEABLE
	BIT 10		SET IF SPINDLE SELECTED AT CONFIG TIME
	BIT 11		SET IF SPINDLE DETECTED AT CONFIG TIME
	BIT 12		SET IF DX NOT USEABLE
	BIT 13		SET IF DX SELECTED AT CONFIG TIME
	BIT 14		SET IF DX DETECTED AT CONFIG TIME
	BIT 15		SET IF RH NOT USEABLE
	BIT 16		SET IF RH SELECTED AT CONFIG TIME
	BIT 17		SET IF RH DETECTED AT CONFIG TIME
	BITS 18-21	LOGICAL DRIVE TYPE (6 OR 7 FOR RP20'S)
				6 MEANS TOPS10 FORMAT
				7 MEANS TOPS20 FORMAT
	BITS 28-35	SPINDLE ADDRESS (8 BITS LONG)


	BIT MEANINGS FOR DEVTBL
	-----------------------

	BITS 0-7	INDEX (SLOT #) WITHIN THIS TABLE
	BIT 9		SPINDLE WRITE PROTECTED
	BIT 10		USER DATA ON THE MEDIA
	BIT 11		ALL OPERATIONS TO MAINTENANCE CYLINDER
	BIT 12		ALL WRITES TO THE MAINTENANCE AREA
	BIT 13		SET IF NO BAT BLOCKS AT CONFIG
	BIT 14		SET IF NO HOME BLOCKS AT CONFIG 
	BIT 15		SET IF SPINDLE IS ON LINE
	BITS 18-35	POINTER TO SPINDLES DSB (DEVICE STATUS BLOCK)

	NOTE: DEVTBL AND RHTBL FORM A 72 BIT WIDE STATUS TABLE FOR EACH OF
	THE POSSIBLE RP20'S FOUND ON A SYSTEM. THE TABLE IS SET UP
	AT 128 WORDS IN LENGTH. THERE IS ROOM FOR A MAXIMUM OF  8
	RH20'S, EACH WITH ONLY 1 DX20. EACH DX20 MAY HAVE UP TO 16
	SPINDLES ATTACHED TO IT. EACH SLOT IN THESE TABLES REPRESENT
	AN RH/DX/RP20 ADDRESS. >
 

MBCMIN:	54000,,0		;Lowest device code
MBCMAX:	57400,,0		;Highest device code

DRMX=	^D16			;Max # spindles per dx20
TBSIZ=	^D128			;Size of the config tables

TBWD:	-TBSIZ,,0		;A general counter pointer

RHTBL:	BLOCK	TBSIZ		;Our rhtbl
DEVTBL:	BLOCK	TBSIZ		;Out device table



	XLIST
	BOX	<CONFIG - - SYSTEM CONFIGURATOR>,<
	THIS ROUTINE DETERMINES WHICH CONTROLLERS AND DRIVES ARE
	ON THE SYSTEM AND THEN ALLOWS FOR THE SELECTION OF WHICH
	ONES ARE TO BE TESTED BY THE DIAGNOSTIC. 
	THIS ROUTINE ALSO CALLS A ROUTINE TO SET UP THE PROPER
	DIAGNOSTIC MONITOR CALL VIA A UUO OR JSYS BASED ON MONITOR 
	TYPE.  THIS ROUTINE CAN ALSO BE RECALLED DURING THE PROGRAM 
	FOR THE PURPOSE OF RECONFIGURING THE PROGRAM. WHEN CALLING IT OVER
	AND OVER AGAIN IT WILL PRESERVE ALL DSB AREAS FOR PREVIOUSLY SELECTED
	DRIVES WHICH GIVES THE ABILITY TO GO BACK AND RESELECT.  >

CONFIG:	PUT	0		;Save
	PUT	1
	PUT	2

;If we haven't done a full init, clear config tables

	SKIPE	FULLI		;Have we done  full init ?
	JRST	CONA		;Yes ?
	MOVE	1,TBWD		;No. get a pointer word (-cnt,,0)
	SETZM	RHTBL(1)	;Clear rhtbl entry
	SETZM	DEVTBL(1)	;Clear devtbl entry
	AOBJN	1,.-2		;Loop through entire table

;Preliminary table setup. set up 0-7 of devtbl with entry number.
;Set logical channel number to 0-2 of rhtbl. if rhtbl(8)=0, then clear
;Devtbl 8-35 and rhtbl 3-35.

CONA:	SETZM	0		;Clear ac0
	MOVE	1,TBWD		;A pointer (-cnt,,0)
TBLP:	DPB	1,[POINT 8,DEVTBL(1),7] ;Sets up devtbl 0-7
	LDB	2,[POINT 3,1,31] ;Gets chan # from our index (16 slots/rh)
	DPB	2,[POINT 3,RHTBL(1),2] ;Sets up rhtbl 0-2
	MOVE	2,RHTBL(1)	;Get the rhtbl entry
	TLNE	2,(1B8)		;This slot in use ?
	JRST	.+3		;Yes
	DPB	0,[POINT 28,DEVTBL(1),35] ;Clr devtbl 8-35
	DPB	0,[POINT 33,RHTBL(1),35] ;Clr rhtbl 3-35
	AOBJN	1,TBLP		;Loop thru entire table

CONB:	MOVE	0,[JFCL]
	MOVEM	0,UREQ		;Set these locs to no-ops
	MOVEM	0,UREL	

;If user mode, set up for diag jsys/uuo

	SKIPN	USER		;User mode
	JRST	CFGA		;No
	GO	DSETUP		;Yes. set up jsys or uuo

;Start polling hardware and setting up tables

CFGA:	GO	RHDXPL		;Find out which rh's and dx's exist
	GO	RP2TST		;Find out which rp20's exist
	MOVE	0,[GO QSTART]	;Qstart merely starts dx20 microcode
	MOVEM	0,UREQ		; .... After a request
	MOVEM	0,UREL		; .... Just before a release	

	GO	RPTELL		;Report what was found
	PCRLF
	GO	ASKRP		;Ask which to test
	PCRLF

	PUT	USEPI		;Save state of this flag
	GO	DXCFG		;Get rp20's to be tested
	GET	USEPI		;Restore it
	PCRLF

	GET	2		;Restore ac's
	GET	1
	GET	0
	RTN			;And exit

	XLIST
	BOX	<RHDXPL -- ROUTINE TO POLL FOR RH'S AND DX'S>,<
	THIS ROUTINE WILL SEARCH THE SYSTEM FOR ALL RH20'S AND
	DX20'S. IT CONSIDERS AN RH20 AS EXISTING IF A CONI RETURNS
	NON-ZERO DATA AND IT CONSIDERS A DX20 TO EXIST IF MASSBUS
	REGISTER 6 CONTAINS THE PROPER DRIVE TYPE. THIS ROUTINE LOOKS
	FOR NO MORE THAN 1 DX20 PER RH20.


	CALLING SEQ:
	GO	RHDXPL		;Do the search
	RTN			;Returns here always>

RHDXPL:	PUT	0		;Save some ac's
	PUT	1
	PUT	2
	PUT	3
	PUT	4
	PUT	5

;Init some pointers for this routine

	MOVE	3,TBWD		;A general pointer (-cnt,,0)
	MOVE	MBCN,MBCMIN	;Get first controller device code
	MOVEI	DRIVE,0		;Get first dx20 device code

;Trap control-c then turn on user iot bit

	GO	CCSET		;Enable for ^c intercepts
	GO	USRION		;Turn on user i/o privilege


;Start looking for rh20's/dx20's in real time

RHNEW:	GO	..CONI		;Issue a coni to the current rh
	SKIPN	1		;Is the coni empty ?
	JRST	RHNEXT		;Yes, try next rh
	TLNE	1,(1B0)		;IS THIS RH A KLIPA?
	JRST	RHNEXT		;Yes, try next rh
	MOVE	0,RHTBL(3)	;Get rhtbl entry
	TLO	0,(1B17)	;Set bit 17 (rh exists)
	MOVEM	0,RHTBL(3)	;And restore to table
DXNEW:	GO	..RDR6		;Read massbus register 6
	JRST	DXNEXT		;Rae - try next dx20

	LDB	2,[POINT 6,1,35];Get the drive type
	JUMPE	2,DXNEXT	;Type = 0 is invalid
	MOVEI	1,DRVTYP	;And table start adr
	GO	TSCAN		;Search for valid type
	JRST	DXNEXT		;Not valid
	ANDI	1,17		;Save only the logical index

;If not a dx20 we'll ignore... dx20/rp20 have index of 6 or 7

	CAIL	1,6		;Range check
	CAILE	1,7
	JRST	DXNEXT		;Wrong type drive... ignore ...
	JFCL			;Ok. continue

;Have a valid rh/dx pair... rhtbl(14)=1, drive# to rhtbl(3-5) and
;Put logical drive type into rhtbl(18-21)

	MOVE	0,RHTBL(3)	;Get the rhtbl entry
	TLO	0,(1B14)	;Dx exists bit
	DPB	DRIVE,[POINT 3,0,5] ;Dx number now set up
	DPB	1,[POINT 4,0,21] ;Logical drive type is now set up
	MOVEM	0,RHTBL(3)	;And restore to rhtbl
	MOVEI	DRIVE,7		;This prevent us from looking further

;Look for dx20 in a different addrss position

DXNEXT:	AOS	DRIVE		;Bump dx #
	CAIG	DRIVE,7		;Tried all possible dx's yet
	JRST	DXNEW		;No

RHNEXT:	GO	INCRH		;Go increment the rh device code
	ADDI	3,DRMX		;Point to next rh bank of slots
	SETZM	DRIVE		;Reset dx20 #
	CAMG	MBCN,MBCMAX	;Tried all possible rh's
	JRST	RHNEW		;No

;Finished the poll, turn off useriot and ctrl-c intercepts. check for ^c

	GO	USRIOF		;Yes, turn off user i/o privilege
	GO	CCCLR		;Disable ^c intercepts
	GO	CCCHK		;Check	for ^c

;This code copies some of the information from the first slot on each rh20
;To the other 15 because they are the same ....
;Copy: - rhtbl(0-2,3-5,14,17,18-21)

	MOVE	5,TBWD		;-Cnt,,0
	ADDI	5,RHTBL		;-Cnt,,rhtbl
	MOVE	4,5		;-Cnt,,rhtbl
AA:	HRLI	4,-DRMX		;-#Slots,,rhtbl
	MOVE	0,0(5)		;Get source word
	AND	0,[770017,,740000] ;Save desired fields and bits
BB:	MOVE	1,0(4)		;Fetch current destination word
	TDZ	1,[770017,,740000] ;Zero fields and bits being updated
	IOR	1,0		;Update words from source
	MOVEM	1,0(4)		;And save updated words
	AOBJP	5,CC		;Bump outer loop and jump out if done
	AOBJN	4,BB		;Bump inner loop and jump until done
	JRST	AA		;Inner loop done. process next 16 slots

;Done. restore the ac's and exit

CC:	GET	5		;Restore ac's
	GET	4
	GET	3
	GET	2
	GET	1
	GET	0
	RTN


	XLIST
	BOX	<RP2TST -- ROUTINE TO FIND ALL RP20 DISK MODULES>,<
	THIS ROUTINE PERFORMS SEVERAL FUNCTIONS, ALL HAVING TO DO WITH
	INTERROGATING THE HARDWARE AND ADJUSTING THE CONFIGURATION TABLES
	ACCORDINGLY. 

	1. CHECK THE EXISTING DX20'S TO SEE IF U-CODE CAN BE LOADED AND
	   STARTED. (NO LOADING TAKES PLACE IN USER MODE)

	2. ESTABLISH THE SPINDLE FORMATS FOR EACH OF THE DX20'S. THEY MAY
	   BE EITHER TOPS10, OR TOPS20. (IN USER MODE THEY ARE MADE TO
	   MATCH THE MONITOR TYPE AT THIS POINT)

	3. POLE THE CHANNEL BUSS ADDRESS 000-377 LOOKING FOR RP20 SPINDLES.
           A SPINDLE IS ASSUMED NOT THERE IF THERE ARE INITIAL SELECTION
	   SEQUENCE ERRORS. A SPINDLE WILL NOT BE ALLOWED IF IT REQUIRES
	   INTERVENTION (OR) WE GET COMPOSITE ERROR OUT OF THE SELECTION
	   SEQUENCE. 

	4. WHEN FINISHED, RHTBL/DEVTBL CORRECTLY INDICATE THE AVAILABILITY
	   OF RH/DX/SPINDLES THAT ARE AVAILABLE FOR SELECTION ...


	CALLING SEQ:
	GO	RP2TST		;Call the routine
	RTN			;Returns here always>

RP2TST:	PUT	1		;Save ac's
	PUT	2
	PUT	6

;First pick a rh20/dx20 pair to go searching on...

	SETOM	SELFLG		;Flag says start at beginning
SEL:	GO	DXSEL		;Choose an rh/dx pair
	JRST	RP2X		;Tried them all ... where done.
	JFCL			;Rh/dx pair are chosen

;We have selected an rh/dx pair. we have mbcn, drive, dsw, x1 set up
;For the first slot in this rh/dx group.  this gets us legal values
;So we can proceed with the code. we'll use ac6 to hold a scratch copy
;Of this guys rhtbl entry for local use here ...

	LDB	6,[POINT 8,DSW,7] ;Get the offset value for this entry
	MOVE	6,RHTBL(6)	;Now have a copy of rhtbl entry in ac6

;We need to insure a valid dsb pointer in dsw so we use free core.

	HRR	DSW,FREE	;Now have a valid pointer

;We'll keep our subunit in ac1 during the poling sequence

	SETZM	1		;Start with subunit=0 (spindle-0)
	HRL	DRIVE,1		;Subunit to left side of drive

;Do all the status checking and set up of dx20 before polling

	GO	DXINIT		;This routine handles the selected dx20
	JRST	SEL		;Error rtn... look for next dx20 ...
	JFCL			;Ok. microcode loaded and started

;Poll for currently selected subunit ....

RPPOL:	HRL	DRIVE,1		;Get the subunit into left side of drive
	DPB	1,[POINT 8,6,35] ;Subunit to our rhtbl entry copy
	GO	INOP		;This polls for the current subunit

;Update subunit and loop till we're done

	AOS	1		;Bump subunit
	CAIG	1,377		;Check for maximum
	JRST	RPPOL		;Try next one
	JRST	SEL		;Look for another rh/dx pair

;Done. restore things and exit

RP2X:	GET	6		;Restore things
	GET	2
	GET	1
	RTN			;And exit


;Dxinit - routine to perform dx20 setup and test functions
;
;This routine responsible for setting up rhtbl (6,7,12,18-21)
;For all of the slots for this rh/dx pair. it expects to find in ac6,
;A scratch copy of the rhtbl entry for the first slot of this rh/dx
;Group. dsw, mbcn, x1, drive are also set up correctly.
;
;Call seq:
;	Go	dxinit	;the call
;	Rtn+1 		;dx20 u-code couldnt be started
;	Rtn+2		; ok to try to use dx20

DXINIT:	PUT	0		;Save the ac's
	PUT	1
	PUT	2
	PUT	3
	SETZM	UREQ		;Ureq will not be executed after a request
	SETZM	UREL		;Urel will not be executed before the release
	TLZ	6,(1B12)	;Assume the dx20 is useable

;Establish spindle format for this dx20 and reload microcode if reqd.

	MOVE	0,MONTYP	;Get monitor type. -1=tops20  0=tops10
	DPB	0,[POINT 1,6,7] ;This establishes format in user mode
	SKIPE	USER		;Are we user mode ?
	JRST	DXINT1		;Yes, then were finished with dialogue.
POLT1:	TEXTF	[ASCIZ/
IS DX20 #/]
	MOVE	0,DRIVE		;Get dx20 #
	PNT1F			;Print it
	TEXTF	[ASCIZ/ON RH /]
	LDB	0,[POINT 9,MBCN,11] ;Get rh #
	PNT3F			;Print it
	TEXTF	[ASCIZ/TO BE TOPS20 FORMAT (Y=TOPS20, N=TOPS10)/]
	TLZ	6,(1B7)		;Assume tops10 format
	GO	QSTN		;Ask the question
	JRST	POLT1		;Timeout
	SKIPA			;Answer no
	TLO	6,(1B7)		;Yes, set tops20 format bit
	SKIPA
POLT2:	PCRLF
	TEXTF	[ASCIZ/DO YOU WISH TO RELOAD THE MICRO-CODE IN THIS DX20  ? /]
	TLZ	6,(1B6)		;Assume no reload
	GO	QSTN		;Ask the question
	JRST	POLT2		;Timeout
	SKIPA			;Answer no
	TLO	6,(1B6)		;Yes. set the reload bit.

;Now load/start microcode if necessary and check status
;First we adjust logical type according to format thats chosen ...

DXINT1:	TLNE	6,(1B7)		;Is the format tops20 ?
	ADDI	6,040000	;Yes. this adds 1 to logical type field
	LDB	X1,[POINT 4,6,21] ;Get logical type set up
	GO	.REL		;Relase the device
	GO	.REQ		;Request the device
	GO	MSTCLR		;Initialize the rh20
	TLNE	6,(1B6)		;Do we want to reload this dx20 ?
	GO	MCLOAD		;Yes, do so.
	GO	QSTART		;Start the ucode
	SETZM	1		;Clear ac1
	GO	RDRG01		;Read the dx20 status register
	JFCL			;Cbto
	JFCL			;Rae other than cbto

	MOVE	0,[GO QSTART]	;Set up to do quick restart microcode
	MOVEM	UREQ
	MOVEM	UREL
	GO	.REL		;Release the device

	TRNE	1,1B23		;Reg-03 data in ac1. is u-code running ?
	JRST	DXINTX		;Yes, give good return

;Problem on the dx20 ..

	TLO	6,(1B12)	;Set the rhtbl can't use bit
	TEXTF	[ASCIZ/
PROBLEM-CAN'T START U-CODE ON RH/]
	LDB	0,[POINT 9,MBCN,11]
	PNT3F
	TEXTF	[ASCIZ/ DX20-#/]
	MOVE	0,DRIVE
	PNT1F
	TEXTF	[ASCIZ/THIS DX20 IS BEING SKIPPED OVER
*****
/]
	JRST	DXINTY

;Update all rhtbl entries for all slots on this rh/dx pair and exit
;We update rhtbl(6,7,12,18-21) from ac6 current contents ...

DXINTX:	AOS	-4(P)		;No error.  give a skip return
DXINTY:	LDB	2,[POINT 8,DSW,7] ;Rhtbl index comes from dsw
	HRLI	2,-DRMX		;-#Slots,,index
	MOVE	1,6		;Copy update info to ac1
	AND	1,[006040,,740000] ;Save only bits to be updated
DXUP1:	MOVE	0,RHTBL(2)	;Get entry from rhtbl
	TDZ	0,[006040,,740000] ;Clear bits that will be updated
	IOR	0,1		;Update the appropriate bits
	MOVEM	0,RHTBL(2)	;Put updated word back in rhtbl
	AOBJN	2,DXUP1		;Loop through all slots

;All done ... restore and exit

	GET	3		;Restore the ac's
	GET	2
	GET	1
	GET	0
	RTN

;Inop - a routine to check status of currently selected spindle
;
;This routine goes out and tests the selected spindle to determine if:
;	1. Its there
;	2. Its on line and useable
;
;A spindle that is there will be marked not useable if it requires 
;Intervention or, a composite error sets during the initial selection 
;Sequences performed on the channel bus ...
;
;The very last thing it does is to update the rhtbl/devtbl entries
;According to what this routine determines...
;
;Call sequence:
;	Go	inop		;cal the routine
;	Rtn+1			;always

INOP:	PUT	0		;Save the ac's
	PUT	1

;Set up pi system and do the necessary i/o ..

	PUT	USEPI		;Save this flag
	SETZM	USEPI		;Don't use pi system
	GO	.REL		;Releas rh if we have it
	GO	.REQ		;Request the device
	GO	DRVCLR		;Clear the dx20
	SETZM	BSYCNT		;Clear out expected interrupt count
	GO	.TIO		;Issue a test-i/o to the rh/dx/rp
	GO	ATAWT		;Wait for the attention
	GO	DRVCLR		;Drive clear again
	GO	.TIO		;Two selects in case port was shut down
	GO	ATAWT		;Wait for the attention
	GO	SNAPA		;Get the registers
	GO	SENSIN		;Get the sense bytes into dsb
	GO	DRVCLR		;Clear the dx20
	GO	.REL		;And release the device

;The i/o is completed.. now test hardware status

	TLO	6,(1B11)	;Assume spindle there
	TLZ	6,(1B9)		;Assume spindle is useable
	MOVE	1,R1D(DSW)	;Get status reg data
	TRNN	1,1B21		;Comp error ?
	JRST	INOPC		;No. drive is there and ok to try

;Composite error. find out if not there or what !!

BADDRV:	LDB	1,[POINT 4,R2D(DSW),27] ;Get error class
	CAIN	1,3		;Is it a select error ?
	JRST	INOPS		;Yes, done with this drive

	MOVE	1,SBYT0(DSW)	;Get sense byte 0
	TRNN	1,SBIT1		;Is intervention required set ?
	JRST	INER		;No, some other error
	TEXTF	[ASCIZ/
THE FOLLOWING IS SKIPPED. IT REQUIRES INTERVENTION.
/]
	GO	IDENTF
	JRST	INOPS		;Done with this drive
INER:	TEXTF	[ASCIZ/
STATUS INDICATES ERROR CONDITION LOOKING FOR RP20
/]
	GO	IDENTF
	PCRL
	GO	DUMPDR		;Dump dx registers
	JRST	INOPC		;Done with this drive

;Here because of select error ... assume no drive at this address

INOPS:	TLZ	6,(1B11)	;Mark drive as not there
	JRST	INOPC		;To common code

;Update tables rhtbl/devtbl according to current dsw and ac6 (rhtbl image)

INOPC:	GO	TBLUPD		;Update the tables now

INOPX:	GET	USEPI		;Restore the flag
	GET	1		;Restore the ac's
	GET	0
	RTN


;Tblupd -- a table update routine called from inop
;
;This routine is used to update rhtbl/devtbl after we've polled for a 
;Particular spindle. at this point in time, the dsw for the current 
;Spindle is in dsw and the current rhtbl image is in ac6. 
;
;The only valid piece of information we really have for determining
;Where in the table we go is contained in ac6. we must search rhtbl
;For he drive and based on what we find there we update accordingly:
;
; A.	if there is a slot already assigned for this drive we update
;	Its status according to ac6 and dsw.
;
; B.	if there is not a slot assigned and a new drive has appeared
;	We assign a slot for its use and plug in the ac6/dsw status
;
;When we update the tables we update devtbl(8-17) from dsw(8-17) and
;Rhtbl(6-35) from ac6(6-35).
;
;Call seq:
;	Move	dsw,arg1		;get valid dsw data to the ac
;	Move	6,arg2			;valid rhtbl image in ac6
;	Go	tblupd			;update the tables
;	Rtn				;returns here
;
;This routine gives an error message if you ever try to make a new table
;Entry but the table is full. this can only happen if you configure more
;Than 16 spindles on a dx which is a violation of the configuration rules.
;If this happens, the additional drives will be ignored.

TBLUPD:	PUT	0		;Save things
	PUT	1
	PUT	2
	PUT	3
	PUT	DSW
	PUT	6

;Build a pointer to start of the bank of slots for this rh. we know that
;The offset to the first slot is contained right now in dsw(0-7).

	LDB	3,[POINT 8,DSW,7]	;Get offset to start of group
	HRLI	3,-DRMX		;-#Slots,,offset to first

;Search bank of slots for the spindle address currently in ac6(28-35)

TBUP1:	MOVE	1,RHTBL(3)	;Fetch current rhtbl entry
	TLNN	1,(1B8)		;Is this slot in use ?
	JRST	TBUP3		;No. update pointer and keep looking
	ANDI	1,377		;Yes.  save slots spindle address
	LDB	0,[POINT 8,6,35] ;Get desired spindle address from ac6
	CAME	0,1		;Do spindle numbers match ?
	JRST	TBUP3		;No. update pointer and keep looking

;Found the correct slot. update devtbl and rhtbl from dsw and ac6

TBUP2:	LDB	1,[POINT 10,DSW,17] ;Get dsw(8-17)
	DPB	1,[POINT 10,DEVTBL(3),17] ;Put into devtbl(8-17)
	DPB	6,[POINT 30,RHTBL(3),35] ;Put ac6(6-35) to rhtbl(6-35)
	JRST	TBUPX		;Done. time to exit

;Update pointer and loop thru table looking for spindle. if we finish
;Without finding it we proceed to next section of code who tries to
;Create a slot for this spindle.

TBUP3:	AOBJN	3,TBUP1		;Bump and loop if not done

;We want to create a new slot only if this drive is there and useable
;Otherwise we're done ....  in order to see if useable we look at our
;Rhtbl image corrently in ac6. the new guy is useable iff:
; Ac6(11,14,17)=1  and  ac6(9)=0

	MOVE	2,6		;Get a scratch copy to ac2
	TLC	2,(1B11!1B14!1B17) ;Complement the expected one bits
	TLNE	2,(1B9!1B11!1B14!1B17) ;Is drive useable ?
	JRST	TBUPX		;No. don't update the table
	JRST	TBUP4		;Yes. try to create an entry

;Here we re initialize our pointer before proceeding

TBUP4:	LDB	3,[POINT 8,DSW,7] ;Offset to 1st slot in group
	HRLI	3,-DRMX		;-# Slots,,pointer to the first

;Search for empty slot and make a new entry for the unit specified
;In ac6 in dsw.

TBUP5:	MOVE	1,RHTBL(3)	;Fetch current rhtbl entry
	TLNE	1,(1B8)		;Is the slot in use ?
	JRST	TBUP7		;Yes. update pointer and keep looking

;Found free slot. assign it, update devtbl and rhtbl from ac6 and dsw
;In this case we also invalidate dsp pointer devtbl(18-35)

TBUP6:	TLO	6,(1B8)		;Set the "slot in use" bit
	DPB	6,[POINT 30,RHTBL(3),35] ;Ac6(6-35) to rhtbl(6-35)
	LDB	1,[POINT 10,DSW,17] ;Get dsw(8-17)
	DPB	1,[POINT 10,DEVTBL(3),17] ;Put into devtbl(8-17)
	SETZM	1		;Clear ac1
	HRRM	1,DEVTBL(3)	;Clears dsb pointer, devtbl(18-35)
	JRST	TBUPX		;Done. time to exit.

;Update pointer and loop, looking for a free slot. if we finish without
;Finding one we print error message and continue ....

TBUP7:	AOBJN	3,TBUP5		;Bump pointer and loop if not done
	JRST	TBUP8		;Finished and found no free slots

;Error ... all slots are used. print error message and continue

TBUP8:	TEXTF	[ASCIZ/
PROGRAM AT MAXIMUM CONFIGURATION FOR THIS DX20 AND THE FOLLOWING RP20
CAN NOT BE TESTED:  /]
	GO	IDENTF		;Identify rh/dx/rp20
	PCRLF			;Advance a line
	JRST	TBUPX		;Exit

;Restore ac's and exit

TBUPX:	GET	6
	GET	DSW
	GET	3
	GET	2
	GET	1
	GET	0
	RTN			;Exit

	XLIST
	BOX	<RPTELL -- REPORT WHAT RP20'S WERE FOUND>,<
	THIS ROUTINE GOES DOWN THE CONFIG TABLES AND REPORTS WHICH
	RH20/DX20/SPINDLES EXIST ....

	AN ENTRY IS REPORTED AS EXISTING IF: 
	RHTBL(11,14,17)=1  (MEANS THERE THERE)
	RHTBL(9,12,15=0 (MEANS OK TO TRY TO USE)

	CALLING SEQ:
	GO	RPTELL		;Report
	RTN+1			;Returns here always>

RPTELL:	GO	CKTBSP		;See first if any are available
	PUT	0		;Save some ac's
	PUT	1
	PUT	2

;First print our header. we know there's at least 1

	TEXTF	[ASCIZ/
THE FOLLOWING CONFIGURATION IS SELECTABLE

RH20'S	DX20'S	RP20'S
------	------	------/]

;Initialize pointers and look for entries to report

	MOVE	2,TBWD		;-Cnt,,0

;Sit in this loop till we find first entry
 
RTAG1:	MOVE	1,RHTBL(2)	;Fetch an rhtbl entry
	TLC	1,(1B11!1B14!1B17) ;Set up the exists bits
	TLNE	1,(1B9!1B11!1B12!1B14!1B15!1B17) ;Is this entry useable ?
	AOBJN	2,RTAG1		;No ... try more.
	
;Found an entry ... report it
	
NEWRH:	PCRLF			;Start at new line
	LDB	0,[POINT 3,1,2] ;Get chan # of this rp20
	MOVEM	0,CHNSAV#	;Save for look ahead ...
	LSH	0,2		;X4
	ADDI	0,540		;Build an rh device code
	PNT3F
	TEXTF	[ASCIZ/    /]
	LDB	0,[POINT 3,1,5] ;Get dx20 #
	MOVEM	0,DXSAV#	;Save for look ahead
	PNT1F
	TEXTF	[ASCIZ/      /]
RPPNT:	LDB	0,[POINT 8,1,35] ;Get device address
	PNT3F

;Process next entry with look ahead and decide if we need to start
;A new line or continue on the same one with spaces separating ..

RTAG2:	AOBJP	2,RPTDON	;Bump pointer and jump when done
	MOVE	1,RHTBL(2)	;Fetch an rhtbl entry
	TLC	1,(1B11!1B14!1B17) ;Set up the exists bits
	TLNE	1,(1B9!1B11!1B12!1B14!1B15!1B17) ;Is this entry useable ?
	JRST	RTAG2		;No ... try more.

	LDB	0,[POINT 3,1,2] ;Get chn #
	CAME	0,CHNSAV	;Is this rp20 on same rh as last one ?
	JRST	NEWRH		;No. advance to next line and process.
	LDB	0,[POINT 3,1,5] ;Get dx #
	CAME	0,DXSAV		;Same dx ?
	JRST	NEWRH		;No. advance to next line and process
	JRST	RPPNT		;Report it

;Restore and exit code

RPTDON:	GET	2		;Restore the ac's
	GET	1
	GET	0
	RTN


	XLIST
	BOX	<ASKRP -- INPUTS RH/DX/SPINDLES TO BE TESTED>,<
	INPUTS A STRING OF DRIVE NUMBERS SEPARATED BY COMMMAS
	OR WILL ALSO ACCEPT THE CHARACTER "A" FOR ALL DRIVES
	THAT ARE AVAILABLE OR "N" FOR NONE ON A PARTICULAR RH.

	CALL SEQ:

	GO	ASKRP		;The call
	RTN1			;Return here  > 


ASKRP:	PUT	0		;Save some ac's
	PUT	1
	PUT	2
	PUT	3
	PUT	4

;First run down rhtbl clearing all the select bits ..

	MOVE	1,TBWD		;Get -cnt,,0
	MOVE	2,RHTBL(1)	;Fetch a devtbl entry
	TLZ	2,(1B10!1B13!1B16) ;Clear all selection bits
	MOVEM	2,RHTBL(1)	;Put it back
	AOBJN	1,.-3		;Loop thru entire devtbl

	TEXTF	[ASCIZ/

DO YOU WISH AUTOMATIC SELECTION (USE ALL DRIVES) ?/]
	SETZM	ATOCON#		;Clear the auto-config flag
	GO	QSTN		;Ask the question
	JRST	.-3		;Timeout
	SKIPA			;Answer is no
	JRST	ASKRR3		;Yes do an auto select

;Here we pick a useable rh/dx pair to work on ..

	SETOM	SELFLG		;Set the select flag
ASKRPM:	GO	DXSEL		;Select rh/dx pair
	JRST	ASKRPX		;Tried 'em all
ASKRPN:	MOVEI	CRLF
	PNTAF
	MOVE	0,CONSW		;Get switches
	TLNE	0,TXTINH	;Normal or short printout mode ?
	JRST	ASKRN1		;Short
	TEXTF	[ASCIZ/SELECT RP20'S (000-377, A=ALL, N=NONE)
ON RH-/]
	JRST	ASKRN2
ASKRN1:	TEXTF	[ASCIZ/DRIVES ON /]
ASKRN2:	LDB	[POINT 7,MBCN,9] ;Get rh dev code
	LSH	2		;Position for printing
	PNT3F			;Print it
	TEXTF	[ASCIZ/ DX-/]
	MOVE	0,DRIVE		;Get dx20 #
	PNT1F
	TEXTF	[ASCIZ/= /]
ASKRPQ:	TTIOCT			;Input some octal
	JRST	ASKRER		;Error return
	CAIL	0,0		;Normal return. ranget test
	CAILE	0,377
	JRST	ASKRPN		;Out of range

;Input is valid. scan our table to see if this spindle is there,
;If not, go back and re-prompt. spindle # is now in ac0.

PROSPN:	JFCL
	MOVE	3,TBNDX		;Get current table index
	ADDI	3,RHTBL		;-Cnt,,point to 1st slot on rh
	HRLI	3,-DRMX		;-# Slots,,pointer to first
	SUB	3,[1,,1]	;Back up by one to initialize
ASKT2:	AOBJP	3,SPINER	;Look through all slots

;Search for the desired spindle. we look at the in-use slots rhtbl(8)=1
;The spindle number comes from rhtbl(28-35).

	MOVE	1,(3)		;Fetch rhtbl entry
	TLNN	1,(1B8)		;Slot in use ?
	JRST	ASKT2		;No. look for another
	LDB	2,[POINT 8,1,35] ;Get spindle address
	CAME	2,0		;Is it the one we want ?
	JRST	ASKT2		;No. look further.

;Found the slot see if its useable rhtbl(8,11,14,17)=1 
;And rhtbl(9,12,15)=0      if ok, select by setting rhtbl(10,13,16)=1

	TLC	1,(1B8!1B11!1B14!1B17) ;Complement expected 1 bits
	TLNE	1,(1B8!1B9!1B11!1B12!1B14!1B15!1B17) ;Status ok ?
	JRST	SPINER		;No ... report and continue
	MOVE	1,(3)		;Yes. fetch clean copy
	TLO	1,(1B10!1B13!1B16) ;Set the select bits
	MOVEM	1,(3)		;Put back in table
	JRST	ASKT3		;Process next char to see whats next

;Here because we don't have selected spindle in config tables.
;Merely tell user, don't select this spindle and continue on ....

SPINER:	TEXT	[ASCIZ/
RP20 #/]
	PNT3			;Identify spindle by number
	TEXT	[ASCIZ/ IS NOT THERE OR IS NOT USEABLE
AND WILL NOT BE SELECTED FOR TEST

/]
	JRST	ASKT3		;Look at next thing to do


;Done with this spindle, see if next char is delimiter or end of line

ASKT3:	MOVE	$CHRIN		;Get the next char
	CAIN	0,15		;Is it a cr ?
	JRST	ASKRPM		;Yes. lets work on next rh/dx pair
	JRST	ASKRPQ		;No. go process next spindle number.


;Input error handler. checks for possibility of "a" or "n"

ASKRER:	CAIN	0,"A"		;Is char an "a" ?
	JRST	ASKRR1		;Yes
	CAIN	0,"N"		;Is char a "n"
	JRST	ASKRPM		;Yes
	JRST	ASKRPN		;No. input error, re-prompt.

;This is the "a" processor. he wants all spindles on this rh.
;We set rhtbl(10,13,16) for all slots whose rhtbl(8,11,14,17)=1
;And rhtbl(9,12,15)=0

ASKRR1:	MOVE	3,TBNDX		;Get current table index
	ADDI	3,RHTBL		;Make it -cnt,,pointer
	HRLI	3,-DRMX		;-# Slots,,pointer to first
	SUB	3,[1,,1]	;Point in front of first one
ASKT4:	AOBJP	3,ASKRPM	;Bump pointer. get out when done ..
	MOVE	1,(3)		;Get current untbl entry
	TLC	1,(1B8!1B11!1B14!1B17) ;Comp bits that should be 1
	TLNE	1,(1B8!1B9!1B11!1B12!1B14!1B15!1B17) ;Is entry useable ?
	JRST	ASKT4		;No. loop and try next entry
	MOVE	1,(3)		;Yes. refetch table entry
	TLO	1,(1B10!1B13!1B16) ;Set the selected bits
	MOVEM	1,(3)		;Put it back in table
	JRST	ASKT4		;Process all slots on this rh

;This is the auto-config processor. want all spindles in the table.
;We set rhtbl(10,13,16) for all entries whose rhtbl(8,11,14,17)=1
;And rhtbl(9,12,15)=0

ASKRR3:	SETOM	ATOCON		;Set the auto-config flag
	MOVE	3,TBWD		;-Cnt,,0
	SUBI	3,1		;Back pointer up for initialization
ASKT5:	AOBJP	3,ASKRPX	;Bump pointer. get out when done ..
	MOVE	1,RHTBL(3)	;Get current untbl entry
	TLC	1,(1B8!1B11!1B14!1B17) ;Comp bits that should be 1
	TLNE	1,(1B8!1B9!1B11!1B12!1B14!1B15!1B17) ;Is entry useable ?
	JRST	ASKT5		;No. loop and try next entry
	MOVE	1,RHTBL(3)	;Yes. refetch table entry
	TLO	1,(1B10!1B13!1B16) ;Set the selected bits
	MOVEM	1,RHTBL(3)	;Put it back in table
	JRST	ASKT5		;Loop thru rest of table

;Restore ac's and exit this routine

ASKRPX:	GET	4		;Restore ac's
	GET	3
	GET	2
	GET	1
	GET	0
	RTN			;And exit


	XLIST
	BOX	<DXCFG - HERE IS WHERE WE CHOOSE RUN TIME OPTIONS>,<
	ON EACH OF THE SELECTED DRIVES WE PERFORM THE FOLLOWING:
	1. ESTABLISH VALIDITY OF BAT BLOCKS
	2. ESTABLISH VALIDITY OF HOME BLOCKS
	3. ESTABLISH VALIDITY OF USER DATA ON THE MEDIA	
	4. ESTABLISH WHERE TO READ/WRITE (CE CYL ETC.)
	5. ESTABLISH IF STRUCTURE IS MOUNTED

	THIS ROUTINE DOES NOT SAVE ANY AC'S
	CALL SEQ:
	GO	DXCFG		;Call
	RTN+1			;Always returns here >

DXCFG:	PUT	USEPI		;Save things
	PUT	0
	PUT	1
	PUT	2
	PUT	3
	SETZM	USEPI		;Don't use pi system

;Init select flag and pick a drive for test

	SETOM	SELFLG		;Select first unit
	SKIPA			;Skip next instr. first time thru.
DXCFGS:	MOVEM	DSW,@(DSW)	;Put current dsw word back in devtbl
	GO	DEVSEL		;Do it
	JRST	DXCFGX		;Tried all. done.

;Have chosen an rh/dx/spindle pair. check for and build a valid 
;Dsb pointer if required...


	TRNN	DSW,777777	;Dsw ptr = 0 ?
	JRST	GS0		;Yes. go assign a dsb area
	HRRZ	0,DSW		;No. get pointer value
	CAME	0,FREE		;Pointing to free core ?
	JRST	GS0A		;No. then pointer is already assigned

;Here is where the dsb is assigned for the first time
;After it's assigned, it's cleared except for the first location.
;The first location is a pointer back to the location in devtbl
;Where dsw originated. it serves as a cross reference pointer so
;The master copy of dsw can be kept up to date on the fly as drive
;Status changes. you can say 'movem dsw,@(dsw)' to update devtbl.
;After we assign a dsb area to the free one, we create a new free
;Core area the size of a dsb to replace the one we've used.

GS0:	HRR	DSW,FREE	;Point to free dsb area
	SETZM	0(DSW)		;Clear first loc of dsb
	HRRZ	1,DSW		;Pointer to first word
	ADDI	1,DSBSIZ	;Now pointing to last word
	HRLZ	2,DSW		;Source,,0
	HRR	2,DSW		;Source,,source
	ADDI	2,1		;Source,,dest
	BLT	2,(1)		;Clears the dsb area
	LDB	1,[POINT 8,DSW,7] ;Gets table offset
	ADDI	1,DEVTBL	;Now have pointer into devtbl
	HRRM	1,(DSW)		;Into dsb and pointing back to devtbl entry

	MOVEI	1,DSBSIZ	;Now build a new free core area
	GO	.GTCOR		;Gets and clears core
	MOVEM	1,FREE		;Saves the pointer ....


;First we reset all the option flags and save current dsw copy

GS0A:	TLZ	DSW,1777	;This clears dsw(8-17)
	MOVEM	DSW,@(DSW)	;And puts back in devtbl

;Print header message and then proceed

	PCRLF
	TEXTF	[ASCIZ/
THIS IS ONE OF THE CONFIGURATIONS SELECTED
/]
	GO	IDENT		;Identify rh/dx/rp20/spindle

;Perform basic i/o to obtain hardware status

GS1:	TLZ	DSW,(1B9)	;Assume write-enabled
	TLO	DSW,(1B15)	;Assume on-line
	SETZM	BSYCNT		;Clear the busy counter
	GO	.REQ		;Request the device
	GO	CLRERR		;Clear the error register
	GO 	.IDLE		;Idle the dx20
	GO	.SNSE		;Issue sense and input
	GO	GETVER		;Reads dx20 microcode version into ac1
	DPB	1,[POINT 16,MCDVER(DSW),35] ;Save 16 bits
	GO	.REL		;Release the device

;Report dx20 microcode version

	MOVE	1,MCDVER(DSW)	;Get microcode version
	GO	MCODEP		;Print microcode version (not forced)

;I/o done. see if drive on-line

	MOVE	1,SBYT0(DSW)	;Get sense byte 0
	TRNN	1,SBIT1		;Check on-line
	JRST	GS2		;On-line
	TLZ	DSW,(1B15)	;Mark drive off-line
	TEXTF	[ASCIZ/
UNIT IS OFF LINE AND WILL NOT BE TESTED
/]
	JRST	GS9		;Yes, mark device not useable

;On line. see if write protected ..
;If write protected, just flag it, and report it and then continue
;A write protected drive is still useable and decisions on this matter
;Will be made at the test level

GS2:	MOVE	1,SBYT1(DSW)	;Get byte 1
	TRNN	1,SBIT6		;Write protected
	JRST	GS3		;No
	TLO	DSW,(1B9)	;Mark as write protected
	TEXTF	[ASCIZ/UNIT IS WRITE PROTECTED
/]
	JRST	GS3		;And continue


;We are now on-line and write-protect state is established ...
;Now we read ad check for valid bat blocks

GS3:	TLO	DSW,(1B15)	;Set on-line
	TLZ	DSW,(1B13)	;Assumes that bat blocks are valid
	MOVE	1,BUF1A		;Get buffer address
	MOVEI	2,2		;Want block #2
	GO	RDBAT		;Read the block into core and check it
	TLNE	DSW,(1B13)	;Is bat block ok ?
	JRST	GS4		;No. try other
	MOVE	1,BUF1A		;Ok so far... check contents
	GO	BATCHK		;Checks for valid contents
	SKIPA			;Rtn-1 invalid bat block
	JRST	GS5		;Rtn-2 valid bat block
GS4:	TLZ	DSW,(1B13)	;Assume next block is valid
	MOVEI	2,13		;Want block #13
	GO	RDBAT		;Read bat block 13 into core
GS5:	MOVE	1,BUF1A		;Get start of buffer
	GO	BATPNT		;Print status of bat blocks
	TLO	DSW,(1B13)	;Rtn-1 invalid bat block
	JFCL			;Rtn-2 valid bat block
	TLNE	DSW,(1B13)	;Is there a valid bat block ?
	JRST	GS6		;No ...
	MOVE	1,BUF1A		;Yes, get pointer to buffer
	GO	BATDSB		;Move entries into dsb area (mapout dat base)

;We have read bat blocks. now read and check for valid home blocks.
;The media is considered to have home blocks if either is good.

GS6:	TLZ	DSW,(1B14)	;Start by assuming home blocks ok
	MOVE	1,BUF1A		;Get the buffer address
	MOVEI	2,1		;# Of first home block
	GO	RDHOM		;Go and try to read it
	TLNE	DSW,(1B14)	;Does home block look ok ?
	JRST	GS6A		;No. go report
	MOVE	1,BUF1A		;Point to data buffer
	GO	HOMCHK		;Check for valid home block contents
	JRST	GS6A		;Rtn-1 invalid
	JRST	GS6C		;Rtn-2 valid
GS6A:	TLZ	DSW,(1B14)	;Assume 2nd home block is valid
	MOVE	1,BUF1A		;Get buffer address
	MOVEI	2,12		;# Of 2nd home block
	GO	RDHOM		;Go read it
GS6C:	SETZM	MONNAM(DSW)	;Clear dsb area locations
	SETZM	PAKID(DSW)	;For monitor and structure names
	MOVE	1,BUF1A		;Get starting addr of buffer
	GO	HOMPNT		;Print home block status and i.d.
	JRST	GS6D		;Invalid block
	MOVEM	1,MONNAM(DSW)	;Save monitor name from home block
	MOVEM	2,PAKID(DSW)	;Save structure name from home block
	JRST	GS7		;And continue
GS6D:	TLO	DSW,(1B14)	;Mark unit as having no home block

;Find out about the state of user data on the media

GS7:	TLZ	DSW,(1B10!1B11!1B12) ;Init some bits to zero
	SKIPE	ATOCON		;Are we doing auto-config ?
	JRST	GS8A		;Yes, avoid the dialogue

;Set up ac's for mounted structure test

	MOVE	2,MBCN		;Get rh # to ac2 3-9
	DPB	DRIVE,[POINT 3,2,26] ;Dx number in at bit 26
	HLRZ	0,DRIVE		;Get subunit # from drive(left)
	DPB	0,[POINT 8,2,35] ;Put subunit number in at bit 35
	MOVE	1,PAKID(DSW)	;Get the structure name read from home block
	GO	MNTTST		;See if structure is mounted
	JRST	GS7Q		;Structure is not-mounted. go query user.
	TEXTF	[ASCIZ/****** THIS UNIT IS CURRENTLY A MOUNTED STRUCTURE ******
THE PROGRAM WILL ALLOW WRITES ONLY TO THE MAINTENANCE CYLINDER(S)
/]
	JRST	GS7S		;Skip the user query about user data
GS7Q:	TEXTF	[ASCIZ/IS THERE DATA ON THE MEDIA THAT MUST BE SAVED /]
	GO	QSTN		;Ask the question
	JRST	.-1		;Timeout or error
	JRST	GS7A		;Answer is no
GS7S:	TLO	DSW,(1B10)	;Answer is yes. flag it.
	TEXTF	[ASCIZ/YOU HAVE 2 OPTIONS
/]
GSTT:	TEXTF	[ASCIZ/ENTER:(1,2 OR HELP) - /]
	TTSIXB			;Input in sixbit
	JRST	GSTT		;Timeout or error
	CAMN	0,[SIXBIT/H/]	;Want help ?
	JRST	.+3		;Yes
	CAME	0,[SIXBIT /HELP/]
	JRST	.+3		;No help ..
	TEXTF	OPTH		;Wants help. prin it.
	JRST	GSTT		;Ask again.
	CAME	0,[SIXBIT /2/]	;A 2 ?
	JRST	.+3		;Nope.
	TLO	DSW,(1B11!1B12) ;A 2. set both status bits
	JRST	GS8		;Then continue
	CAME	0,[SIXBIT /1/]	;A 1 ?
	JRST	GSTT		;No. ask again
	TLO	DSW,(1B12)	;Yes. set only one bit in status word
	JRST	GS8		;Continue

;Last chance to change mind. ask if he's sure there's no data to be
;Preserved. give chance to change mind. he's already said once that
;There's nothing on the media worth preserving. we only give another
;Chance if a home block is there .....otherwise, take his word for it.

GS7A:	TLNE	DSW,(1B14)	;Is there a home block ??
	JRST	GS8		;No. then don't bother asking
	TEXTF	[ASCIZ/ARE YOU SURE /] ;Last chance message
	GO	QSTN		;Ask the question
	JRST	GS7		;Timeout..another chance
	JRST	GS7		;Answer no ...another chance
GS8:	JRST	DXCFGS		;Get next drive

GS8A:	TLO	DSW,(1B10!1B12)	;All writes to maint cyl
	JRST	DXCFGS		;Get next drive

;Here to mark this spindle not useable.
;We set rhtbl(9)=1 and put it back

GS9:	LDB	1,[POINT 8,DSW,7] ;Get table offset from dsw
	MOVE	0,RHTBL(1)	;Get rhtbl entry
	TLO	0,(1B9)		;Mark as not useable
	MOVEM	0,RHTBL(1)	;Put rhtbl entry back
	JRST	DXCFGS		;Get next drive

;Time to restore things and exit

DXCFGX:	GET	3		;Restore ac's
	GET	2
	GET	1
	GET	0
	GET 	USEPI		;Restore pi use flag
	RTN			;Exit


	XLIST
	BOX <MCLOAD - ROUTINE TO LOAD AND START THE DX20 MICROCODE>,<
	THIS ROUTINE SETS UP THE CORRECT MICROCODE VERSION PARAMETERS
	AND THEN CALLS "LDUP" TO ACTUALLY LOAD THE MICROPROCESSOR.

	AFTER THE LOAD IT SETS UP ANOTHER CALL AND FINALLY CALLS "ST"
	TO START THE MICROCODE...

	THIS ROUTINE DETERMINES WHICH MICROCODE TO LOAD BY LOOKING AT
	THE CONTENTS OF "X1" WHICH IS THE LOICAL DEVICE TYPE.
	THIS WILL BE 6 FOR TOPS10 AND 7 FOR TOPS20...

	CALL SEQ:
	GO	MCLOAD		;Call the routine
	RTN			;The return >

MCLOAD:	PUT	0		;Save ac0
	MOVE	0,MCNAM		;Get tops10 ucode name
	CAIE	X1,6		;Did we choose correctly ?
	MOVE	0,MCNAM2	;No, get tops20 microcode name
	MOVEM	0,FILNAM	;Save it
	MOVEM	0,SUBFIL
	MOVSI	0,'ADX'		;Extention
	MOVEM	0,FILEXT	;Save it
	MOVEM	0,SUBEXT
	GO	LDUP		;Load the micro-processor
	FATAL			;Error return ...
	GO	QSTART		;Go start u-code and idle the dx20
	GET	0		;Restore ac0
	RTN			;And exit

MCNAM:	SIXBIT	/DXMCD/		;Tops10 u-code name
MCNAM2:	SIXBIT	/DXMCE/		;Tops20 u-code name

	XLIST
	BOX <QSTART - ROUTINE TO START U-COD AND IDLE THE DX20>,<
	THIS ROUTINE RESETS THE DX20 AND THEN STARTS THE U-CODE.
	IT THEN IDLES THE DX20 BY WRITING A 10(OCTAL) INTO THE
	DX20 CONTROL REGISTER. 

	CALL SEQ:
	GO	QSTART		;Call the routine
	RTN			;The return >


QSTART:	PUT	1		;Save ac1
	LDREG	3,2		;Reset the dx20
	MOVEI	1,5		;Get start address
	MOVEM	1,CADDR		;Address for console pkg
	GO	ST		;Start u-code
	GO	.IDLE		;Idle the dx20
	GET	1		;Restore ac1
	RTN


	XLIST
	BOX <GETVER - READS THE DX20 MICROCODE VERSION INTO AC1>,<
	
	CALL SEQ:
	GO	GETVER		;The call
	RTN			;Version is in ac1 >

GETVER:	PUT	0		;Save ac's	
	GO	.REQ		;Request device
	GO	SP		;Stop uprocessor
	SETOM	RUNFLG		;No type out
	MOVEI	1,0		;Get cram address to read
	MOVEM	1,CADDR		;Store it
	GO	RCR		;Code to get contents of cram in ac1
	GO	QSTART		;Restart ucode
	SETZM	RUNFLG		;Restore flag
	GO	.REL		;Release device
	GET	0
	RTN

	XLIST
	BOX <MCODEP - PRINT DX20 U-CODE VERSION FROM AC1>,<
	THIS ROUTINE PRINTS THE CURRENT DX20 MICROCODE VERSION AND EDIT
	NUMBERS FROM AC1 FOLLOWED BY A CRLF. (PRINTING IS NOT FORCED).

	THE LOW ORDER 16 BITS OF THE AC CONTAIN THE VERSION 
	AND EDIT NUMBERS.

	THE HIGH ORDER 6 BITS IS THE VERSION AND LOW ORDER 10 BITS 
	IS THE EDIT LEVEL.

	CALL SEQ:
	MOVE	1,ARG1		;Get 16 bit microcode identifier
	GO	MCODEP		;The call
	RTN			;Returns here >

MCODEP:	PUT	0		;Save the ac
	TEXT	[ASCIZ/DX20 MICROCODE:  VERSION - /]
	LDB	0,[POINT 6,1,25] ;Get version
	GO	POCDEC		;Print it
	TEXT	[ASCIZ/   EDIT - /]
	LDB	0,[POINT 10,1,35] ;Get edit level 
	GO	POCDEC		;Print it
	PCRL			;Advance to next line
	GET	0
	RTN			;Exit



	XLIST
	BOX <RDBAT -- READ SPECIFIED BAT BLOCK AND CHECK VALIDITY>,<
	THE FOLLOWING IS DONE:
	1. TURN OFF ERROR REPORTS, WE EXPECT ERRORS HERE.
	2. TURN OFF RETRY. THIS CODE DOES UP TO 10 RE-READS OF ITS OWN.
	3. BAT BLOCKS ARE CONSIDERED NON-EXISTANT IF AN ERROR
	   IS NOT RECOVERABLE WITH 10 RE-READS OR IF THE FORMAT
	   OF THE DATA IN EITHER BAT BLOCK IS INCORRECT
	4. BIT-13 OF DSW WILL BE SET TO A 1 IF BAT BLOCKS NON-EXISTANT

	NOTE - BOTH HEADERS AND DATA ARE READ INTO CORE 

	CALL SEQ:
	MOVE	1,ARG1		;Buffer addr
	MOVE	2,ARG2		;Bat block # (2 or 13)
	GO	RDBAT		;Call the routine
	RTN			;+1 Always with dsw(13) adjusted >

RDBAT:	PUT	NORET		;Save the no-retry flag state
	PUT	NORPT		;Save the no-report flag state
	PUT	X		;Save general index ac
	PUT	3		;And other ac's
	PUT	2
	PUT	1
	MOVEI	X,^D10		;Set up the retry count
RBA:	SETOM	NORET		;Flag says no normal retry
	SETOM	NORPT		;Flag says no error report
	SETZM	BSYCNT		;Init to no interrupts outstanding

	GO	.REQ		;Request the device
	MOVE	1,-1(P)		;Get block # to ac1
	GO	ADCON		;Convert to a disk address
	MOVEI	1,71		;Read data command
	HRLZ	3,CWRWD(X1)	;# Words for 1 sect xfer
	HRR	3,(P)		;Pick buffer addr from stack
	GO	XFSTRT		;Start the transfer
	GO	IOWAIT		;Wait,snapa,getlog,release .....

;Data now in core .. see how we did ..

	MOVE	1,R1D(DSW)	;Get status reg data
	TRNE	1,1B21		;Composite error ?
	JRST	RBDCT		;Yes. retryable error
CHCK:	MOVE	1,CONID(DSW)	;Get coni status
	TRNN	1,1B22		;Channel error ?
	JRST	CKFBAT		;No. check for validity
	JRST	RBDCT		;Yes. this is retryable

;Here's where we check for valid bat block format
;First word must be sixbit bat
;2Nd last word must be 606060
;Last word must have the correct logical block number (2 or 13)

CKFBAT:	MOVE	1,(P)		;Get buffer addr (build pointer
	GO	BATCHK		;Check for a valid bat block
	JRST	BBAT		;Bad
	JRST	GBAT		;Bat block looks ok

;Diddle the local retry counter and loop if possible

RBDCT:	SOJG	X,RBA		;Decrement and loop if x > 0
	TEXT	HDBAT		;Print bad news message
	MOVE	RGLIST,[400000,,700700] ;Select regs for printing
	GO	DUMPS		;Print registers
	GO	SNSDMP		;Print 'em
	MOVE	1,CONID(DSW)	;Get the coni data
	TRNE	1,20000		;Is there a channel error ?
	GO	LOGPNT		;Yes. print logout data

;Bat block invalid for some reason

BBAT:	TLO	DSW,(1B13)	;Set the bit in the status word

;Common exit code

GBAT:	GET	1		;Restore things
	GET	2
	GET	3
	GET	X
	GET	NORET
	GET	NORPT
	RTN			;And exit

	XLIST
	BOX <RDHOM -- READ SPECIFIED HOME BLOCK AND CHECK VALIDITY>,<
	THE FOLLOWING IS DONE:
	1. TURN OFF ERROR REPORTS, WE EXPECT ERRORS HERE.
	2. TURN OFF RETRY. THIS CODE DOES UP TO 10 RE-READS OF ITS OWN.
	3. HOME BLOCKS ARE CONSIDERED NON-EXISTANT IF ANY ERROR IS
	   NOT RECOVERABLE WITH 10 RE-READS OR IF THE FORMAT OF THE
	   DATA IN EITHER HOME BLOCK IS BAD.
	4. BIT-8 OF DSW WILL BE SET TO A 1 IF HOME BLOCKS NON-EXISTANT

	NOTE - BOTH HEADERS AND DATA ARE READ INTO CORE 

	CALL SEQ:
	MOVE	1,ARG1		;Buffer addr
	MOVE	2,ARG2		;Home block # (1 or 12 (octal))
	GO	RDHOM		;Call the routine
	RTN			;+1 Always with dsw(8) adjusted >

RDHOM:	PUT	NORET		;Save the no-retry flag state
	PUT	NORPT		;Save the no-report flag state
	PUT	X		;Save general index ac
	PUT	3		;And other ac's
	PUT	2
	PUT	1
	MOVEI	X,^D10		;Set up the retry count
RHM:	SETOM	NORET		;Flag says no normal retry
	SETOM	NORPT		;Flag says no error report
	SETZM	BSYCNT		;Init to no interrupts outstanding

	GO	.REQ		;Request the device
	MOVE	1,-1(P)		;Get the block #
	GO	ADCON		;Convert to a disk address
	MOVEI	1,71		;Read data command
	HRLZ	3,CWRWD(X1)	;# Words for 1 sect xfer
	HRR	3,(P)		;Pick buffer addr from stack
	GO	XFSTRT		;Start the xransfer
	GO	IOWAIT		;Wait,snapa,getlog,release .....

;Data now in core .. see how we did ..

	MOVE	1,R1D(DSW)	;Get status reg data
	TRNE	1,1B21		;Composite error ?
	JRST	RR%DCT		;Yes, do a re-read

CH%CK:	MOVE	1,CONID(DSW)	;Get coni status
	TRNN	1,1B22		;Channel error ?
	JRST	CKFHOM		;No. check for validity
	JRST	RR%DCT		;Yes. this is retryable

;Here's where we check for valid home block format
;First word must be sixbit hom
;2Nd last word must be 707070
;Last word must have the correct logical block number

CKFHOM:	MOVE	1,(P)		;Get buffer addr (build pointer)
	GO	HOMCHK		;Check for valid home block
	JRST	BHOM		;Bad
	JRST	GHOM		;Home block looks ok

;Diddle the local retry counter and loop if possible

RR%DCT:	SOJG	X,RHM		;Decrement and loop if x > 0
	TEXT	HDHOM		;Print bad news message
	MOVE	RGLIST,[400000,,700700] ;Select regs for printing
	GO	DUMPS		;Print registers
	GO	SNSDMP		;Print 'em
	MOVE	1,CONID(DSW)	;Get the coni data
	TRNE	1,20000		;Is there a channel error ?
	GO	LOGPNT		;Yes. print logout data

;Home block invalid for some reason

BHOM:	TLO	DSW,(1B14)	;Set the bit in the status word

;Common exit code

GHOM:	GET	1		;Restore things
	GET	2
	GET	3
	GET	X
	GET	NORET
	GET	NORPT
	RTN			;And exit

HDBAT:	ASCIZ/
CAN'T READ BAT BLOCK IN 10. TRIES
/

HDHOM:	ASCIZ/
CAN'T READ HOME BLOCK IN 10. TRIES
/

OPTH:	ASCIZ/
OPTION #1 - READ ANYWHERE ON MEDIA BUT WRITE ONLY TO MAINT AREA
OPTION #2 - ALL READS AND WRITES ARE DONE  WITHIN MAINT AREA
/

	XLIST
	BOX <INCRH - - ROUTINE TO INCREMENT MBCN PROPERLY>,<
	THIS ROUTINE INCREMENTS MBCN PROPERLY TO GET IT SET FOR THE NEXT
	CONTROLLER. IT IS NECESSARY BECAUSE OF THE STAGGERED RH DEVICE
	CODES THAT HAVE BEEN ASSIGNED. >
INCRH:	ADD	MBCN,[400,,0] ;Does it for rh20's
	RTN


	XLIST
	BOX <RNGCHK - - ROUTINE TO RANGE TEST RH DEVICE CODES >,<
	THIS ROUTINE TESTS THE LOW ORDER 9 BITS OF AC0 FOR A VALID RH
	DEVICE CODE AND BRANCHES ACCORDINGLY. THE NON SKIP RETURN IS 
	TAKEN EITHER IF THE DEVICE CODE IS ILLEGAL OR, THE SUBROUTINE
	PACKAGE FLAG "TTNBRF" INDICATES THAT THE USER HAS HIT THE 
	DELIMITING CHARACTER BEFORE ENTERING THE NUMBER. IN EITHER
	CASE, AC0 IS RETURNED UNMODIFIED. 

	CALLING SEQUENCE:
		GO	RNGCHK
		RTN-1		;Out of range
		RTN-2		;Ok >
RNGCHK:	SKIPN	TTNBRF		;Any digits input ?
	RTN			;No. error
	TRNE	0,3		;These bits must be zero
	RTN			;Error. there not
	CAML	0,LODEV		;Range test
	CAMLE	0,HIDEV
	RTN			;Out of range
	AOS	(P)		;Ok. bump the return
	RTN			;And exit

LODEV:	540
HIDEV:	574



	XLIST
	BOX	<DEVSEL - SELECT -- DEVICE SELECTION ROUTINES >,<
	THESE ROUTINES ALLOW FOR THE SELECTION OF THE NEXT AVAILABLE
	RH/DX/SPINDLE PAIR TO BE TESTED.

	THE ALGORITHIM INCREMENTS THROUGH DEVTBL/RHTBL PICKING THE NEXT 
	GROUP FOR TEST. THEY ARE SELECTED IN THE ORDER THEY WERE FOUND AT
	CONFIG TIME. THE SOFTWARE SUPPORTS UP TO 8 RH'S WITH A MAXIMUM OF
	1 DX20 PER RH AND 16 SPINDLES PER DX20.

	FOR A PAIR TO BE SELECTED BY THIS ROUTINE, WE MERELY HAVE TO HAVE
	RHTBL(10)=1 SAYING THE SPINDLE WAS SELECTED. THE DECISION OF WHETHER
	OR NOT THE RH/DX/SPINDLE GROUP IS STILL USEABLE IS MADE AT THE TEST 
	LEVEL BY STATCK.

	THE ROUTINES AND EXERCISES IN THE PROGRAM ALL CALL SELECT WITH THE
	EXCEPTION OF TOTALS AND TOTCLR WHICH CALL DEVSEL. THIS GIVES YOU THE
	ABILITY TO STILL FETCH AND CLEAR TOTALS FOR EACH OF THE ORIGINALLY 
	SELECTED DRIVES, EVEN IF ALL OF THE ORIGINALLY SELECTED DRIVES BECOME
	UNUSEABLE FOR SOME REASON.

	CALLING SEQ:
		GO DEVSEL (OR) SELECT	;Select next dev for test
		RTN1		;Tried all. first re-selected
		RTN2		;Next is selected. >

SELECT:	JUMPE	MBCN,.+3	;Jump if rh is not assigned
	CAMN	MBCN,DIAGCR	;Do we have rh ?
	GO	.REL		;Yes, release it
	GO	CHKTBL		;Check for a useable drive
	JRST	SEL0		;To common code

DEVSEL:	JUMPE	MBCN,.+3	;Jump if rh is not assigned
	CAMN	MBCN,DIAGCR	;Do we have rh ?
	GO	.REL		;Yes release it

SEL0:	PUT	1		;Save ac's
	PUT	2
	SKIPN	SELFLG		;Initializing ?
	JRST	SEL1		;No.
	SETZM	SELFLG		;Yes. clear the flag
	MOVE	1,TBWD		;-Cnt,,0
	SUBI	1,1		;Adjustment for initializing
	MOVEM	1,TBNDX		;Always holds current table index

SEL1:	MOVE	1,TBNDX		;Get current table index
	AOBJP	1,SELX		;Bump and jump if done

;Process entry pointed to pointed to by tbndx (now in ac1)

SEL2:	MOVEM	1,TBNDX		;Save current index
	MOVE	2,RHTBL(1)	;Get rhtbl entry
	TLNN	2,(1B10)	;Spindle selected ?
	JRST	SEL1		;No ... try for another
	AOS	-2(P)		;Yes. adjust for skip return
	MOVE	DSW,DEVTBL(1)	;Set up dsw for dswbrk routine
	GO	DSWBRK		;Ok. set up drive, mbcn and, x1
SELX:	GET	2		;Restore
	GET	1
	RTN			;And exit

;A cell that always points (in a sense) to the currently selected
;Rhtbl entry   -cnt,,offset  of current table entry

TBNDX:	Z			;Used by select, devsel, dxsel

	XLIST
	BOX <DXSEL -- SELECTION ROTUTINE USED WITHIN THE CONFIGURATOR>,<
	THIS ROUTINE IS USED BY RP2TST TO POLL FOR SPINDLES ON AN RH/DX
	PAIR. THIS ROUTINE SELECTS THE NEXT RH/DX PAIR (DIFFERENT FROM
	THE CURRENT ONE). THIS MEANS WE PASS OVER THE CONFIGURATION 
	TABLES IN JUMPS (OR GROUPS) OF HOWEVER MANY SLOTS ARE ASSIGNED
	TO AN RH/DX PAIR IN THE CONFIG TABLES.

	WE PICK RH/DX PAIR IFF: RHTBL(14,17)=1 AND RHTBL(12,15)=0
	WHICH MEANS RH/DX PAIR IS THERE AND NOT BROKEN ....

	YOU CAN SET SELFLG TO -1 TO START FROM BEGINNING AND LEAVE 
	ALONE TO PROCEED THROUGH THE REST OF THE TABLE ....
	CALLING SEQ:
	GO	DXSEL		;Select next rh/dx pair
	RTN1			;Tried all
	RTN2			;Next is selected. >

DXSEL:	PUT	1		;Save ac's
	PUT	2
	SKIPN	SELFLG		;Initializing ?
	JRST	DSEL1		;No.
	SETZM	SELFLG		;Yes. clear the flag

;Initialize our pointer to point one group of slots in front of
;The table so first adjustment takes us to start of the table

	MOVE	1,TBWD		;-Cnt,,0
	SUB	1,[DRMX,,DRMX]	;Adjustment for initializing
	MOVEM	1,TBNDX		;Always holds current table index

DSEL1:	MOVE	1,TBNDX		;Get current table index
	ADD	1,[DRMX,,DRMX]	;Bump both halves to next slot
	JUMPGE	1,DSELX		;Get out when left side goes positive

;Process entry pointed to pointed to by tbndx (now in ac1)

DSEL2:	MOVEM	1,TBNDX		;Save current index
	MOVE	2,RHTBL(1)	;Get rhtbl entry
	TLC	2,(1B14!1B17)	;Complement expected 1's bits
	TLNE	2,(1B12!1B14!1B15!1B17) ;Test.  status correct ?
	JRST	DSEL1		;No. adjust pointer for next rh/dx slot
	AOS	-2(P)		;Yes. adjust for skip return
	MOVE	DSW,DEVTBL(1)	;Det up dsw for dswbrk routine
	GO	DSWBRK		;Ok. set up drive, mbcn and, x1
DSELX:	GET	2		;Restore
	GET	1
	RTN			;And exit


	XLIST
	BOX <DSWBRK - BUILD DSW, MBCN, DRIVE, X1 FROM AN RHTBL/DEVTBL ENTRY>,<
	THIS ROUTINE EXPECTS TO FIND DSW SET UP WITH AN ENTRY FROM DEVTBL,
	IT WILL INTERN SET UP MBCN, DRIVE, X1 IN THE PROPER FORMATS FOR THE 
	REST OF THE PROGRAM.

	FORMATS:  
	--------

	DSW	CONTAINS AN IMAGE OF A PARTICULAR DEVTBL ENTRY FOR AN 
		RH/DX/SPINDLE GROUP. THE LEFT HALF IS FLAGS AND STATUS
		AND THE RIGHT HALF IS A POINTER TO THE SPINDLES DSB AREA.

	MBCN	CONTAINS THE MASSBUSS CONTROLLER DEVICE CODE IN BITS 3-9

	DRIVE	CONTAINS THE SPINDLE (SUBUNIT) NUMBER IN THE LEFT SIDE AND
		THE DX20 MASSBUSS DRIVE NUMBER IN THE RIGHT SIDE.

	X1	WILL CONTAIN EITHER A 6 OR 7 FOR THIS PROGRAM. THIS IS THE
		LOGICAL DEVICE TYPE AND IS USED FOR INDEXING INTO ALL OF THE
		VARIOUS PARAMETER TABLES IN THE PROGRAM. MOST OF THE TABLES
		ARE IN THE 'DISKS' MODULE.

	CALLING	SEQ:

	MOVE	DSW,ARG		;Get a devtbl entry to dsw
	GO	DSWBRK		;Call the routine
	RTN			;Returns here always >

DSWBRK:	PUT	0		;Save ac's
	PUT	1
	LDB	1,[POINT 8,DSW,7]	;Get index from dsw

;Set up x1 with logical device type

	LDB	X1,[POINT 4,RHTBL(1),21] ;Get from rhtbl(18-21)

;Set up drive with subunit # in left and dx20 # in right half

	LDB	DRIVE,[POINT 3,RHTBL(1),5] ;Dx# from rhtbl(3-5)
	LDB	0,[POINT 8,RHTBL(1),35]    ;Subunit from rhtbl(28-35)
	HRL	DRIVE,0		;Drive/ subunit#,,dx20#

;Build mbcn from the channel #

	LDB	MBCN,[POINT 3,RHTBL(1),2] ;Chan # from rhtbl(0-2)
	ROT	MBCN,^D-10	;Shift into position
	ADD	MBCN,[54000,,0] ;Now have an rh device code

	GET	1		;Restore ac's
	GET	0
	RTN			;Exit


	XLIST
	BOX <CHKTBL -- CHECKS CONFIG TABLE FOR AT LEAST 1 TESTABLE DRIVE>,<
	THIS ROUTINE SCANS THE CONFIG TABLES LOOKING FOR AT LEAST 1 RH/DX/DR
	COMBINATION THAT IS STILL USEABLE. THIS IS SO THE SECLECTION ROUTINE
	WON'T GET STUCK IN A LOOP LOOKING FOR A USEABLE DRIVE. IF NO USEABLE
	DEVICES ARE THERE, THE PROGRAM WILL GIVE THE APPROPRIATE MESSAGE AND
	WILL BE RESTARTED FROM "STARTQ" (QUICK START).

	CALL SEQ:
	GO	CHKTBL		;The call
	RTN			;+1 If a useable drive still exists

	FOR A USEABLE DRIVE TO EXIST, WE MUST HAVE:
		RHTBL (8,10,11,13,14,16,17) = 1
		RHTBL (9,12,15) = 0    AND   DEVTBL (15) = 1  >

CHKTBL:	PUT	0		;Save ac's
	PUT	1
	PUT	2
	MOVE	2,TBWD		;-Cnt,,0
CHKTB1:	MOVE	0,RHTBL(2)	;Get rhtbl entry 
	MOVE	1,DEVTBL(2)	;Get devtbl entry
	TLC	0,(1B8!1B10!1B11!1B13!1B14!1B16!1B17) ;Prepare for test
	TLNN	0,(1B8!1B9!1B10!1B11!1B12!1B13!1B14!1B15!1B16!1B17) ;Check
	TLNN	1,(1B15)	;The final test
	SKIPA			;Error
	JRST	CKTBX		;Good entry. exit

	AOBJN	2,CHKTB1	;Bump pointer. loop till done
	TEXTF	[ASCIZ/

*****************************
NO DEVICES AVAILABLE FOR TEST
*****************************

/]
	JRST	STARTQ		;And restart program

CKTBX:	GET	2		;Restore ac's
	GET	1
	GET	0
	RTN			;Exit


	XLIST
	BOX <CKTBDX -- CHECKS CONFIG TABLE FOR AT LEAST 1 TESTABLE RH/DX>,<
	THIS ROUTINE SCANS THE CONFIG TABLES LOOKING FOR AT LEAST 1 RH/DX
	COMBINATION THAT IS STILL USEABLE. THIS IS SO THE CONFIGURATOR ROUTINE
	WON'T GET STUCK IN A LOOP LOOKING FOR A USEABLE RH/DX. IF NO USEABLE
	DEVICES ARE THERE, THE PROGRAM WILL GIVE THE APPROPRIATE MESSAGE AND
	WILL BE RESTARTED FROM "STARTQ" (QUICK START).

	CALL SEQ:
	GO	CKTBDX		;The call
	RTN			;+1 If a useable drive still exists

	FOR A USEABLE RH/DX TO EXIST, WE MUST HAVE:
		RHTBL (14,17) = 1
		RHTBL (12,15) = 0   >

CKTBDX:	PUT	0		;Save ac's
	PUT	1
	PUT	2
	MOVE	2,TBWD		;-Cnt,,0
CHKDX1:	MOVE	0,RHTBL(2)	;Get rhtbl entry 
	MOVE	1,DEVTBL(2)	;Get devtbl entry
	TLC	0,(1B14!1B17) 	;Prepare for test
	TLNE	0,(1B12!1B14!1B15!1B17) ;Check
	SKIPA			;Error
	JRST	CKTDXX		;Good entry. exit

	AOBJN	2,CHKDX1	;Bump pointer. loop till done
	TEXTF	[ASCIZ?

*******************************
NO RH/DX20'S AVAILABLE FOR TEST
*******************************

?]
	JRST	STARTQ		;And restart program

CKTDXX:	GET	2		;Restore ac's
	GET	1
	GET	0
	RTN			;Exit


	XLIST
	BOX <CKTBSP -- CHECKS CONFIG TABLE FOR AT LEAST 1 TESTABLE SPINDLE>,<
	THIS SCANS THE CONFIG TABLES LOOKING FOR AT LEAST 1 RH/DX/SPINDLE
	COMBINATION THAT IS STILL USEABLE. IF NO USEABLE DEVICES ARE THERE,
	THE PROGRAM WILL GIVE THE APPROPRIATE MESSAGE AND WILL BE RESTARTED
	FROM "STARTQ" (QUICK START).

	CALL SEQ:
	GO	CKTBSP		;The call
	RTN			;+1 If a useable drive still exists

	FOR A USEABLE RH/DX/SPINDLE TO EXIST, WE MUST HAVE:
		RHTBL (11,14,17) = 1
		RHTBL (9,12,15) = 0   >

CKTBSP:	PUT	0		;Save ac's
	PUT	1
	PUT	2
	MOVE	2,TBWD		;-Cnt,,0
CHKSP1:	MOVE	0,RHTBL(2)	;Get rhtbl entry 
	MOVE	1,DEVTBL(2)	;Get devtbl entry
	TLC	0,(1B11!1B14!1B17) ;Prepare for test
	TLNE	0,(1B9!1B11!1B12!1B14!1B15!1B17) ;Check
	SKIPA			;Error
	JRST	CKTSPX		;Good entry. exit

	AOBJN	2,CHKSP1	;Bump pointer. loop till done
	TEXTF	[ASCIZ?

************************************
NO RH/DX/SPINDLES AVAILABLE FOR TEST
************************************

?]
	JRST	STARTQ		;And restart program

CKTSPX:	GET	2		;Restore ac's
	GET	1
	GET	0
	RTN			;Exit

	END