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