/*********************************************************
 ** BuildMMUConfig					**
 **							**
 ** Builds the MMU-Configuration file automatically	**
 ** from the boards information, including kludges for	**
 ** bad or mis-designed hardware			**
 ** Version 1.05 © 1999 THOR-Software, Thomas Richter   **
 ** 23.12.1999                                          **
 ** with special thanks to Tobias Abt and Niels Knoop	**
 ** for the Board Id's					**
 *********************************************************/
 
PARSE ARG destination .

	if (destination = '') then
		destination = '*'

	
	rec = 25;

	if (OPEN(.out,destination,'W')) THEN; DO
		rv=WRITELN(.out,";*************************************************************************");
		rv=WRITELN(.out,";** MMU Configuration file                                              **");
		rv=WRITELN(.out,";**                                                                     **");
		rv=WRITELN(.out,";** this file is read on startup by the mmu.library and used to modify  **");
		rv=WRITELN(.out,";** the pre-calculated or scanned MMU table                             **");
		rv=WRITELN(.out,";**                                                                     **");
		rv=WRITELN(.out,";** © 1999 THOR Software, Thomas Richter                                **");
		rv=WRITELN(.out,";*************************************************************************");
		rv=WRITELN(.out,"");
		rv=WRITELN(.out,"");
		rv=WRITELN(.out,"");
		rv=WRITELN(.out,"; the current version of the MMU library knows four commands that can");
		rv=WRITELN(.out,"; be used in this file:");
		rv=WRITELN(.out,"; CLEARTTX clears all or parts of the transparent translation registers");
		rv=WRITELN(.out,"; ADDMEM   adds memory to the exec free list pool. BE WARNED, this command");
		rv=WRITELN(.out,";          does NOT modify the MMU tables, this must be done manually with");
		rv=WRITELN(.out,";          SETCACHEMODE");
		rv=WRITELN(.out,"; SETCACHEMODE  defines the MMU tables.");
		rv=WRITELN(.out,"; DESCRIPTORCACHEINHIBIT defines whether the data cache should be disabled");
		rv=WRITELN(.out,"; for the MMU descriptors. It's usually OFF meaning the cache will remain");
		rv=WRITELN(.out,"; enabled. This is fine for the mmu.library, but certain hacks might require");
		rv=WRITELN(.out,"; an ON argument here. Note that this means more work for the library.");
		rv=WRITELN(.out,"");
		rv=WRITELN(.out,"");
		rv=WRITELN(.out,"ClearTTx        ;ignore all TTX registers if any. We don't need them");
		rv=WRITELN(.out,"");
		rv=WRITELN(.out,";DescriptorCacheInhibit ON	;make access to MMU descriptors cache inhibited");		
		rv=WRITELN(.out,"");
		rv=WRITELN(.out,"");
		rv=WRITELN(.out,";Board specific setup follows here,");
		rv=WRITELN(.out,";generated by BuildMMUConfig 1.05 © 1999 THOR-Software");
		rv=WRITELN(.out,"");

		rv=WRITELN(.out,";General memory setup follows.");
		rv=WRITELN(.out,";The following lines are a compatibility cludge for some P5 boards");
		rv=WRITELN(.out,";which enable the MMU prior to the 68040/68060 library and leave");
		rv=WRITELN(.out,";the memory in CACHEINHIBIT state. You may remove the following");
		rv=WRITELN(.out,";lines on all other machines most likely.");
		rv=WRITELN(.out,"");

		ADDRESS COMMAND "MemModes >T:MemInfo";
		IF (OPEN(.meminfo,"T:MemInfo",'R')) THEN; DO 
			DO UNTIL EOF(.meminfo)
				line = READLN(.meminfo);
				WRITELN(.out,line);
			END;
			rv=CLOSE(.meminfo);
		END;
		
		rv=WRITELN(.out,";Memory setup end.");
		rv=WRITELN(.out,"");
		rv=WRITELN(.out,"");

		ADDRESS COMMAND "ShowBoards to T:BoardInfo";
		IF (OPEN(.boardinfo,"T:BoardInfo",'R')) THEN; DO
			rec = 0;
			DO UNTIL EOF(.boardinfo)
				line = READLN(.boardinfo)
				IF line ~= '' THEN; DO
					PARSE VAR line 'Type:' type 'Product:' product 'Manufacturer:' mf 'Serial#:' id 'BoardAddr:' from 'BoardSize:' size;
					type=X2D(type);
					product=X2D(product);
					mf=X2D(mf);
					id=X2D(id);
					dfrom=X2D(from);
					dsize=X2D(size);
					from=STRIP(from);
					size=STRIP(size);
					rv=WRITELN(.out,";Setup for board "mf"/"product);
					rv=IdentifyBoard(type,product,mf,id,from,size,dfrom,dsize);
					rv=WRITELN(.out,"");	
				END
			END	
			rv=CLOSE(.boardinfo);
		END

		memfix = 0;
		ppcheck = 0;
		ADDRESS COMMAND 'P5Identify'
		p5mode = RC;
		ADDRESS COMMAND 'FindPort "BOOT-MMU-Port"'
		portmode = RC;
		ADDRESS COMMAND 'FindResident "ppc.library"'
		ppclibmode = RC;

		IF ppclibmode = 0 THEN; DO
			ppccheck = 1
		END;

		IF portmode = 0 THEN; DO
			ppccheck = 1
		END;

		IF p5mode ~= 0 THEN;DO
			WRITELN(.out,"");
			WRITELN(.out,";P5 fixes follow here:");
			WRITELN(.out,";If you do not own a P5 board, you may remove the following lines");
			WRITELN(.out,"");
		END;			


		IF ppclibmode = 0 THEN; DO
			WRITELN(.out,"");
			WRITELN(.out,";This board has a ppc.library resident. Node that the");
			WRITELN(.out,";mmu.library does NOT support the ppc.library and you");
			WRITELN(.out,";MUST NOT use it.");
			WRITELN(.out,"");
			SAY "Warning! The setup script found the ppc.library resident.";
			SAY "Note that the mmu.library does not support the ppc.library";
			SAY "and that this combination will not operate properly unless";
			SAY "you replace the ppc.library by WarpOs";
		END;

		IF portmode = 0 THEN;DO
			WRITELN(.out,"");
			WRITELN(.out,";Several P5 boards build a private MMU setup on boot");
			WRITELN(.out,";using a kludge called the BOOT-MMU-Port. To run this");
			WRITELN(.out,";kludge, the following external command is run from");
			WRITELN(.out,";LIBS:mmu/ as all other external commands");
			WRITELN(.out,"ScanMMUPort");
			IF ~EXISTS("LIBS:mmu") THEN; DO
				OPTIONS FAILAT 15
				ADDRESS COMMAND 'MakeDir >NIL: LIBS:MMU/'
				OPTIONS FAILAT 10
			END;
			IF ~EXISTS("LIBS:mmu/ScanMMUPort") THEN; DO
				ADDRESS COMMAND 'Copy >NIL: ScanMMUPort to LIBS:MMU/ScanMMUPort'
			END;
			WRITELN(.out,";SetCacheMode FROM 0xFFFF8000 SIZE 0x00008000 VALID CACHEINHIBIT");
			WRITELN(.out,"");
		END;

		IF p5mode = 1 THEN;DO
			rv=WRITELN(.out,"");
			rv=WRITELN(.out,";Several P5 boards need the following to be set:");
			rv=WRITELN(.out,"SetCacheMode FROM 0xfff00000 SIZE 0x00020000 VALID CACHEINHIBIT");
			rv=WRITELN(.out,"SetCacheMode FROM 0x00f00000 SIZE 0x00080000 VALID WRITETHROUGH");
			rv=WRITELN(.out,"");
		END;

		IF p5mode = 2 THEN; DO
			rv=WRITELN(.out,"");
			rv=WRITELN(.out,";CyberStorm PPC board memory setup follows here:");
			rv=WRITELN(.out,"SetCacheMode FROM 0xfff00000 SIZE 0x00080000 VALID CACHEINHIBIT");
			rv=WRITELN(.out,"SetCacheMode FROM 0x00f00000 SIZE 0x00050000 VALID CACHEINHIBIT");
			rv=WRITELN(.out,"SetCacheMode FROM 0x00f60000 SIZE 0x00020000 VALID CACHEINHIBIT");
			ppccheck = 1;
			memfix = 1;
		END;

		IF p5mode = 3 THEN; DO
			rv=WRITELN(.out,"");
			rv=WRITELN(.out,";CyberStorm MK3 board memory setup follows here:");
			rv=WRITELN(.out,"SetCacheMode FROM 0x00f00000 SIZE 0x00050000 VALID CACHEINHIBIT");
			rv=WRITELN(.out,"SetCacheMode FROM 0x00f60000 SIZE 0x00020000 VALID CACHEINHIBIT");
			ppccheck = 1;
			memfix = 1;
		END;

		IF p5mode = 4 THEN; DO
			rv=WRITELN(.out,"");
			rv=WRITELN(.out,";Blizzard PPC board memory setup follows here:");
			rv=WRITELN(.out,"SetCacheMode FROM 0xfff00000 SIZE 0x00080000 VALID CACHEINHIBIT");
			rv=WRITELN(.out,"SetCacheMode FROM 0x00f00000 SIZE 0x00080000 VALID CACHEINHIBIT");
			ppccheck = 1;
			memfix = 2;
		END;

		IF ppccheck = 1 THEN; DO
			ADDRESS COMMAND 'PPCIdentify'
			ppccheck = RC;
		END;

		IF ppccheck = 1 THEN; DO
			rv=WRITELN(.out,";More P5 PPC setups:");
			rv=WRITELN(.out,"SetCacheMode FROM 0xe0000000 SIZE 0x01000000 VALID CACHEINHIBIT IMPRECISE NONSERIAL");
			rv=WRITELN(.out,"SetCacheMode FROM 0xef000000 SIZE 0x00020000 VALID CACHEINHIBIT");
			rv=WRITELN(.out,"SetCacheMode FROM 0xfff80000 SIZE 0x00020000 VALID CACHEINHIBIT");
			rv=WRITELN(.out,"SetCacheMode FROM 0xfffc0000 SIZE 0x00040000 VALID CACHEINHIBIT");
		END;

		IF memfix ~= 0 THEN; DO
			rv=WRITELN(.out,"");
			rv=WRITELN(.out,";Even more P5 memory fixes. If the following memory is in your");
			rv=WRITELN(.out,";memory free list, this should be marked as cache-inhibited");
			rv=WRITELN(.out,";possibly because of bus logic problems. Note that setting the cache");
			rv=WRITELN(.out,";cache mode does not validate the access.");
			IF memfix = 1 THEN; DO
				rv=WRITELN(.out,"SETCACHEMODE FROM 0x08000000 SIZE 0x08000000 CACHEINHIBIT");
			END; 
			IF memfix = 2 THEN; DO
				rv=WRITELN(.out,"SETCACHEMODE FROM 0x40000000 SIZE 0x80000000 CACHEINHIBIT");
			END;
			rv=WRITELN(.out,"");
		END

		rv=WRITELN(.out,"");
		rv=CLOSE(.out);
		ADDRESS COMMAND 'Delete T:BoardInfo QUIET'
	END	

