Google
 

Trailing-Edge - PDP-10 Archives - BB-Y393M-SM - monitor-sources/swpalc.mac
There are 48 other files named swpalc.mac in the archive. Click here to see a list.
;Edit 3071 to SWPALC.MAC by LOMARTIRE on Mon 30-Jan-84, for SPR #18481
;		Prevent ASGSW2 BUGHLTs when swap space is exhausted
;<4-1-FIELD-IMAGE.MONITOR>SWPALC.MAC.2, 25-Feb-82 20:48:01, EDIT BY DONAHUE
;UPDATE COPYRIGHT DATE
;<4.MONITOR>SWPALC.MAC.3,  3-Jan-80 08:10:32, EDIT BY R.ACE
;UPDATE COPYRIGHT DATE
;<OSMAN.MON>SWPALC.MAC.1, 10-Sep-79 16:05:48, EDIT BY OSMAN
;TCO 4.2412 - Move definition of BUGHLTs, BUGCHKs, and BUGINFs to BUGS.MAC
;<4.MONITOR>SWPALC.MAC.1, 11-Mar-79 12:59:35, Edit by KONEN
;UPDATE COPYRIGHT FOR RELEASE 4


;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980,1981,1982 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	SEARCH PROLOG
	TTITLE(SWPALC,,< - SWAPPING SPACE ALLOCATION>)

;SWAP STORAGE ALLOCATOR

;THIS ALLOCATOR HANDLES A DEVICE OF SOME NUMBER (SWPSEC) OF SECTORS,
;AND SOME NUMBER (DRMMXB) OF TRACKS (BANDS). IT HAS A RESIDENT BIT TABLE,
;AND IS USED TO ALLOCATE SWAPPING STORAGE, EVEN IF THE PHYSICAL
;SWAPPING DEVICE IS THE SAME AS THE PHYSICAL FILE DEVICE

;PARAMETERS DRMSEC AND NTRK OF THE PHYSICAL DRUM ARE ALSO USED
;TO DETERMINE THE NUMBER OF PAGES ON THE ACTIVE PHYSICAL DRUMS

;** THE ACTUAL DRUM DRIVER IS ASSEMBLED AHEAD OF THIS ALLOCATOR **


;*** ALLOCATOR ***


EXTN <SWPSEC,DRMMXB,DRMBSZ,NPDRMS,MAXDRA,DRMBND,MDRMBD>
EXTN <DRMTPG,DRMBBT,DRMCNT,DRMBN0,DRMFRE>
EXTN <DRMSEC,NTRK,DRMINI>
;ASSIGN DRUM PAGE, FREE CHOICE
;	CALL DRMASN
; RETURN +1: DRUM FULL
; RETURN +2: PAGE ASSIGNED, A/ DRUM ADDRESS

DRMASN::SKIPG DRMFRE		;ANY SPACE ON DRUM?
	RET			;NO, FAIL
	SE1CAL
	MOVE A,DRMBN0		;GET LAST TRACK ASSIGNED
	SKIPE DRMCNT(A)		;ANY FREE ON THAT TRACK?
	JRST DRMAS3		;YES, GOOD ONE TO USE
	HRLZ A,MDRMBD		;NO, HAVE TO SEARCH. SETUP AOBJN PTR
	SKIPG DRMCNT(A)		;ANY FREE ON THIS TRACK?
	AOBJN A,.-1		;NO
	JUMPGE A,DRMBUG		;JUMP IF COULDN'T FIND ANY SPACE
DRMAS3:	MOVEI A,0(A)		;GET TRACK NUMBER
	MOVEM A,DRMBN0		;REMEMBER LAST TRACK ASSIGNED
	IMULI A,DRMBSZ		;COMPUTE INDEX TO BITS FOR THIS TRACK
	ADDI A,DRMBBT
	HRLI A,400002		;SET UP INDEX INDIRECT OF B
	MOVSI B,-DRMBSZ		;SETUP TO SCAN BIT WORDS
DRMAS2:	SKIPE C,@A		;GET BITS
	JFFO C,DRMAS1		;FREE BIT HERE?
	AOBJN B,DRMAS2		;NO, GO TO NEXT WORD
DRMBUG:	BUG(DRMIBT)

