Google
 

Trailing-Edge - PDP-10 Archives - bb-pbdea-bb - 10,7/unsmon/saxser.mac
There are 5 other files named saxser.mac in the archive. Click here to see a list.
TITLE	SAXSER - GENERAL SA10 SERVICE ROUTINES - V7
SUBTTL	JOSEPH A. DZIEDZIC/JAD (DEC) & JEFF GUNTER/JEG (ADP)	02-AUGUST-89


	SEARCH	F, S, DEVPRM, SAXPRM
	$RELOC
	$HIGH

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;  OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1987,1988.
;ALL RIGHTS RESERVED.

.CPYRT<1987,1988>

XP	VSAXSR,7		;VERSION NUMBER FOR GLOB AND MAP

SAXSER::ENTRY	SAXSER		;LOAD IN LIBRARY SEARCH MODE


SAXTBL==2*6			;ENTRIES IN SA10 DATA TABLES - ALLOW FOR
				; 2 SA10S PER EACH OF 6 CPUS

OP.NOP==3			;NO-OPERATION (NO-OP) OPERATION CODE
OP.SNS==4			;SENSE I/O OPERATION CODE
	SUBTTL	AUTOCONFIGURATION TABLES

	SUBTTL	DEFINITIONS

;DRIVER CHARARCTERISTICS
;	SAX	= SAXCNF
;	SAX	= SA10 IBM CHANNEL ADAPTER
;	SAXTBL	= MAXIMUM DEVICES IN SYSTEM
;	0	= KONTROLLER TYPE
;	0	= MAXIMUM DRIVES PER KONTROLLER
;	0	= HIGHEST DRIVE NUMBER ON KONTROLLER
;	MDSEC0	= SECTION FOR KDB/UDB
;	MDSEC0	= SECTION FOR DDB
DRVCHR	(SAX,SAX,SAXTBL,0,0,0,MDSEC0,MDSEC0,<DR.MCD!DR.UCK!DR.UCU>)