EXIT rec

IdentifyBoard:	PROCEDURE
PARSE ARG type,product,mf,id,xfrom,xsize,from,size

	IF BitExtract(type,5) = '1' THEN; DO
		rv=WRITELN(.out,";This board contains memory and requires no special threadment.");
		rv=WRITELN(.out,";In case accessing this memory with COPYBACK enabled causes crashes,");
		rv=WRITELN(.out,";please remove the semicolon in front of the next line:");
		rv=WRITELN(.out,";SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" CACHEINHIBIT NONSERIAL IMPRECISE");
		sp = 1;
	END; ELSE; DO
		z2 = 0
		z3 = 0
		if (from >= X2D('00200000')) & (from+size <= X2D('00A00000')) THEN; DO
			z2 = 1;
		END;
		if (from >= X2D('10000000')) & (from+size <= X2D('7FFFFFFF')) THEN; DO
			z3 = 1;
		END;
		IF (mf = 18260) & (product = 19) THEN; DO
			rv=WRITELN(.out,";Altais");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;
		IF (mf = 18260) & (product = 16) & z3 THEN; DO
			rv=WRITELN(.out,";Retina Z3");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'00c00000')" SIZE 0x00400000 CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;
		IF (mf = 2117) & (product = 3) THEN; DO
			rv=WRITELN(.out,";Merlin");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'00c00000')" SIZE 0x00200000 CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;			
		IF (mf = 2181) & (product = 0) & (size >= X2D('00100000')) & z2 THEN; DO
			rv=WRITELN(.out,";oMniBus");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'00c00000')" SIZE 0x00200000 CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;			
		IF (mf = 2092) & (product = 33) & z3 THEN; DO
			rv=WRITELN(.out,";Graffity Z3");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'00c00000')" SIZE 0x00200000 CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;
		IF (mf = 2092) & (product = 33) & z2 THEN; DO
			rv=WRITELN(.out,";Graffity Z2");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;		
		IF (mf = 2167) & (product = 1) & z2 THEN; DO
			rv=WRITELN(.out,";Domino");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;
		IF (mf = 2167) & (product = 11) THEN; DO
			rv=WRITELN(.out,";Picasso II");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;
		IF (mf = 2167) & (product >= 21) & (product <= 24) THEN; DO
			rv=WRITELN(.out,";Picasso IV");
			sp = 1;
		END;
		IF (mf = 2193) & (product = 1) THEN; DO
			rv=WRITELN(.out,";GVP Spectrum");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;
		IF (mf = 2195) & (product = 5) THEN; DO
			rv=WRITELN(.out,";Piccolo");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;
		IF (mf = 2195) & (product = 10) & z2 THEN; DO
			rv=WRITELN(.out,";Piccolo-SD64 Z2");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;
		IF (mf = 2195) & (product = 10) & z3 THEN; DO
			rv=WRITELN(.out,";Piccolo-SD64 Z3");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x00400000 VALID IOSPACE CACHEINHIBIT NONSERIAL IMPRECISE");
			sp = 1;
		END;
		IF (mf = 8512) & (product = 34) & z3 THEN; DO
			sp = 1;
			rv=WRITELN(.out,";CyberVision Z3");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" BLANK IOSPACE");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x01400000 VALID IOSPACE CACHEINHIBIT");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'01400000')" SIZE 0x00c00000 VALID IOSPACE CACHEINHIBIT NONSERIAL IMPRECISE");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'02000000')" SIZE 0x02000000 VALID IOSPACE CACHEINHIBIT");
		END;
		IF (mf = 8512) & (product = 67) THEN; DO
			sp = 1;
			rv=WRITELN(.out,";CyberVision3D");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" BLANK IOSPACE");
			IF Z2 THEN; DO
				rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x00380000 VALID IOSPACE CACHEINHIBIT NONSERIAL IMPRECISE");
				rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'00380000')" SIZE 0x00080000 VALID IOSPACE CACHEINHIBIT");
			END; ELSE; DO
				rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'04000000')" SIZE 0x01000000 VALID IOSPACE CACHEINHIBIT NONSERIAL IMPRECISE");
				rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'05000000')" SIZE 0x00010000 VALID IOSPACE CACHEINHIBIT");
				rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'05800000')" SIZE 0x00008000 VALID IOSPACE CACHEINHIBIT");
				rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'07000000')" SIZE 0x00008000 VALID IOSPACE CACHEINHIBIT");
				rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'08000000')" SIZE 0x00001000 VALID IOSPACE CACHEINHIBIT");
				rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'0C000000')" SIZE 0x00010000 VALID IOSPACE CACHEINHIBIT");
				rv=WRITELN(.out,"SetCacheMode FROM 0x"Add(xfrom,'0C0E0000')" SIZE 0x00001000 VALID IOSPACE CACHEINHIBIT");
			END
		END;	
		IF (mf = 2145) & (product = 33) THEN; DO
			sp = 1;
			rv=WRITELN(.out,";Rainbow 3");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" BLANK IOSPACE");
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x00400000 VALID IOSPACE CACHEINHIBIT");
		END;
		IF (mf = 8512) & (product = 100) THEN; DO
			sp = 1;
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" BLANK IOSPACE");
		END;
		IF (mf = 8512) & (product = 110) THEN; DO
			sp = 1;
			rv=WRITELN(.out,"SetCacheMode FROM 0x"xfrom" SIZE 0x"xsize" BLANK IOSPACE");
		END;
		IF (sp = 0) THEN; DO
			rv=WRITELN(.out,";no special care has been taken for this board.");
		END;
		
	END	

RETURN 0

;
; The AREXX BITTST function seems to be broken. We implement our own
;
BitExtract:	PROCEDURE
PARSE ARG num,bit
	bit=SUBSTR(C2B(D2C(num)),8-bit,1);
RETURN bit

;
; ARexx uses floating point addition and causes a mess about it when
; converting this back to integer. Therefore, we use another approach for
; adding numbers.
; Luckely, boards are aligned...
Add:		PROCEDURE
PARSE ARG base,offset
	offset = LEFT(offset,LENGTH(offset)-2)
	base   = LEFT(base,LENGTH(base)-2)
	base   = D2X(X2D(offset)+X2D(base))'00'
RETURN base