DRMAS1:	MOVE C,BITS(D)		;GET THE BIT JUST FOUND
	ANDCAM C,@A		;MAKE IT IN USE
	MOVEI B,0(B)		;GET WORD NUMBER WITHIN TRACK GROUP
	IMULI B,^D36		;COMPUTE SECTOR NUMBER JUST ASSIGNED
	ADDI B,0(D)
	MOVE A,DRMBN0		;RECOVER TRACK NUMBER
	SOS DRMCNT(A)		;UPDATE FREE COUNT OF TRACK
	SOS DRMFRE		;UPDATE FREE COUNT OF DRUM
	CALL DRMMKA		;MAKE DRUM ADDRESS FROM TRACK AND SECTOR
	RETSKP

;MAKE DRUM ADDRESS FROM TRACK AND SECTOR
; A/ TRACK NUMBER
; B/ SECTOR NUMBER
;	CALL DRMMKA
; RETURN +1: ALWAYS, A/ DRUM ADDRESS

DRMMKA:	IMULI A,SWPSEC		;COMPUTE LINEAR PAGE ADDRESS
	ADD A,B
	CAML A,MAXDRA		;ON OVERFLOW DEVICE?
	JRST [	SUB A,MAXDRA	;YES, FORM ADDRESS ON OVERFLOW DEVICE
	MOVE C,STRTAB	;POINT TO SDB FOR PUBLIC STRUCTURE
		MOVE C,SDBTYP(C) ;POINT TO SIZE DATA FOR THIS DISK TYPE
		IMUL A,SECPAG(C) ;CONVERT TO SECTORS
		TXO A,DRMOB	;INDICATE OVERFLOW
		JRST DRMMK1]
	IDIVI A,DRMSEC		;CONVERT TO PHYSICAL DRUM TRACK AND SECTOR
	STOR A,DRTRK,A		;CONSTRUCT ADDRESS
	STOR B,DRSEC,A
DRMMK1:	TXO A,DRMAB		;INDICATE SWAPPING ADDRESS
	RET
;ASSIGN SPECIFIC DRUM ADDRESS
; 1/ ADDRESS TO BE ASSIGNED
;	CALL DRMASA
; RETURN +1: FAILED, ADDRESS ILLEGAL OR ALREADY ASSIGNED
; RETURN +2: SUCCESSFUL

DRMASA::SE1CAL
	CALL DRMGTS		;GET TRACK AND SECTOR
	 JRST RFALSE		;ILLEGAL ADDRESS
	PUSH P,A		;SAVE TRACK
	IMULI A,DRMBSZ		;COMPUTE INDEX TO PROPER BIT WORD
	IDIVI B,^D36
	ADDI B,0(A)
	POP P,A			;RECOVER TRACK
	MOVE C,BITS(C)		;GET BIT FOR SECTOR
	TDNN C,DRMBBT(B)	;SECTOR NOW FREE?
	JRST RTRUE		;NO. FAIL
	ANDCAM C,DRMBBT(B)	;YES, MARK IT IN USE
	SOS DRMCNT(A)		;UPDATE TRACK FREE COUNT
	SOS DRMFRE		;UPDATE DRUM FREE COUNT
	RETSKP

;LOCAL ROUTINE TO GET TRACK AND SECTOR FROM DRUM ADDRESS
; 1/ DRUM ADDRESS
;	CALL DRMGTS
; RETURN +1: ILLEGAL ADDRESS
; RETURN +2: A/ TRACK NUMBER, B/ SECTOR NUMBER

DRMGTS:	TXZ A,-1B<POS(DRMOB)-1> ;EXTRACT ADDRESS BITS
	TXZE A,DRMOB		;OVERFLOW ADDRESS?
	JRST [	MOVE C,STRTAB	;YES. POINT TO SDB FOR PUBLIC STRUCTURE
		MOVE C,SDBTYP(C) ;POINT TO SIZE DATA FOR THIS DISK TYPE
		IDIV A,SECPAG(C) ;CONVERT TO LINEAR PAGE ADDRESS
		ADD A,MAXDRA	;SWP ADDR BASE FOR OVERFLOW DEVICE
		JRST DRMGT1]
	LOAD B,DRSEC,A		;GET SECTOR
	LOAD A,DRTRK,A		;GET TRACK
	IMULI A,DRMSEC		;COMPUTE LINEAR PAGE ADDRESS
	ADD A,B
