Google
 

Trailing-Edge - PDP-10 Archives - isi-saio_19830204 - isi-sa10/physa.mac
There are 2 other files named physa.mac in the archive. Click here to see a list.
;<ISI-SA10>PHYSA.MAC.5001	 3-Feb-83 14:37:06	Edit by ISI-SA10
;
;	Copyright 1982, All Rights Reserved
;	University of Southern California
;
;<5.ISI.MONITOR>PHYSA.MAC.5000	22-Oct-82 08:45:54	Edit by SMITH
;#500 CDSCCA dispatch added
;<4.ISI-MONITOR>PHYSA.MAC.260	31-Mar-81 13:08:50	Edit by SMITH
;#26 Support IBM-3420 compatable Tape drives on SA10 channel
;#25 Support IBM-3330 compatable disks on SA10 channel.
;#25 ;#26 Entire module included in these change #'S

	SEARCH PROLOG		;System parameter file
	TTITLE (PHYSA,,< - CHANNEL DEPENDENT CODE FOR SA10 CONTROLLER>)
	SUBTTL Dennis R. Smith 30-Nov-79

	SEARCH PHYPAR		;PHYSIO parameters

Comment	~
	
	This module contains  the code  to handle one  or more  SA10
	controllers.  It interfaces with PHYSIO, which calls it, and
	individual  device  modules,   which  it  calls   (currently
	supported: IBM 3330 style disks and IBM 3420 style  magnetic
	tapes).  SSAINI is intitially called by PHYSIO during system
	initialization through the  dispatch vector SSADSP.   SSAINI
	sets up CDB's for each subchannel  on each SA10 it finds  of
	those it is assembled to handle, and call each of the device
	initialization routines it  knows about  for every  possible
	unit on each subchannel  (except that channels having  disks
	are not  checked for  other devices).   SSASV is  a  routine
	called by the PI service  routine for the channel  'SSACHN'.
	It dispatches PHYSIO as though it were the routine put  into
	the CDB  by massbus  controller routines  to handle  massbus
	interrupts.

	The base addresses for the SA10s  reside on a page which  is
	not cached, and SSAINI sets  that. The device lists used  by
	the devices are  assumed to reside  on a page  which is  not
	cached, and it is up to the device routines to see that this
	is so.  It is also up to the device routines to assure  that
	any pages involved in I/O  have been flushed from cache,  or
	are not cached.

	~
	SUBTTL Parameters

; device dependent definitions in the CDB