EQUATE	(LOCAL,0,<SAXUDB,SAXULN,SAXULP,SAXULB>)
EQUATE	(LOCAL,CPOPJ##,<SAXINI,SAXRLD,SAXEDL>)

SAXDSP::DRVDSP	(SAX,SAXCHN##,0,0,0)

;DEFAULT MONGEN'ED DEVICE TABLE

DEFMDT:	MDKL10	(7,274,0,0,<MD.KON>)	;SA10 DEVICE CODE 274
	MDKL10	(7,270,0,0,<MD.KON>)	;SA10 DEVICE CODE 270
	MDTERM				;TERMINATE TABLE

SAXCKT:	EXP	0			;COMPATIBLE KONTROLLER TABLE

	.ORG	KDBSIZ
				;*** DO NOT RE-ORDER THE FOLLOWING ***
SAXNCP:!BLOCK	2		;NO-OP CHANNEL PROGRAM
				;WORD 0: DVW
				;WORD 1: HLT
SAXSCP:!BLOCK	4		;SENSE CHANNEL PROGRAM
				;WORD 0: NO-OP
				;WORD 1: DVW
				;WORD 2: DCW
				;WORD 3: HLT
SAXSND:!BLOCK	SNSWDS		;SENSE DATA BUFFER
				;*** END OF DO NOT RE-ORDER ***
SAXCNI:!BLOCK	1		;CONI IN CASE DEVICE CODE ISN'T RH10
SAXSAV:!BLOCK	^D16		;DUMP SAVED COPY OF SA10 BASE AREA
SAXADR:!BLOCK	1		;ADDRESS OF BASE AREA FOR THIS SA10
SAXKLN:!
	.ORG

;PROTOTYPE KONTROLLER DATA BLOCK

SAXKDB:	KDBBEG	(SAX,SAXKLN)
	SETWRD	(KDBNAM,<SIXBIT /SAX/>)
	SETWRD	(SAXNCP,<F.NMT!F.XEC!F.SLI!<OP.NOP>B15>)
	SETWRD	(SAXSCP+SNSNOP,<F.NMT!F.XEC!F.SLI!F.CC!<OP.NOP>B15>)
	SETWRD	(SAXSCP+SNSDVW,<F.XEC!F.BYTE!<OP.SNS>B15<000>B23>)
	SETWRD	(SAXSCP+SNSDCW,<BYTE (1)1(DCSSIZ)-SNSBYT(DCSADR)SAXSND>)
	KDBEND
	SUBTTL	AUTOCONFIGURATION - PROTOTYPE INTERRUPT CODE

SAXICD:	PHASE	0		;AUTCON MUST FILL IN OFFSETS

;CONSO SKIP CHAIN CODE

	CONSO	000,SI.PIR	;(0) SA10 PI REQUEST?
	JRST	.		;(1) NOT FOR THIS DEVICE
	JSR	PIERR##		;(2) SAVE AC'S
SICDSC:!MOVEI	M,-1		;(3) LOAD GLOBAL SA10 SUBCHANNEL NUMBER OF S.C. ZERO
	SKIPA	W,.+1		;(4) LOAD KDB ADDRESS
	EXP	0		;(5) AUTCON FILLS IN KDB ADDRESS
	XJRST	.+1		;(6) DISPATCH TO INTERRUPT HANDLER
	EXP	SAXINT		;(7) INTERRUPT HANDLER ADDRESS

	DEPHASE
SAXICL==.-SAXICD		;LENGTH OF CONSO SKIP CHAIN CODE
	SUBTTL	AUTOCONFIGURE ENTRY POINT

;CALLED WITH DEVICE CODE/4 IN T1 AND CONI DEV, IN T2

SAXCFG:	TLNN	T2,(SI.SAX)	;IS THIS AN SA10?
	JRST	CPOPJ1##	;NO
	XMOVEI	T1,SAXMDT##	;MONGEN'ED DEVICE TABLE
	XMOVEI	T2,DEFMDT	;DEFAULT TABLE
	MOVSI	T3,-1		;MATCH ON ANY MASSBUS UNIT
	MOVEI	T4,MD.KON	;MATCH ON KONTROLLER DEFINITION
	PUSHJ	P,AUTMDT##	;SCAN THE TABLES
	  JRST	CPOPJ1##	;NO MATCHES
	MOVSI	T1,CP.SAX	;GET CHANNEL TYPE BITS FOR SA10
	PUSHJ	P,AUTCHN##	;BUILD A CHANNEL DATA BLOCK FOR THE SA10
	  POPJ	P,		;ERROR
	MOVNI	T1,1		;NO MASSBUS UNIT NUMBER INFO
	PUSHJ	P,AUTKDB##	;BUILD AND LINK A KONTROLLER DATA BLOCK
	  POPJ	P,		;ERROR, WOULD BE NICE TO DO SOMETHING ABOUT IT
	MOVE	T1,KDBCSO(W)	;GET ADDRESS OF CONSO SKIP CHAIN CODE
	HRRE	M,SICDSC(T1)	;GET GLOBAL SUBCHANNEL NUMBER FROM SKIP CHAIN CODE
	JUMPGE	M,SAXCF2	;GO IF THIS SA10 HAS ALREADY BEEN FOUND
	AOS	M,SAXNUM	;COUNT ANOTHER SA10 FOUND
	CAIL	M,SAXTBL	;FOUND TOO MANY?
	POPJ	P,		;YES, NOTHING WE CAN DO AT THIS POINT
	.CREF	SCHNUM		;CREF THE LSH
	LSH	M,2		;CONVERT TO GLOBAL SUBCHANNEL INDEX
	HRRM	M,SICDSC(T1)	;INSERT GLOBAL SA10 SUBCHANNEL NUMBER IN CODE
	ADDM	W,SAXSCP+SNSDCW(W) ;ADJUST SENSE BUFFER ADDRESS IN CHANNEL PROGRAM
	MOVEI	T4,0		;SUBCHANNEL ZERO IS AS GOOD AS ANY
	PUSHJ	P,SASTPX	;STOP ON SELECTED SUBCHANNEL
	MOVEI	T2,SA.BA1	;LOAD FIRST MICROINSTRUCTION
	PUSHJ	P,SAXCTX	;EXECUTE IT
	MOVEI	T2,SA.BA2	;LOAD SECOND MICROINSTRUCTION
	PUSHJ	P,SAXCTX	;EXECUTE IT
	MOVEI	T1,SO.DT1	;REGISTER TO READ
	XCT	KDBCNO(W)	;TELL THE SA10
	XCT	KDBDTI(W)	;READ BASE ADDRESS FOR SUBCHANNEL ZERO
	MOVEM	T2,SAXADR(W)	;SAVE SA10 BASE ADDRESS IN KDB FOR DUMP TIME
	MOVEI	T1,SO.CLK!SO.SET ;REQUEST TO TURN uPROC BACK ON
	XCT	KDBCNO(W)	;LEAVE THE SA10 RUNNING WHEN WE'RE DONE
	HRLI	M,-SCHNUM	;AOBJN POINTER TO FILL IN SUBCHANNEL ADDRESSES
SAXCF1:	HRRZM	T2,SAXSBA(M)	;STORE BASE ADDRESS OF SUBCHANNEL
	ADDI	T2,.CLLEN	;ADVANCE TO NEXT BASE AREA
	AOBJN	M,SAXCF1	;LOOP FOR ALL SUBCHANNELS
	SUBI	M,SCHNUM	;BACK DOWN TO GLOBAL SUBCHANNEL NUMBER
	PUSHJ	P,SAXNXM	;GO SEE IF THIS SA10 IS CONNECTED
	  PJRST	SAXRST		;RESET SA10 ON THE WAY OUT TO CLEAR INT REQ
	HRRZ	T1,SAXSBA(M)	;GET BASE ADDRESS OF SUBCHANNEL ZERO
	PUSHJ	P,SAXMBA	;MARK OFF THE BASE ADDRESSES
	  POPJ	P,		;ERROR
;NOW WE LOOP THROUGH ALL SA10 SUB-DRIVERS, CALLING THEM AT THEIR
;SA10-SPECIFIC AUTO-CONFIGURATION ENTRY POINT.  NOTE THAT THE
;"CFG" ENTRY WILL SIMPLY BE A JRST CPOPJ1##.

SAXCF2:	PUSHJ	P,SAVE4##	;FREE UP AN AC OR THREE
	PUSHJ	P,SAVR##	;THIS SEEMS USEFUL TOO
	PUSH	P,.CPDRV##	;SAVE OUR DISPATCH ADDRESS
	XMOVEI	P4,SAXSCP(W)	;POINT AT THE SENSE CHANNEL PROGRAM
	HRLI	M,-SCHNUM	;SET UP TO SCAN THROUGH SUBCHANNELS
SAXCF3:	MOVSI	P1,-MAXCUS	;SET UP TO SCAN THROUGH CONTROL UNITS
SAXCF4:	HRRZ	T1,P1		;GET HIGH 'MAXCUA' BITS OF CONTROL UNIT ADDRESS
	LSH	T1,WIDUNA	;POSITION IT
	DPB	T1,[POINT DVSDVA, SAXNCP(W), DVNDVA] ;STORE DEVICE ADDRESS
	DPB	T1,[POINT DVSDVA, SAXSCP+SNSNOP(W), DVNDVA] ; OF UNIT ZERO
	DPB	T1,[POINT DVSDVA, SAXSCP+SNSDVW(W), DVNDVA] ; ...
	XMOVEI	T1,SAXNCP(W)	;POINT AT THE NO-OP CHANNEL PROGRAM
	PUSHJ	P,SAXRCP	;RUN THE CHANNEL PROGRAM, WAIT FOR A RESPONSE
	  JRST	SAXCF7		;NO RESPONSE, MUST NOT BE A CONTROL UNIT THERE
	TLNE	T1,(S.SE)	;SELECT ERROR?
	JRST	SAXCF7		;YES, NO CONTROL UNIT EXISTS
	SKIPE	SAXDVP(M)	;HAS A DEVICE LIST ALREADY BEEN ALLOCATED?
	JRST	SAXCF5		;YES, SKIP THIS
	MOVE	T1,[CP.SAX,,400000] ;GET CHANNEL TYPE BITS AND "IGNORE DUPS" FLAG
	PUSHJ	P,AUTCHN##	;BUILD CHANNEL DATA BLOCK
	  POPJ	P,		;THAT'S ABOUT AS FAR AS WE CAN GO
	MOVE	T1,.CPCHA##	;GET CHANNEL DATA BLOCK ADDRESS
	MOVEM	T1,SAXCHA(M)	;STORE CHANNEL DATA BLOCK ADDRESS
	MOVEI	T1,DVLMAX+1	;GET SPACE FOR DEVICE LIST
	PUSHJ	P,SAXCOR	;ASK FOR IT
	  POPJ	P,		;ERROR
	MOVEM	T1,SAXDVP(M)	;SAVE PHYSICAL ADDRESS
	MOVEM	T2,SAXDVV(M)	;SAVE VIRTUAL ADDRESS
	TLO	T1,(BMXTIC)	;MAKE IT A BLOCK MUX TIC
	MOVEM	T1,@SAXSBA(M)	;SAVE IT AWAY
SAXCF5:	LDB	P2,[POINT 2,M,35] ;GET LOCAL SUBCHANNEL NUMBER
	MOVE	R,SAXLST	;GET FIRST ENTRY IN DRIVER LIST
SAXCF6:	TRNN	R,-1		;END OF LIST?
	JRST	SAXCF7		;YES
	MOVE	T1,SADDSP(R)	;GET THE REAL DRIVER DISPATCH
	MOVEM	T1,.CPDRV##	;SET IT UP
	PUSHJ	P,@SADCFS(R)	;CALL THE CONFIGURATION ROUTINE
				;M/ GLOBAL SA10 SUBCHANNEL NUMBER
				;P1/ JUNK,,DCU ADDRESS
				;P2/ SA10 SUBCHANNEL NUMBER
				;P3/ USABLE BY CALLEE
				;P4/ ADDRESS OF SENSE CHANNEL PROGRAM
	  JRST	SAXCF7		;NON-SKIP RETURN MEANS DRV CLAIMED THIS CU
	MOVE	R,SADLNK(R)	;GET LINK TO NEXT DRIVER
	JRST	SAXCF6		;LOOP

SAXCF7:	AOBJN	P1,SAXCF4	;LOOP FOR ALL POSSIBLE DCU ADDRESSES
	AOBJN	M,SAXCF3	;THEN LOOP FOR ALL SA10 SUBCHANNELS
	POP	P,.CPDRV##	;RESTORE DRIVER FOR AUTCON'S SAKE
	POPJ	P,		;RETURN WHEN DONE
;ROUTINE TO RUN A CHANNEL PROGRAM ON CHANNEL 0
;OF A NEWLY DISCOVERED SA10 TO MAKE SURE THAT THE SA10
;IS ACTUALLY ENABLED, AND IF NOT, TO RESET IT AND LEAVE IT ALONE

SAXNXM:	PUSHJ	P,SAXRST	;RESET ENTIRE SA10
	MOVEI	T1,SAXZRO	;POINT AT SIMPLE PROGRAM (ONLY A HALT)
	PUSHJ	P,SAXRCP	;RUN IT
	  JFCL			;EXPECT AN ERROR CUZ NO DEVICE
	XCT	.CPCNI##	;DO A CONI TO GET SA10 BITS
	TRNN	T1,SI.PAR!SI.NXM ;SKIP IF SOME SORT OF MEMORY ERROR
	AOS	(P)		;PASS BACK SKIP RETURN
	POPJ	P,		;PASS BACK THE ERROR
;ROUTINE TO RESET THE ENTIRE SA10

SAXRST:	MOVEI	T1,SO.RES	;RESET ENTIRE SA10 BIT
	XCT	.CPCNO##	;DO IT
	MOVSI	T1,7		;A LONG DELAY
	SOJG	T1,.		;WAIT TO LET CU'S SETTLE
	POPJ	P,		;RETURN
;ROUTINE TO SAVE SA10 INFO IN A DUMP

SAXDMP::PUSHJ	P,SAVT##	;SAVE SOME ACS
	MOVEI	T4,KDBTAB##+.TYSAX-KDBNXT ;POINT AT 1ST SA10 KDB
SAXDM1:	SKIPN	T4,KDBNXT(T4)	;STEP TO NEXT KDB
	POPJ	P,		;RETURN IF NO MORE SA10S
	XCT	KDBCNI(T4)	;GET SA10S CONI
	MOVEM	T1,SAXCNI(T4)	;SAVE THE VALUE
	MOVEI	T3,SAXSAV(T4)	;POINT AT SAVE AREA FOR BASE AREA
	HRLI	T3,-<SCHNUM*.CLLEN> ;COUNT FOR EVERY WORD OF BASE AREA
	MOVE	T2,SAXADR(T4)	;POINT AT PHYSICAL ADDRESS OF BASE AREA
SAXDM2:	PMOVE	T1,T2		;GET A WORD FROM BASE AREA
	MOVEM	T1,(T3)		;SAVE IT IN SAVE AREA
	ADDI	T2,1		;ADVANCE PHYSICAL ADDRESS
	AOBJN	T3,SAXDM2	;LOOP FOR EVERY WORD OF BASE AREA
	JRST	SAXDM1		;BRANCH BACK SO AS TO APPLY TO EVERY SA10
;ROUTINE TO READ DF10 IOWDS AND RETURN 2-WORD DESCRIPTORS
;
;ENTER:
;	P1/ POINTER TO DF10 PROGRAM
;EXIT:
;	P1/ UPDATED POINTER TO DF10 PROGRAM, FIRST UN-SEEN WORD
;	T1/ +VE COUNT
;	T2/ CORRECT 1ST WORD TO XFER

GETIOW::SETZB	T1,T2			;T1=ACCUMULATED COUNT,T2=1ST XFR ADDRESS
	PUSHJ	P,SAVR##		;R = POINTER TO END OF CONTIGUOUS AREA
GETIO1:	PUSHJ	P,GETIOX		;PICK UP T3=COUNT, T4=ADDRESS FROM (P1)
	  POPJ	P,			;EXIT IF WE FIND HALT
	DMOVE	T1,T3			;INIT T1=1ST COUNT, T2=1ST XFR ADR
GETIO2:	ADD	T4,T3			;COMPUTE 1ST WORD NOT XFER'ED
	MOVE	R,T4			;SAVE R=1ST WORD NOT XFER'ED
	ADDI	P1,1			;ADVANCE PC TO PEEK AT NEXT IOWD
	PUSHJ	P,GETIOX		;GET NEXT IOWD
	  POPJ	P,			;RETURN IF HALT, RE-FIND IT LATER
	CAME	T4,R			;SKIP IF IOWDS ACTUALLY CONTIGUOUS CORE
	POPJ	P,			;RETURN WITH DESCRIPTOR PAIR IN T1/T2
	ADD	T1,T3			;INCLUDE THIS IOWD'S COUNT
	JRST	GETIO2			;AND TRY ANOTHER
;ROUTINE TO FETCH NEXT DF10 IOWD
;
;	PUSHJ P,GETIOX
;	  HERE IF HALT, T3=0, T4=0
;	  HERE IF XFER, T3=COUNT, T4=ADDRESS
;	(BRANCHES HAPPEN INTERNALLY, AND UPDATE P1 AS NECESSARY)
GETIOX:	LDB	T3,[POINT 14,(P1),13]	;PICK UP COUNT FIELD FROM IOWD
	LDB	T4,[POINT 22,(P1),35]	;PICK UP ADDRESS FIELD FROM IOWD
	JUMPN	T3,GETIX1		;BRANCH IF COUNT#0, (MUST BE XFER)
	JUMPE	T4,CPOPJ##		;IF BOTH=0, MUST BE HALT, DO NOT SKIP
	HLRE	T3,LOWPTR##		;GET # OF MAPPING WORDS
	IMUL	T3,[-1*<^D36*4>]	;COMPUTE # OF WORDS IN LOCORE
	ADD	T3,LOWLOC##		;COMPUTE 1ST WORD ABOVE LOCORE AREA
	CAMGE	T4,T3			;SKIP IF ADR ABOVE LOCORE, MUST BE XFR
	JRST	[MOVE P1,T4		;UPDATE PC IF A BRANCH
		JRST GETIOX]		;AND CONTINUE SCAN FOR IOWD
	LDB	T3,[POINT 14,(P1),13]	;IF AN XFER, RELOAD COUNT
GETIX1:	TDO	T3,[777777,,740000]	;MAKE COUNT LOOK -VE
	MOVNS	T3			;CONVERT TO +VE COUNT
	AOJA	T4,CPOPJ1##		;EXIT WITH T3=COUNT, T4=TRUE ADDRESS
;ROUTINE TO ALLOCATE CONTIGUOUS NZS CORE AND RETURN IT'S PHYSICAL ADDRESS
;CALL:
;	MOVE	T1, SIZE OF CHUNK DESIRED
;	PUSHJ	P,SAXCOR
;	  <NON-SKIP>		;ERROR
;	<SKIP>			;T1 = 22-BIT PHYSICAL ADDRESS, T2 = VIRTUAL ADDRESS

SAXCOR::MOVE	T2,T1		;PUT IT WHERE ALLOCATOR WANTS IT
	PUSH	P,T1		;SAVE NUMBER OF WORDS DESIRED
IFN FTXMON,<			;IF NZS MONITOR
	MOVEI	T1,(MS.SAX)	;SPECIFY "SA10 GENERAL" FOR SECTION
	MOVEI	T3,GFWNZN##	;ADDRESS OF ROUTINE TO CALL DURING ONCE ONLY
	SKIPN	DINITF##	;SKIP IF ONCE ONLY IN PROGRESS
>;END IFN FTXMON
	MOVEI	T3,GETWDS##	;ROUTINE TO CALL DURING "TIME SHARING"
	PUSHJ	P,(T3)		;CALL THE ALLOCATOR
	  JRST	TPOPJ##		;OH DARN
	SETZM	(T1)		;CLEAR FIRST WORD
	MOVE	T2,T1		;COPY ADDRESS
	XMOVEI	T3,1(T1)	;SET UP TO CLEAR REMAINDER
	EXCH	T1,(P)		;SAVE ADDRESS, GET COUNT
	SUBI	T1,1		;NUMBER OF WORDS TO MOVE
	EXTEND	T1,[XBLT]	;ZERO THE CORE
	MOVE	T1,(P)		;GET VIRTUAL ADDRESS
	MAP	T1,(T1)		;TURN IT INTO PHYSICAL
	TLZ	T1,(MP.NAD)	;TURN OFF RANDOM BITS
	JRST	T2POJ1##	;POP VIRTUAL ADDRESS INTO T2 AND THEN RETURN
;ROUTINE TO ASSIGN DEVICE LIST SPACE TO A KONTROLLER.
;CALL:
;	M/ GLOBAL SA10 SUBCHANNEL NUMBER
;	P1/ JUNK,,DCU ADDRESS (HIGH 'WIDCUA' BITS)
;	T1/ NUMBER OF ENTRIES DESIRED
;	PUSHJ	P,SAXDVL
;	  <NON-SKIP>		;COULDN'T ASSIGN SUFFICIENT DEVICE LIST ENTRIES
;	<SKIP>			;SUCCESS, T1 = PHYSICAL ADDRESS OF FIRST ENTRY

SAXDVL::MOVE	T2,SAXDVP(M)	;GET ADDRESS OF DEVICE LIST FOR THIS SUBCHANNEL
	MOVSI	T4,-DVLMAX	;SET UP TO SCAN FOR FREE SLOTS IN DEVICE LIST
SAXDV1:	PMOVE	T3,T2		;GET THE ENTRY
	JUMPE	T3,SAXDV2	;JUMP IF THIS ENTRY IS FREE
	AOBJP	T4,CPOPJ##	;RETURN IF ENTIRE LIST IS FULL
	AOJA	T2,SAXDV1	;KEEP LOOKING

SAXDV2:	MOVEI	T3,DVLMAX	;SEE IF THERE IS ENOUGH SPACE FOR CALLER
	SUBI	T3,(T4)		;...
	CAILE	T1,(T3)		;...
	POPJ	P,		;NO, SORRY
	MOVN	T4,T1		;YES, SET UP AN AOBJN
	HRLZS	T4		;...
	MAP	T3,SAXZRO	;GET ADDRESS OF A NICE WORD OF ZEROES
	TLZ	T3,(MP.NAD)	;CLEAR NON-ADDRESS BITS
	DPB	P1,[POINT WIDCUA, T3, SANDLD-WIDUNA] ;STORE DEVICE ADDRESS OF
				; UNIT ZERO
	MOVEI	T1,DL.TRM	;GET "TERMINATED" CODE
	DPB	T1,[POINT SASDLO, T3, SANDLO] ;STORE IT
	MOVE	T1,T2		;SAVE START OF LIST FOR RETURN TO CALLER
SAXDV3:	PMOVEM	T3,T2		;INSERT THE ENTRY
	AOBJP	T4,CPOPJ1##	;RETURN WHEN ALL ENTRIES ARE INSERTED
	ADD	T3,[1B<SANDLD>]	;INCREMENT THE DEVICE ADDRESS
	AOJA	T2,SAXDV3	;BUMP DEVICE LIST ADDRESS AND LOOP
;SAXCTX EXECUTES AN SA10 MICROINSTRUCTION, ASSUMING THE CLOCK IS
; STOPPED ON THE DESIRED SA10 SUBCHANNEL.
;CALL:
;	T2/ MICROINSTRUCTION TO EXECUTE
;	T4/ DESIRED SUBCHANNEL NUMBER 
;	W/ KDB ADDRESS
;SASTPX STOPS THE SA10 CLOCK AT THE DESIRED SA10 SUBCHANNEL.
;CALL:
;	T4/ DESIRED SUBCHANNEL NUMBER 

SAXCTX:	XCT	KDBDTO(W)	;SEND THE DATA TO THE SA10
SASTPX:	MOVEI	T1,SO.CLK!SO.DT0 ;CLOCK CONTROL, SELECT REGISTER 0
	XCT	KDBCNO(W)	;STEP CLOCK
	XCT	KDBDTI(W)	;READ CONTENTS OF REGISTER 2
	HLRZS	T2		;ISOLATE THE SELECTED SUBCHANNL #
	CAIE	T2,(T4)		;SKIP IF CORRECT SUBCHANNEL SELECTED
	JRST	SASTPX		;NO, TRY AGAIN
	POPJ	P,		;RETURN
;ROUTINE TO MARK OFF THE I/O BLOCKS USED FOR THE LOGOUT AREA FOR EACH
;OF THE SA10'S SUBCHANNELS.
;CALL:
;	T1/ BASE ADDRESS OF SUBCHANNEL ZERO'S LOGOUT AREA
;	PUSHJ	P,SAXMBA
;	  <NON-SKIP>		;BASE ADDRESS ALREADY IN USE
;	<SKIP>			;BASE ADDRESS MARKED OFF
;MOSTLY SWIPED FROM MRKIOW IN SYSINI

SAXMBA:	PUSHJ	P,SAVE4##	;FREE UP ARGUMENT ACS FOR SETOS
	MOVE	P1,T1		;COPY BASE ADDRESS IN CASE DUPLICATE
	SUB	T1,LOWLOC##	;SUBTRACT BASE OF AREA
	LSH	T1,-2		;CONVERT TO BIT NUMBER
	IDIVI	T1,^D36		;GET WORD AND BIT IN TABLE
	MOVE	P4,T1		;COPY OFFSET TO BIT
	ADD	P4,LOWPTR##	;ADD IN BASE OF AOBJN POINTER TO TABLE
	MOVNS	T2		;GET -VE BIT NUMBER TO START WITH
	HRLI	P4,^D36(T2)	;BIT POSITION,,ADDRESS
	MOVEI	P3,SCHNUM	;GET NUMBER OF BLOCKS TO RETURN FOR SETOS
	PUSHJ	P,SETOS##	;MARK OFF THE BITS
	 STOPCD	CPOPJ##,DEBUG,SAXBAI,DIEBAI, ;++SA10 BASE ADDRESS IN USE
	MOVNI	T1,SCHNUM	;NUMBER OF BLOCKS WE APPROPRIATED
	ADDM	T1,NOIOWD##	;DECREMENT COUNT ACCORDINGLY
	JRST	CPOPJ1##	;SKIP RETURN

;HERE FROM ERRCON ON AN "SAXBAI" STOPCD

DIEBAI:	PUSHJ	P,INLMES##	;START THE NOISE
	ASCIZ	/SA10 base address /
	MOVE	T1,P1		;COPY BASE ADDRESS
	PUSHJ	P,PRTDI8##	;PRINT IT
	PJSP	T1,CONMES##	;MORE NOISE AND RETURN
	ASCIZ	/ already in use/
	SUBTTL	RUN SA10 CHANNEL PROGRAM AND WAIT FOR COMPLETION

;ROUTINE TO RUN AN SA10 CHANNEL PROGRAM AND WAIT FOR COMPLETION.
;ONLY INTENDED FOR USE DURING ONCE-ONLY OR DURING AUTO CONFIGURATION.
;CALL:
;	T1/ VIRTUAL ADDRESS OF CHANNEL PROGRAM
;	M/ GLOBAL SA10 SUBCHANNEL NUMBER
;	PUSHJ	P,SAXRCP
;	  <TIMEOUT RETURN>
;	<SOMETHING HAPPENED RETURN>	;T1/ CHANNEL STATUS WORD (.CLCSW)

SAXRCP::PUSHJ	P,SAVE1##	;FREE UP AN AC
	MAP	T1,(T1)		;MAKE ADDRESS PHYSICAL
	TLZ	T1,(MP.NAD)	;TURN OFF NON-ADDRESS BITS
	SETZ	P1,		;START AFRESH
	DPB	M,[POINT 2,P1,^L<SO.CHN>] ;STORE SUBCHANNEL IN POSITION FOR CONO
	PUSH	P,@SAXSBA(M)	;SAVE EXISTING POINTER
	TLO	T1,(TIC)	;MAKE A TIC TO THE CHANNEL PROGRAM
	MOVEM	T1,@SAXSBA(M)	;POINT BASE AREA AT CHANNEL PROGRAM
	MOVEI	T3,10		;NUMBER OF ATTEMPTS TO RUN THE CHANNEL PROGRAM
SAXRC1:	MOVEI	T1,SO.CLR!SO.STS(P1) ;CLEAR THE STATUS FLAG
	XCT	.CPCNO##
	MOVE	T1,SAXSBA(M)	;GET BASE ADDRESS OF SUBCHANNEL
	SETZM	.CLCSW(T1)	;CLEAR OLD STATUS
	MOVEI	T1,SO.SET!SO.GO(P1) ;SET THE GO FLAG
	XCT	.CPCNO##
	LDB	T1,[POINT 2,M,35] ;GET SA10 SUBCHANNEL NUMBER
	MOVNS	T1		;NEGATE IT
	MOVEI	T2,SI.STS	;BIT FOR CHANNEL ZERO'S STATUS FLAG
	LSH	T2,(T1)		;MAKE BIT FOR THIS CHANNEL'S STATUS FLAG
	MOVEI	T4,10000	;SET UP TIMEOUT
SAXRC2:	XCT	.CPCNI##	;GET THE STATUS
	TRNE	T1,SI.PAR!SI.NXM ;CHECK FOR CATASTROPHIC MEMORY ERROR
	JRST	SAXRC5		;BRANCH IF MEMORY ERRORS SEEN
	TRNN	T1,(T2)		;WAIT FOR STATUS FLAG TO COME UP
	SOJG	T4,SAXRC2	;WAIT UNTIL IT DOES
	JUMPLE	T4,SAXRC4	;GIVE UP IF IT TIMED OUT
	MOVE	T1,SAXSBA(M)	;GET BASE ADDRESS
	MOVE	T1,.CLCSW(T1)	;GET ENDING STATUS
	TLNE	T1,(S.BUSY)	;SKIP IF NOT BUSY
	JRST	SAXRC6		;BRANCH IF CU OR UNIT BUSY
	TLNE	T1,(S.SE!S.CTLE!S.CE!S.UC!S.UE) ;DID WE GET A REASONABLE
				; CHANNEL STATUS?
	JRST	SAXRC3		;YES
	SOJG	T3,SAXRC1	;NO, TRY AGAIN WHILE WE CAN
	JRST	SAXRC4		;COULDN'T RUN THE CHANNEL PROGRAM

SAXRC3:	AOS	-1(P)		;SET FOR SKIP RETURN
SAXRC4:	PUSH	P,T1		;SAVE CHANNEL STATUS FOR RETURN TO CALLER
	MOVEI	T1,SO.CLR!SO.STS(P1) ;CLEAR STATUS FLAG
	XCT	.CPCNO##
	MOVEI	T1,SO.CLR!SO.GO(P1) ;CLEAR GO FLAG
	XCT	.CPCNO##
	POP	P,T1		;RESTORE CHANNEL STATUS
	POP	P,@SAXSBA(M)	;RESTORE PROPER BASE POINTER
	POPJ	P,		;RETURN TO CALLER

SAXRC5:	MOVE	T1,SAXSBA(M)	;GET BASE ADDRESS
	MOVE	T1,.CLCSW(T1)	;GET CHANNEL STATUS FOR CALLER
	JRST	SAXRC4		;JOIN COMMON CODE

;HERE IF WE GOT BUSY
SAXRC6:	MOVSI	T4,1		;GET A LONG TIME OUT
	MOVEI	T1,SO.CLR!SO.STS(P1) ;CLEAR STATUS FLAG
	XCT	.CPCNO##	;...
SAXRC7:	IMULI	T1,1		;PAUSE BRIEFLY BETWEEN CONIS
	XCT	.CPCNI##	;WAIT FOR ANOTHER STATUS FLAG
	TRNN	T1,(T2)		;SKIP IF IT COMES UP AGAIN
	SOJG	T4,SAXRC7	;TRY AGAIN
	SOJG	T3,SAXRC1	;SET GO FLAG AGAIN IF WE GET ANY STATUS
	JRST	SAXRC4		;GIVE UP IF WE TIMED OUT
	SUBTTL	PROCESS SA10 INTERRUPT

;SA10 INTERRUPTS BRANCH HERE AFTER SAVING ACS.
;CALL:
;	M/ GLOBAL SA10 SUBCHANNEL NUMBER OF S.C. ZERO
;	W/ KDB ADDRESS

SAXINT:	XCT	KDBCNI(W)	;GET THE CONI BITS
	MOVE	T3,T1		;PASS THEM TO THE DRIVER IN T3

;FIRST CHECK FOR MEMORY ERROR WHICH MUST BE HANDLED HERE, AND
;THEN PASSED ALONG TO THE DRIVER WHICH CONTROLS THE SUBCHANNEL
;ON WHICH THE ERROR OCCURRED.

	TRNN	T1,SI.PAR!SI.NXM ;PARITY ERROR OR NXM?
	JRST	SAXNME		;NO
	MOVEI	T1,SO.CLK	;STOP SA10 CLOCK SO CAN READ ITS REGISTERS
	XCT	KDBCNO(W)
	MOVEI	T1,SO.SDR+SO.DT1 ;SELECT SA10 REGISTER 1 (MEMORY ADDRESS)
	XCT	KDBCNO(W)
	XCT	KDBDTI(W)	;READ MEMORY ADDRESS
	MOVE	T4,T2		;SAVE IT
	MOVEI	T1,SO.SDR+SO.DT2 ;SELECT SA10 REGISTER 2 (MEMORY USER,,XXX)
	XCT	KDBCNO(W)
	XCT	KDBDTI(W)	;READ MEMORY USER,,XXX (USER = SUBCHANNEL)
	HLRZS	T2		;MOVE SUBCHANNEL TO RH
	ADDI	M,(T2)		;M NOW CONTAINS GLOBAL SA10 SUBCHANNEL NUMBER
	MOVEI	T1,SO.CLK+SO.SET ;START THE CLOCK AGAIN
	XCT	KDBCNO(W)
	MOVEM	T4,SAMERR(M)	;SAVE MEMORY ADDRESS

	STOPCD	.+1,INFO,SAXMER, ;SA10 DETECTED MEMORY-PARITY OR NXM
	MOVE	T1,SAXCHA(M)	;GET ADDRESS OF CHANNEL DATA BLOCK FOR SUBCHANNEL
	PUSH	P,T3		;SAVE THE CONI STATUS BITS
	SKIPA	T1,CHNTBP(T1)	;GET AOBJN POINTER TO KDBS AND SKIP
SAXIN1:	MOVE	T3,(P)		;RESTORE STATUS BITS
	MOVE	W,(T1)		;GET THE KDB ADDRESS
	PUSH	P,T1		;SAVE THE AOBJN
	PUSHJ	P,SAXCTD	;CALL THE DRIVER
	POP	P,T1		;RESTORE AOBJN
	AOBJN	T1,SAXIN1	;LOOP FOR REMAINING KDBS
	ADJSP	P,-1		;CLEAN THE STACK
	PUSH	P,[1]		;PRETEND WE'VE SERVICED AT LEAST 1 KDB
	PJRST	SAXDU0		;SCAN FOR SOFTWARE INTERRUPT REQUESTS
;HERE WHEN NOT A MEMORY ERROR - SEE IF ANY SUBCHANNEL HAS ITS
;STATUS FLAG UP, AND DISPATCH TO THE APPROPRIATE DRIVER IF SO.
;CONI RESULTS STILL IN T1.

SAXNME:	ANDI	T1,SI.AST	;MASK OFF ALL STATUS FLAGS
	SKIPN	T1		;MAKE SURE SOMEONE INTERRUPTED!
	STOPCD	CPOPJ##,DEBUG,SAXNSI, ;++ NO STATUS ON INTERRUPT
	LSH	T1,^L<SI.STS>	;POSITION IN BITS 0-3
	JFFO	T1,.+1		;GET INTERRUPTING SUBCHANNEL NUMBER IN T2
	DPB	T2,[POINT 2,M,35] ;M NOW CONTAINS GLOBAL SA10 SUBCHANNEL NUMBER
	MOVE	T4,SAXSBA(M)	;GET GLOBAL SUBCHANNEL'S CHANNEL LOGOUT AREA
	LDB	T1,[POINT CSSTYP,.CLCSW(T4),CSNTYP] ;GET STATUS TYPE
	CAIN	T1,S.DUM	;SKIP IF NORMAL STATUS OF SOME SORT
	JRST	SAXDUM		;OOPS - OUR STATUS, SCAN FOR KDB
	LDB	T4,[POINT CSSKON,.CLCSW(T4),CSNKON] ;GET HIGH HEX DIGIT OF KON
	SKIPN	T1,SAXCHA(M)	;GET ADDRESS OF CHANNEL DATA BLOCK
	JSP	T1,SAXCSR	;CLEAR STATUS REQUEST AND DISMISS INTERRUPT
	MOVE	T1,CHNTBP(T1)	;GET AOBJN POINTER TO CHANNEL'S KDBS
SAXNM1:	MOVE	W,(T1)		;GET A KDB ADDRESS
	LDB	T2,[POINT WIDCUA,KDBUNI(W),17] ;GET THIS KON'S CU ADDRESS
	CAMN	T4,T2		;SKIP IF WE HAVEN'T FOUND KON YET
	JRST	SAXCTD		;YES
	AOBJN	T1,SAXNM1	;KEEP LOOKING
;	PJRST	SAXDUM		;FALL INTO SAXDUM

;HERE AT END OF SCAN TO FIND KDBS THAT WOULD LIKE A "REQUESTED" INTERRUPT
SAXDUM:	PUSH	P,[0]		;NOTE THAT 0 KDBS HAVE BEEN SERVICED
SAXDU0:	SKIPN	T1,SAXCHA(M)	;GET ADDRESS OF CHN FOR THIS SUBCHANNEL
	JSP	T1,SAXCSR	;CLEAR STATUS REQUEST AND DISMISS INTERRUPT
	MOVE	T1,CHNTBP(T1)	;GET AOBJN TO ALL THE KDBS FOR THAT CHN
SAXDU1:	MOVE	W,(T1)		;GET A KDB
	MOVE	T2,KDBSTS(W)	;GET RANDOM BITS
	TLZN	T2,(KD.SIR)	;SOFTWARE INTERRUPT REQUEST?
	JRST	SAXDU2		;NO
	MOVEM	T2,KDBSTS(W)	;YES, PUT BACK WITHOUT FLAG
	PUSH	P,T1		;SAVE AOBJN
	PUSHJ	P,SAXCTD	;GO HANDLE SOFT INTERRUPT REQUEST
	POP	P,T1		;RESTORE THE AOBJN
	AOS	(P)		;REMEMBER WE FOUND ONE
SAXDU2:	AOBJN	T1,SAXDU1	;LOOK AT NEXT ONE
	POP	P,T1		;GET THE SERVICE COUNT
	JUMPN	T1,CPOPJ##	;EXIT NOW IF SOMEONE GOT SERVICED
;*** IF THIS IS TRULY SPURIOUS, WE REALLY OUGHT TO CLEAR THE
;*** STATUS FLAG SINCE IT WILL PROBABLY CAUSE A PI LEVEL LOOP!
	JSP	T1,SAXCSR	;CLEAR STATUS REQUEST AND DISMISS INTERRUPT
;HERE TO CLEAR A STATUS REQUEST FOR A NON-EXISTANT CHANNEL (AT LEAST,
;IN OUR HUMBLE OPINION).
;CALL:
;	JSP	T1,SAXCSR
;NEVER RETURNS, DISMISSES INTERRUPT IN PROGRESS.

SAXCSR:	STOPCD	.+1,INFO,SAXISR,ISRDIE, ;++INVALID STATUS REQUEST
	XCT	KDBCNI(W)	;FETCH THE PI CHANNEL INFO
	ANDI	T1,SI.PIA	;ISOLATE PI CHANNEL
	DPB	M,[POINT 2,T1,^L<SO.CHN>] ;STORE SUBCHANNEL IN POSITION FOR CONO
	TRO	T1,SO.CLR!SO.STS ;STATUS-FLAG-CLR FUNCTION
	XCT	KDBCNO(W)	;CLEAR IT
	POPJ	P,		;DISMISS INTERRUPT

;HERE FROM ERRCON ON A SAXISR STOPCODE.

ISRDIE:	PUSH	P,T1		;SAVE THE PC FROM THE JSP
	PUSHJ	P,INLMES##	;ADD SOME NOISE
	ASCIZ	/Invalid SA10 status request from PC /
	POP	P,T1		;POP OFF THE PC
	HRRZS	T1		;DON'T WORRY ABOUT NZS PCS
	PUSHJ	P,OCTPNT##	;PRINT IT
	PUSHJ	P,INLMES##
	ASCIZ	/ for subchannel /
	LDB	T1,[POINT 2,M,35] ;GET SUBCHANNEL
	PJRST	PRTDI8##	;PRINT IT AND RETURN
;HERE TO CALL THE DRIVER ROUTINE
;CALL:
;	W/ KDB ADDRESS

SAXCTD:	MOVE	T1,KDBDSP(W)	;GET DISPATCH TABLE ADDRESS
	MOVE	T1,DRVINT(T1)	;GET ADDRESS OF INTERRUPT HANDLER
	TLNE	T1,MXSECN	;NZS ADDRESSING DRIVER?
	PUSHJ	P,SSEC1##	;YES, GET INTO SECTION 1
	JRST	@T1		;CALL THE ROUTINE AND RETURN
	SUBTTL	THE END

	$LOW

	.LNKEN	.LKSAX, SAXLST	;END OF DEVICE DRIVER LIST
SAXLST:	XWD	0,0		;DEVICE DRIVER LIST

SAXNUM:	EXP	-1		;SYSTEM-WIDE SA10 NUMBER

SAXZRO:	EXP	0		;A NICE WORD OF ZEROES IN THE LOW SEGMENT

;TABLES INDEXED BY GLOBAL SA10 SUBCHANNEL NUMBER

SAXCHA:	BLOCK	SAXTBL*SCHNUM	;ADDRESS OF CHANNEL DATA BLOCK
SAXDVP::BLOCK	SAXTBL*SCHNUM	;PHYSICAL ADDRESS OF DEVICE LIST
SAXDVV::BLOCK	SAXTBL*SCHNUM	;VIRTUAL ADDRESS OF DEVICE LIST
SAXSBA::BLOCK	SAXTBL*SCHNUM	;SUBCHANNEL BASE ADDRESS (LOGOUT AREA ADDRESS)
SAMERR::BLOCK	SAXTBL*SCHNUM	;SPACE FOR MEMORY ERROR WORD

	$HIGH
	$LIT

	END