DRMGT1:	IDIVI A,SWPSEC		;CONVERT TO TRACK AND SECTOR
	CAML A,DRMBND		;WITHIN RANGE?
	RET			;NO, FAIL
	RETSKP			;YES
;DEASSIGN DRUM ADDRESS
; 1/ DRUM ADDRESS
;	CALL DASDRM
; RETURN +1: ALWAYS (BUGCHK IF BAD OR UNASSIGNED ADDRESS)

DASDRM::SE1CAL
	CALL DEDRM		;DO THE WORK
	 BUG(ILDRA1)
	RET

;DEASSIGN DRUM ADDRESS
; 1/ DRUM ADDRESS
;	CALL DEDRM
; RETURN +1: BAD OR UNASSIGNED DRUM ADDRESS
; RETURN +2: SUCCESS, ADDRESS DEASSIGNED

DEDRM::	SE1CAL
	CALL DRMGTS		;GET TRACK AND SECTOR FROM ADDRESS
	 RET			;ILLEGAL ADDRESS, FAIL
	PUSH P,A		;SAVE TRACK
	IMULI A,DRMBSZ		;COMPUTE INDEX TO PROPER BIT WORD
	IDIVI B,^D36
	ADDI B,0(A)
	POP P,A			;RECOVER TRACK
	MOVE C,BITS(C)		;GET BIT FOR SECTOR
	TDNE C,DRMBBT(B)	;NOW ASSIGNED?
	RET			;NO, FAIL
	IORM C,DRMBBT(B)	;MARK IT FREE
	AOS DRMCNT(A)		;UPDATE TRACK FREE COUNT
	AOS DRMFRE		;UPDATE DRUM FREE COUNT
	RETSKP
;**;[3071]  Change lines at DEDRM:+20			DML	27-JAN-84
;ASSIGN MULTIPLE CONTIGUOUS DRUM ADDRESSES
; 1/ NUMBER OF CONTIGUOUS PAGES DESIRED
;	CALL DRMAM
; RETURN +1: FAILURE, DRUM IS FULL
;	 +2: SUCCESS, WITH:
;  A/ NUMBER OF CONTIGUOUS PAGES ACTUALLY FOUND
;  B/ ADDRESS OF FIRST OF GROUP OF CONTIGUOUS PAGES

;PAGES ARE NOT ACTUALLY ASSIGNED HERE, CALLER MUST ASSIGN PAGES
;INDIVIDUALLY AS THEY ARE SUBSEQUENTLY USED

;AC USAGE:
; Q1 - AOBJN PTR TO SCAN TRACKS
; Q2 - DESIRED N FROM CALLER
; Q3 - MAX CONTIGUOUS PAGES FOUND SO FAR
; P1 - TRACK,,SECTOR  OF FIRST PAGE OF BEST CONTIGUOUS GROUP

DRMAM::	SKIPG DRMFRE		;ANY SPACE ON DRUM?
	RET			;NO, FAIL
	SE1CAL
	PUSH P,Q1
	PUSH P,Q2
	PUSH P,Q3
	PUSH P,P1
	MOVEM A,Q2		;SAVE DESIRED COUNT
DRMAM6:	HRLZ Q1,MDRMBD		;SETUP TO SCAN TRACKS
	SETZ Q3,		;INIT MAX
DRMAM2:	CAMG Q2,DRMCNT(Q1)	;ENOUGH FREE PAGES THIS TRACK FOR REQUEST?
	JRST DRMAM3		;YES, GO CHECK IT
DRMAM4:	AOBJN Q1,DRMAM2		;LOOP OVER TRACKS
	JUMPG Q3,DRMAM5		;JUMP IF HAVE FOUND SOMETHING
	ASH Q2,-1		;FOUND NO TRACK WITH N, REDUCE N
	JUMPG Q2,DRMAM6		;TRY AGAIN UNLESS N NOW 0
	BUG(DRMNFR)

;HERE WHEN HAVE A TRACK WITH .GE. N FREE PAGES.  PAGES MAY OR MAY NOT
;BE CONTIGUOUS HOWEVER.