SSACNI==CDBDDP+0		;CONI SSA,T1
SSACNO==CDBDDP+1		;CONO SSA,SA%CHn(T1)
;;	CDBDDP+2		; * UNUSED *
SSABAS==:CDBDDP+3		;address of base register for subchannel
SSASCI==:CDBDDP+4		;subchannel index (4*<SA10 #> + subchan)
SSASBA==:CDBDDP+5		;address of sense buffer for channel
SSADVL==:CDBDDP+6		;address of device list for channel (disk)
SSACUB==:CDBDDP+6		; current UDB that is active on this channel (tape)
L.SSA==CDBDDP+7-CDBINT		;length of SA10 CDB
	SUBTTL Channel Dispatch Table for SA10

SSADSP::JRST SSAINI		;0 - Initiation
	JRST SSASTK		;1 - Stack second channel command
	JRST SSASIO		;2 - Start I/O
	JRST SSAPOS		;3 - Position request
	JRST SSALTM		;4 - Return best xfer
	JRST SSAINT		;5 - Interrupt processing
	JRST SSACCW		;6 - Make channel xfer word
	JRST SSAHNG		;7 - Transfer hung
	JRST SSARST		;10 - Reset channel
	JRST SSACHK		;11 - Periodic check
	JRST EXTKDB		;12 - check legality of unit - use PHYSIO rtn.
	JRST SSACCA		;#500 13 - Extract address from CCW 

; Dummy routines

SSALTM:	RET
	SUBTTL Initialization

;SSAINI - initialize SA10 devices on system
; Called from PHYSIO via CDSINI entry in SSADSP.
; P4/ first free system channel #
;	CALL SSAINI	or	 CALL CDSINI(ac) ;where ac/ SSADSP
; RETURN +1: Always
;  P4/ next free system channel #
;   Other AC's not preserved.

SSAINI:
	MOVEI T1,SA0BAS/PGSIZ	;page uncacheable data is on
	CALL NOCASH##		;turn off caching on it
	MOVE T1,[SAXCDB,,SAXCDB+1]
	MOVE T2,SAXMSC		;get maximum subchannel number
	SETZM SAXSEL		;zero selector
	ADDI T2,SAXCDB		;point to last entry in table
	SETZM -1(T1)		;clear table of CDB for each subchannel
	BLT T1,0(T2)		;clear rest of table
	MOVEI P2,0		;start with CH0 on SA0
SSAIN1:
	MOVEI T1,SA%INI!SA%CME	;clear the channel
	XCT SAXCNO(P2)
	MOVEI T1,SSACHN		;assign PI but do not enable
	XCT SAXCNO(P2)
	XCT SAXCNI(P2)		;read it back
	TRNE T1,SA%PIA		;test for PI assignment
	CALL SSAINA		;SA10 exists: initialize it
	 MOVEI P2,SSANSC(P2)	;next SA10 (SSAIN2 always skips)
	CAMGE P2,SAXMSC		;done them all?
	JRST SSAIN1		;no, do next
	MOVE T1,[JRST SSASV2]	;interrupt entry for 2 SA10's
	SKIPE SAXCDB		;SA0 found?
	SKIPN SAXCDB+SSANSC	;and SA1 too?
	HRRI T1,SSASV1		;only 1 SA10, use simpler routine
	MOVEM T1,SSASV		;establish entry routine
	RET			;return to PHYSIO

SSAINA:				;initialize 1 SA10 per P2
	HRLI P2,-SSANSC		;counter for doing each subchannel
SSAIN2:	CAIG P4,CHNN		;do nothing if all channels in use
	CALL SSAINC		;initialize 1 subchannel
	AOBJN P2,SSAIN2		;do each subchannel
	MOVEI T1,SA%SET!FLD(.SAPIE,SA%FCN)!SSACHN ;enable PI interrupts
SSAIN5:	XCT SAXCNO-4(P2)	;enable PI interrupts on SA10 just processed
	ADDI T1,FLD(.SACH1,SA%CHN) ;next subchannel on that SA10
	JXN T1,SA%CHN,SSAIN5	;do next subchannel if any left
	RETSKP			;yes, skip the increment of P2
;SSAINC - Initialize one SA10 subchannel
; P2/ subchannel index (SA10#*NSSASC+Subchannel#)
; P4/ system channel #
;	CALL SSAINC		;called only from SSAIN2
; RETURNS +1: Always
;  P4/ next available system channel number
;  P1/ CDB if PHYALC didn't fail
;  Q1-Q3 may be destroyed


SSAINC:				;initialize one SA10 subchannel per P2
	MOVEI T1,L.SSA		;length of CDB
	CALL PHYALC		;allocate CDB
	 RET			;failure, quit
	HRRZ T3,P2		;get subchannel index
	ANDI T3,<SSANSC-1>	;isolate subchannel
	MOVEI P1,-CDBINT(T1)	;CDB base address to P1
	MOVEM P1,CHNTAB(P4)	;save cdb in channel table
	MOVEM P1,SAXCDB(P2)	;save cdb in SA10 subchannel table
	HRRZM P4,CDBADR(P1)	;store logical channel number
	HRRZM P2,SSASCI(P1)	;store subchannel index
	EXCH P1,P3		;get CDB in P3
	MOVEI T1,.BTCDB		;mark as CDB
	DPB T1,USYBKT		; ...
	EXCH P1,P3		;restore
	MOVEI T1,.CTSSA		;set type
	DPB T1,CSYTYP		; ...
	MOVEI T1,SSACHN		;SA10 PI channel
	DPB T1,CSYPIA		;set PIA in configuration information
	IOR T1,SAXCNO(P2)	;get CONO SAn,SSACHN
	STOR T3,SA%CHN,T1	;store subchannel number in it
	MOVEM T1,SSACNO(P1)	;store CONO in CDB
	MOVE T1,SAXCNI(P2)	;get CONI appropriate for this SA10
	MOVEM T1,SSACNI(P1)	;keep a copy handy in CDB
	MOVE T1,SAXBAS(P2)	;get base address for this subchannel
	MOVEM T1,SSABAS(P1)	;save base address in CDB
	DMOVE T1,[BLT 17,17	;get instruction to restore AC's
		SETOM SAXICH ]	;and one to show no interrupt in progress
	DMOVEM T1,CDBJEN(P1)	;and put them in CDB for PHYSIO exit sequence
	MOVE T1,[UNBRK SSA]	;instruction to return to PI5 routine
	MOVEM T1,CDBJEN+2(P1)	;put in exit sequence
	MOVEI T1,SSADSP		;insert address of dispatch vector
	MOVEM T1,CDBDSP(P1)	; into DCB
	MOVE Q3,[-MAXSAU,,CDBUDB] ;AOBJN pointer to UDB table
	ADDI Q3,(P1)		;relocate pointer
	MOVEM Q3,CDBCUN(P1)	;store in UDB as current pointer
	MOVEM Q3,CDBIUN(P1)	;store also as initial pointer
	SETOM CDBXFR(P1)	;indicate channel free   ???
	MOVEI Q2,0		;first unit #
SSAIN3:	CALL SSAINU		;initialize the unit
SSAIN4:	AOJ Q2,			;next device
	AOBJN Q3,SSAIN3		;keep going
	AOJA P4,R		;next system channel #, return

;SSAINU - Initialize unit
; P1/ CDB
; P3/ 0
; Q2/ unit number
; Q3/ location in CDB where UDB for this unit is to be stored
;	CALL SSAINU
; RETURNS +1: Always
;  P3/ UDB if unit responds to initialization

SSAINU:	MOVEI P3,0		;in case not wanted
	SKIPE T1,[CC1DSP]	;SA10 disks exist?
	CALL UDSINI(T1)		;yes, initialize
	JUMPN P3,SSANXU		;don't check for tape if disk was found
	SKIPE T1,[SATDSP]	;SA10 tapes exist?
	CALL UDSINI(T1)		;yes, initialize

SSANXU:	MOVEM P3,0(Q3)		;store in CDB if any (0 if none)
	RET
	SUBTTL Start I/O and Positioning

;SSAPOS - start positioning
; P1/ CDB
; P3/ UDB
; P4/ IORB
;	CALL CDSPOS(ac)		;where ac/ SSADSP
; RETURNS +1: failure
; RETURNS +2: success, positioning started

SSAPOS:	HRRZ T1,UDBDSP(P3)	;address of device routine vector
	CALLRET UDSPOS(T1)	;start positioning

;SSASIO - Start an I/O operation
; P1/ CDB
; P3/ UDB
; P4/ IORB
;	CALL CDSSIO(ac)		;where ac/ SSADSP
; RETURNS +1: failure
; RETURNS +2: success, I/O started

SSASIO:	HRRZ T1,UDBDSP(P3)	;get device routine vector
	CALL UDSSIO(T1)		;try to start I/O
	 RETBAD			;lost, do not skip
	RETSKP			;won

;SSASTK - stack a second command
; P1/ CDB
; P3/ UDB
; P4/ IORB
;	CALL CDSSTK(ac)		;where ac/ SSADSP
; RETURNS +1: failure
; RETURNS +2: success, command stacked

SSASTK:	HRRZ T1,UDBDSP(P3)	;get device dispatch
	CALLRET UDSSTK(T1)	;let him stack it if he can
	SUBTTL Hung, Reset, and Check entries

;SSAHNG - handle a hung transfer
; called with PI off
; P1/ CDB
; P3/ UDB
; P4/ IORB
;	CALL CDSHNG(ac)		;where ac/ SSADSP
; RETURNS +1: Always

SSAHNG:	RET			;do nothing

;SSARST - Reset the channel and all units
; T1/ 0 for reset just the channel (subchannel)
; T1/ 1 for full reset
; ( both resets currently the same for the SA10 )
; P1/ CDB
;	CALL CDSRST(ac)		;where ac/ SSADSP
; RETURNS +1: Always

SSARST:	MOVEI T1,SA%SET!FLD(.SARSC,SA%FCN)!SA%CME ;reset subchannel
	XCT SSACNO(P1)
	RET

;SSACHK - check PIA for SA10 (call about once a second)
; P1/ CDB
;	CALL CDSCHK(ac)		;where ac/ SSADSP
; RETURNS +1: Always

SSACHK:	XCT SSACNI(P1)		;do CONI
	ANDI T1,7		;isolate PIA
	LDB T2,CSYPIA		;get what PIA should be
	CAMN T1,T2		;are they the same?
	RET			;yes
	HRRZ T3,SSASCI(P1)	;no, get SubChannel Index
	BUG(SSAPIM,<<T3,CONI>>)	;<PHYSA - SA10 lost PI assignment>
	LDB T1,CSYPIA		;get correct PIA
	IORI T1,SA%SET!FLD(.SAPIE,SA%FCN) ;enable PI interrupts 
	XCT SAXCNO(T3)		;set the PIA
	RET
	SUBTTL CCW Generation entry

;SSACCW - generate a channel xfer word.
; This routine generates the second word of an SA10 CCW (IOW).
; T1/ mode,,+count (1B0 if backwards)
; T2/ Physical address
; P1/ CDB
; P3/ UDB
; P4/ IORB
;	CALL CDSCCW(ac)		;where ac/ SSADSP
; RETURNS +1: Always
;  T1/ CCW for this transfer
;[note: Transfer cannot cross page boundary ... that is caller's problem.]

SSACCW:	SKIPGE T1		;Read backwards?
	BUG(SSANRB,<<SSASCI(P1),SUBCHN>>) ;<PHYSA - read backwards not supported>
	HRRZ T3,T1		;get count
	HLRZS T1		;get mode in correct place
	TRZ T1,(1B0)		;clear backwards bit from mode
	CAIN T1,IRMWRD		;is it the common case (word mode)?
	JRST SSACW1		;yes, do it fast
	SKIPLE T1		;check for legal mode
	CAILE T1,IRMMAX		; ...
	JRST [	BUG(SSAIHM,<<T1,MODE>,<SSASCI(P1),SUBCHN>>) ;<PHYSA - Illegal HDW Mode - Word Mode Assumed>
		MOVEI T1,IRMWRD	;assume word mode
		JRST SSACW1]	;and continue as though nothing unusual
	IDIV T3,MODTAB(T1)	;convert to words
	SKIPE T4		;leftovers?
	AOS T3			;yes, need another word
SSACW1:	MOVX T1,SC%LST		;build CCW - indicate no chaining
	MOVNI T3,0(T3)		;get negative count
	STOR T3,SC%CNT,T1	;store count in CCW
	STOR T2,SC%ADR,T1	;store address in CCW
	MOVEM T1,CDBCCL(P1)	;store CCW
	RET			;return
;#500 SSACCA - EXTRACT THE PHYSICAL MEMORY ADDRESS FROM A CCW TRANSFER WORD.
;#500 ARGUMENT:
;#500   T1/	CCW WORD
;#500 RETURNS:
;#500   T1/	ADDRESS, OR ZERO IF NONE


SSACCA:	LOAD T1,SC%ADR,T1	;#500  Get Address from CCW
	RET			;#500 .
	SUBTTL Interrupt routine

;SSAINT - service interrupt on SA10 for subchannel
; P1/ CDB
;	CALL CDSINT(ac)		;where ac/ SSADSP
; RETURNS +1: Error detected
;  P4/ 0 : request PHYSIO to dismiss interrupt
;      negative : Request Schedule cycle
;      IORB : I/O completed on this IORB
;  P2-P3 not preserved
;  Q1-Q4 not preserved
; RETURNS +2: no error detected
;  P4/ 0 : request PHYSIO to dismiss interrupt
;      negative : Request Schedule cycle
;      IORB : I/O completed on this IORB
;  P2-P3 not preserved
;  Q1-Q4 not preserved

SSAINT:	SETZ P4,		;assume exit with no IORB
	XCT SSACNI(P1)		;get conditions on sa10
	MOVEM T1,CDBCNI(P1)	;save them
	TRNE T1,SA%MPE!SA%NXM	;fatal memory errors?
	JRST SSAMPE		;yes, handle them
	MOVE Q3,SSABAS(P1)	;get base register address
	DMOVE T1,1(Q3)		;get status words
	DMOVEM T1,CDBCS1(P1)	;save them in the CDB
	AOS T2,SAXTTP		;get Trace Table Pointer
	ANDI T2,SAXTTL-1	;wrap around
	MOVEM T1,SAXTT(T2)	;Store status word 1 in table
	LOAD T1,S1%DEV,1(Q3)	;get number of device causing interrupt
	MOVE Q2,T1		;copy address
	ANDI T1,<MAXSAU-1>	;convert to unit number
	CALL SETUDB		;set P3 := UDB, T2 := xxxDSP
	JUMPE P3,SSAONL		;unknown unit came on line
	CALL UDSINT(T2)		;call interrupt service
	 JFCL			;ERROR: special action necessary?
SSAINX:	MOVEI T1,FLD(.SASTS,SA%FCN) ;clear status of interrupting channel
	XCT SSACNO(P1)		;clear status
	SETOM SAXICH
	RETSKP			;good return

SSAMPE:				;process MPE's and Parity errors
	SETOM SAXICH		;show no subchannel being serviced
	MOVX T2,<-6,,0>		;read 6 SA10 registers (0-5)
	HRRZ T3,SSASCI(P1)	;get subchannel index
SSAMP1:	MOVEI T1,0(T2)		;register to read
	LSH T1,3		;shift register number to select position
	XCT SAXCNO(T3)		;select word desired
	MOVEI T1,SAXERD(T2)	;where to store this word
	XCT SAXDTI(T3)		;input word to buffer
	AOBJN T2,SSAMP1		;loop to get all registers
	MOVEI T1,SA%CME!SSACHN	;clear memory errors
	XCT SAXCNO(T3)		;clear memory errors
	MOVE T4,CDBCNI(P1)	;get conditions back
	TRNE T4,SA%NXM		;was it an NXM?
	JRST [	BUG(SSANXM,<<SAXERD,CHN/CBUS/uPC>,<SAXERD+1,MEMADR>,<SAXERD+2,MB.LH>,<SAXERD+3,MB.RH>>) ;<PHYSA - NXM detected by SA10>
		AOS CDBNXM(P1)	;count errors
		RETBAD ]	;return to PHYSIO
	HLRZ T1,SAXERD+2	;get channel pariter error happened on
	ANDI T1,3		;isolate subchannel number
	ADDI T3,(T1)		;create subchannel index
	MOVSI T1,(SIXBIT 'SSA')	;record who saw error
	MOVEM T1,DEVMPE		;save for JOB0
	AOS CDBPAR(P1)		;count errors
	RETBAD

SSAONL:				;interrupt from unknown unit
	MOVE T1,Q2		;get device address
	TRZ T1,<MAXSAU-1>	;remove unit code
	SETZ T2,		;don't know what type of unit
	CAIN T1,.IDDSK		;disk?
	MOVEI T2,CC1DSP		;yes
	CAIN T1,.IDMTA		;mag tape?
	MOVEI T2,SATDSP		;yes

	JUMPE T2,[BUG(SSAUKU,<<Q2,DEVADR>,<CDBCS1(P1),SW1>,<SSASCI(P1),SUBCHN>>) ;<PHYSA - Unknown unit interrupted>
		JRST SSAINX]	;dismiss interrupt
	CALL UDSINT(T2)		;call interrupt routine
	 BUG(SSAIIS,<<Q2,DEVADR>,<SSASCI(P1),SUBCHN>>) ;<PHYSA - Unit initialization failed>
	JUMPE P3,SSAINX		;quit if no UDB
	MOVEI Q3,CDBUDB(P1)	;get address of UDB list
	ADDI Q3,0(Q2)		;where to store UDB for this unit
	MOVEM P3,0(Q3)		;store UDB for unit
	JRST SSAINX		;dismiss interrupt
	SUBTTL Interrupt Service - called from PI service routine


; This routine is called by the PI service routine for "SSACHN".
; It has T1-T4 & CX available for scratch, and must save any
; other AC's it uses.  P is set to a ^O20 word stack, and a RET
; will return to process the next device on that channel.  The
; RET is used if the interrupt was not for the SA10.  Otherwise,
; return is via "UNBRK SSA".

; This routine will set up for a call to PHYSIO as though an
; interrupt came from an RH20 channel thru the interrupt code in
; a CDB.  PHYSIO will save all the AC's except for P1, which it
; expects in CDBSVQ, and the AC's will be restored in CDBJEN,
; thru which PHYSIO exits.

;;SSASV::	;SA10 PI interrupt service routine, JRST SSASV1 or SSASV2

SSASV2::			;interrupt routine if 2 SA10s
	MOVE T3,SAXSEL		;get last channel serviced
	TRC T3,SSANSC		;switch to other SA10
	XCT SAXCNI(T3)		;do a coni
	TXNN T1,SA%PIR		;interrupt request?
	JRST SSASV9		;yes, service it
				;no, try same channel as last time
SSASV1::			;interrupt routine if only one SA10 
	MOVE T3,SAXSEL		;get subchannel number
	XCT SAXCNI(T3)		;do a coni
	TXNN T1,SA%PIR		;interrupt request?
	RET			;no, return to PI routine


SSASV9:				;merging point of SSASV1,SSASV2
	MOVEM T3,SAXSEL		;remember channel serviced
	MOVE T4,T1		;save the status
	TRNE T1,SA%MPE!SA%NXM!FLD(.SACB0,SA%SFN) ;bad trouble or most likely channel?
	JRST SSASV4		;yes, go handle subchannel 0
	ANDI T1,<SA%SFN> ;mask off status flags untested
	JFFO T1,.+2		;find the first flag
	JRST [	BUG(SSANCI,<<T3,SA10IX>,<T4,CONI>>) ;<PHYSA - Interrupt but no channel flag>
		RET ]		;dismiss interrupt
	ADDI T3,-^L<SA%SFN>(T2) 	;compute subchannel index
SSASV4:	MOVEM T3,SAXICH		;remember where interrupt came from while
				; processing it (set to -1 on exit)
	SKIPN T2,SAXCDB(T3)	;get address of cdb for this channel 
	JRST [	BUG(SSAUKC,<<T3,SUBCHN>,<T4,CONI>>) ;<PHYSA - Interrupt from unknown channel>
		RET ]		;dismiss interrupt
	MOVEM P1,CDBSVQ(T2)	;save P1 where PHYSIO expects it
	MOVE P1,T2		;put CDB address in P1 for PHYSIO
	JRST PHYINT		;got to interrupt handler in PHYSIO
	SUBTTL SAINGO - Initialization routine to start I/O

;SAINGO - Routine to start I/O during initialization
; [Note: Caller must worry about caching of channel program and I/O area.]
; T1/ address of channel program 
; T2/ 0 = do reset (else don't)
; P1/ CDB
;	CALL SAINGO
; RETURNS +1: I/O unsuccessful
;  T1-T4 destroyed
; RETURNS +2: I/O successful
;  T1-T4 destroyed

SAINGO::SAVEQ			;save some AC's
	MOVE Q1,T1		;copy CP address
	TXO Q1,TCH		;create transfer program
	MOVE Q2,SSASCI(P1)	;get subchannel index
	MOVE Q3,SSABAS(P1)	;get base address
	JUMPN T2,SAING1		;Reset desired?
	MOVEI T1,SA%INI!SA%CME	;yes, reset SA10, clear errors
	XCT SSACNO(P1)		;do reset
	MOVEI T1,4000		; some delay for the SA10 and channel
	SOJG T1,.		;stall
SAING1:	MOVEI T3,4		;Try up to 4 times
SAING2:	SETOM 1(Q3)		;store phony status
	SETOM CDBCS1(P1)	;store phony status for caller
	MOVE T1,Q1		;get CP address
	CALL SSAGO		;start the I/O
	MOVEI T4,100000		;lots of time to find the device
SAING3:	XCT SSACNI(P1)		;get current conditions
	TRNE T1,SA%MPE!SA%NXM	;parity error or NXM?
	JRST [	BUG(SAIERR,<<T1,CONI>,<Q2,SUBCHN>>) ;<SAINGO - parity error or NXM>
		JRST SAING8]	;yes, return failure
	TDNN T1,BITS+^L<SA%SFN>(Q2) ;status flag present?
	SOJG T4,SAING3		;no, go look again
	JUMPLE T4,SAING9	;quit if it timed out
	DMOVE T1,1(Q3)		;get status words
	DMOVEM T1,CDBCS1(P1)	;save in CDB
	TXNE T1,FLD(.S1SER!.S1BIP!.S1CSE,S1%CHS) ;test for errors meaning "not found"
	JRST SAING8		;yes, indicate failure and quit
	TXNN T1,FLD(.S1BSY!.S1CUE,S1%DVS) ;Test for transient condition
	JRST SAING9		;no, done
	MOVEI T1,SA%CME!FLD(.SASTS,SA%FCN) ;yes, clear status and errors
	XCT SSACNO(P1)		;do clears
	SOJG T3,SAING2		;try again if haven't tried too much
SAING8:	SETZ T4,		;indicate failure
SAING9:	SETZM 0(Q3)		;clear channel dispatch
	MOVEI T1,SA%CME!FLD(.SASTS,SA%FCN) ;clear status and errors
	XCT SSACNO(P1)		;do clears
	JUMPG T4,RSKP		;good return
	RETBAD			;"not found" return
	SUBTTL SSAGO - Start I/O

;SSAGO - Start I/O on SA10 subchannel
; P1/ CDB
; T1/ TCH to Channel program, or Mux pointer
;	CALL SSAGO
; RETURNS +1: Always
;  T1 destroyed


SSAGO::	MOVEM T1,@SSABAS(P1)	;store pointer
	MOVEI T1,SA%SET!FLD(.SAGOF,SA%FCN) ;request channel to execute cmd
	XCT SSACNO(P1)		;go
	RET			;return
	SUBTTL SSAALC - Allocate space in uncached page

;SSAALC - Allocate uncached space
; T1/ number of words needed
; Returns +1: Failure - not enough space
; Returns +2: Success
;  T1/ Address of 1st word allocated

SSAALC::
	HRLI T1,(T1)		;copy amount wanted to LH
	ADD T1,SAXFRE		;calculate <-amt left>,,<new free>
	JUMPGE T1,R		;fail if negative count goes positive
	EXCH T1,SAXFRE		;set up new header, get address from old
	MOVEI T1,0(T1)		;address only
	RETSKP			;skip return for success
	TNXEND
	END