DRMAM3:	CALL DRMBG		;GET MAX CONTIGUOUS GROUP ON THIS TRACK
	CAMLE A,Q3		;BEST GROUP SO FAR?
	JRST [	MOVEM A,Q3	;YES, SAVE COUNT
		MOVEM B,P1	;SAVE SECTOR NUMBER
		HRLM Q1,P1	;SAVE TRACK NUMBER
		JRST .+1]
	CAMGE Q3,Q2		;ENOUGH TO SATISFY REQUEST?
	JRST DRMAM4		;NO, KEEP LOOKING
DRMAM5:	HLRZ A,P1		;GET TRACK
	HRRZ B,P1		;GET SECTOR
	CALL DRMMKA		;MAKE DRUM ADDRESS
	MOVE B,A		;RETURN IT IN B
	MOVE A,Q3		;GET COUNT TO RETURN
DRMAMX:	POP P,P1
	POP P,Q3
	POP P,Q2
	POP P,Q1
;**;[3071]  Change 1 line at DRMAMX:+4			DML	27-JAN-84
	RETSKP			;[3071] RETURN SUCCESS
;LOCAL ROUTINE TO FIND LARGEST CONTIGUOUS CLUSTER OF PAGES ON
;A TRACK.
; Q1/ TRACK NUMBER
;	CALL DRMBG
; RETURN +1: ALWAYS,
;  A/ MAX NUMBER OF CONTIGUOUS PAGES FOUND
;  B/ SECTOR NUMBER OF FIRST PAGES OF GROUP

;AC USAGE:
; A/ NUMBER OF BITS LEFT TO EXAMINE IN CURRENT WORD
; B/ CURRENT BIT WORD
; C/ RESULT OF JFFO
; D/ NUMBER OF CONTIGUOUS BITS FOUND IN THIS GROUP
; Q1/ AOBJN PTR TO LOOP THROUGH ALL BIT WORDS FOR THIS TRACK
; Q2/ LH: SECTOR NUMBER OF FIRST SECTOR OF BEST GROUP SEEN
;     RH: SECTOR NUMBER OF FIRST SECTOR OF CURRENT GROUP
; P1/ NUMBER OF CONTIGUOUS BITS IN BEST GROUP SEEN SO FAR

DRMBG:	PUSH P,Q1
	PUSH P,Q2
	PUSH P,P1
	MOVEI Q1,0(Q1)		;GET TRACK NUMBER
	IMULI Q1,DRMBSZ		;COMPUTE INDEX TO BITS WORDS FOR THIS TRK
	HRLI Q1,-DRMBSZ		;CONSTRUCT AOBJN PTR
	SETZB Q2,P1		;INIT MAX COUNT AND SECTOR NUMBER
	SETZ D,			;INIT CURRENT COUNT
DRMBG3:	MOVE B,DRMBBT(Q1)	;GET BIT WORD
	MOVEI A,^D36		;WE HAVE 36 BITS TO EXAMINE IN THIS WORD
DRMBG2:	SETCA B,		;COMPLEMENT SO JFFO WILL FIND 0'S
	JFFO B,.+2		;SKIP OVER 1'S TO FIND FIRST 0
	MOVEI C,0(A)		;NO 0'S, REST OF WORD IS 1'S
	ADD D,C			;ADD COUNT TO COUNT FROM PREVIOUS WORDS
	CAMLE D,P1		;MAX COUNT SEEN SO FAR?
	JRST [	MOVEM D,P1	;YES, REMEMBER IT
		HRLM Q2,Q2	;AND REMEMBER FIRST SECTOR NUMBER
		JRST .+1]
	SUB A,C			;REDUCE BIT COUNT BY BITS JUST PASSED
	JUMPLE A,DRMBG1		;JUMP IF NO MORE BITS IN THIS WORD
	SETCA B,		;GET TRUE WORD BACK
	LSH B,0(C)		;SHIFT OUT BITS JUST PASSED
	ADDM D,Q2		;UPDATE SECTOR NUMBER FOR BITS NOW PASSED
	SETZ D,			;SET NO BITS IN PREVIOUS WORD
	JFFO B,.+2		;SKIP 0'S TO FIND A 1
	MOVEI C,0(A)		;NO 1'S IN REST OF WORD
	SUB A,C			;REDUCE BIT COUNT BY BITS JUST PASSED
	ADDM C,Q2		;UPDATE SECTOR NUMBER FOR BITS JUST PASSED
	LSH B,0(C)		;SHIFT OUT 0'S JUST PASSED
	JUMPG A,DRMBG2		;JUMP IF MORE BITS IN THIS WORD
DRMBG1:	AOBJN Q1,DRMBG3		;LOOK AT ALL BIT WORD FOR THIS TRACK
DRMBG4:	MOVE A,P1		;GET MAX COUNT SEEN
	HLRZ B,Q2		;GET SECTOR NUMBER
	POP P,P1
	POP P,Q2
	POP P,Q1
	RET
;CONVERT DRUM ADDRESS INTO INDEX INTO DST

	INTERN GDSTX

; 2/ DRUM ADDRESS
;	CALL GDSTX
; RETURN +1: ALWAYS, 2/ DST INDEX

GDSTX:	TLNN 2,14		;INSIST ON REGULAR DRUM ADDRESS
	TLNN 2,2
	BUG(ILGDA1)
	TXZ 2,-1B<POS(DRMOB)-1> ;EXTRACT ADDRESS BITS
	TXZE 2,DRMOB		;AN OVERFLOW ADDRESS?
	JRST [	MOVE C,STRTAB	;YES. POINT TO SDB FOR PUBLIC STRUCTURE
		MOVE C,SDBTYP(C) ;POINT TO SIZE DATA FOR THIS DISK TYPE
		IDIV 2,SECPAG(C) ;CONVERT TO PAGE UNITS
		ADD 2,MAXDRA	;SWP ADDR BASE FOR OVERFLOW DEVICE
		JRST GDSTX1]
	LOAD C,DRSEC,B		;GET SECTOR
	LOAD B,DRTRK,B		;GET TRACK
	IMULI B,DRMSEC		;COMPUTE LINEAR PAGE ADDRESS
	ADD B,C
GDSTX1:	CAIL 2,NDST
	BUG(ILGDA2)
	RET

;INCREMENT DRUM ADDRESS - USED TO GET NEXT ADDRESS IN GROUP WHEN
;CONSTRUCTING MULTIPLE-PAGE SWAP
; 1/ DRUM ADDRESS
;	CALL DRMIAD
; RETURN +1: ALWAYS, A/ DRUM ADDRESS 1 PAGE BEYOND ARGUMENT

DRMIAD::SE1CAL
	CALL DRMGTS		;GET TRACK AND SECTOR
	 BUG(ILDRA2)
	ADDI B,1		;INCREMENT SECTOR
	CAIL B,SWPSEC		;BEYOND END OF TRACK?
	JRST [	SETZ B,		;YES, RESET TO SECTOR 0
		AOJA A,.+1]	;GO TO NEXT TRACK
	CALLRET DRMMKA		;RECONSTRUCT ADDRESS AND RETURN
;ROUTINE TO INITIALIZE BIT TABLE FOR A TRACK
; A/ TRACK NUMBER
;	CALL DRMTKI
; RETURNS +1: ALWAYS, ALL PAGES ON TRACK SET FREE

DRMTKI:	MOVEI B,SWPSEC		;INIT COUNT FOR TRACK
	MOVEM B,DRMCNT(A)
	IMULI A,DRMBSZ		;COMPUTE INDEX TO FIRST WORD OF BITS
	ADDI A,DRMBBT
	HRLI A,400002		;SET UP INDIRECT B
	MOVSI B,-DRMBSZ		;SETUP AOBJN PTR TO INIT ALL BIT WORDS
	SETOM @A		;SET ALL PAGES FREE IN THIS WORD
	AOBJN B,.-1
	MOVEI B,SWPSEC
	IDIVI B,^D36		;COMPUTE NUMBER BITS IN LAST WORD
	JUMPE C,R		;PERHAPS NONE
	MOVNI B,-1(C)		;SETUP TO CONSTRUCT BIT WORD
	MOVX C,1B0		;GET A BIT
	ASH C,0(B)		;REPLICATE IT
	MOVEI B,DRMBSZ-1	;MAKE PTR TO LAST BIT WORD
	MOVEM C,@A		;SET LAST (PARTIAL WORD
	RET

;ROUTINE TO ASSIGN ALL PAGES FOR A TRACK IN CASE TRACK BAD
; A/ TRACK NUMBER
;	CALL DRMTLK
; RETURN +1: ALWAYS, TRACK SET TO 0 FREE

DRMTLK:	SETZM DRMCNT(A)		;SET COUNT TO 0
	IMULI A,DRMBSZ		;GET PTR TO FIRST WORD OF BITS
	ADDI A,DRMBBT
	HRLI A,400002		;SET UP FOR @A
	MOVSI B,-DRMBSZ		;SETUP TO REF ALL BIT WORDS
	SETZM @A		;CLEAR ALL BITS
	AOBJN B,.-1
	RET
;INITIALIZE DRUM BIT TABLES

SWPINI::SETZM NPDRMS		;DECLARE 0 PHYSICAL UNLESS DRMINI CHANGES
	CALL DRMINI		;INIT DEVICE DRIVER, COUNT PHYSICAL UNITS
	MOVE A,NPDRMS		;GET NUMBER OF PHYSICAL UNITS
	IMULI A,NTRK*DRMSEC	;COMPUTE NUMBER OF PAGES OF PHYS UNITS
	MOVEM A,MAXDRA		;IT MARKS BOUNDARY BETWEEN DRUM AND DISK SWAP
	CALL DRMISP		;INIT STORAGE PARAMETERS
	HRLZ D,MDRMBD		;SETUP TO INIT ALL TRACKS
	MOVEI A,0(D)		;GET TRACK NUMBER
	CALL DRMTKI		;INIT THE TRACK
	AOBJN D,.-2
	MOVE A,DRMTPG		;GET TOTAL NUMBER PAGES ON DRUM
	CAILE A,NDST		;CHECK AGAINST DST
	BUG(DST2SM)
	MOVEM A,DRMFRE
	CALL SETSSP		;SETUP LIMITS BASED ON DRUM SPACE
	SKIPG DRUMP		;REAL DRUM ON SYSTEM?
	RET			;NO, DON'T ASSIGN RESERVED ADDRESSES
	PUSH P,Q1
	MOVSI Q1,-NDRMBA	;SETUP TO ASSIGN BAD ADDRESSES
DRMIN2:	MOVE A,DRMBAT(Q1)	;GET A BAD ADDRESS
	JUMPL A,DRMIN1		;JUMP IF END OF LIST
	CALL DRMASA		;ASSIGN THE ADDRESS
	 BUG(ASGSWB)
	AOBJN Q1,DRMIN2
DRMIN1:	POP P,Q1
	RET

;SETUP SWAP STRUCTURE PARAMETERS BASED ON NDST

DRMISP:	MOVEI A,NDST		;GET MAX NUMBER PAGES FOR SWAPPING
	MOVE B,NSSUN		;GET # OF DISK SECTORS RESERVED
	MOVE C,STRTAB		;POINT TO SDB FOR PUBLIC STRUCTURE
	MOVE D,SDBTYP(C)	;POINT TO SIZE DATA FOR THIS DISK TYPE
	IDIV B,SECPAG(D)	;CONVERT NUMBER SWAP SECTORS TO PAGES
	MOVE C,STRTAB		;POINT TO SDB FOR PUBLIC STRUCTURE
	IMUL B,SDBNUM(C)	;GET TOTAL DSK PAGES RESERVED
	ADD B,MAXDRA		;ADD DRUM PAGES AVAILABLE
	CAMLE A,B		;GET MINIMUM AMOUNT
	MOVE A,B		;LIMITED TO SPACE RESERVED ON DISK & DRUM
	MOVEM A,DRMTPG		;SAVE TOTAL DRUM PAGES
	IDIVI A,SWPSEC		;COMPUTE TOTAL NUMBER TRACKS
	MOVEM A,DRMBND
	MOVNM A,MDRMBD		;KEEP NEGATIVE ALSO FOR CONVENIENCE
	RET

;BAD AND RESERVED ADDRESS TABLE

DRMBAT:	-1			;MARK END OF LIST
	BLOCK 6			;PATCH SPACE FOR ADDITIONAL BAD ADRS
NDRMBA==.-DRMBAT

	TNXEND			;BUGSTRINGS, ETC.
	END