unit Expansion;

INTERFACE
uses Exec, AmigaDOS;


type
	pConfigDev = ^tConfigDev;
	pCurrentBinding = ^tCurrentBinding;
	tCurrentBinding = record
		cb_ConfigDev: pConfigDev;
		cb_FileName: pbyte;
		cb_ProductString: pbyte;
		cb_ToolTypes: ppbyte;
		end;

	pExpansionBase = ^tExpansionBase;
	tExpansionBase = record
		LibNode: tLibrary;
		Flags: byte;
		eb_Private01: byte;
		eb_Private02: long;
		eb_Private03: long;
		eb_Private04: tCurrentBinding;
		eb_Private05: tList;
		MountList: tList;
		end;

	pExpansionRom = ^tExpansionRom;
	tExpansionRom = record
		er_Type: byte;
		er_Product: byte;
		er_Flags: byte;
		er_Reserved03: byte;
		er_Manufacturer: word;
		er_SerialNumber: long;
		er_InitDiagVec: word;
		er_Reserved0c: byte;
		er_Reserved0d: byte;
		er_Reserved0e: byte;
		er_Reserved0f: byte;
		end;

	pDiagArea = ^tDiagArea;
	tDiagArea = record
		da_Config: byte;
		da_Flags: byte;
		da_Size: word;
		da_DiagPoint: word;
		da_BootPoint: word;
		da_Name: word;
		da_Reserved01: word;
		da_Reserved02: word;
		end;

	pExpansionControl = ^tExpansionControl;
	tExpansionControl = record
		ec_Interrupt: byte;
		ec_Z3_HighBase: byte;
		ec_BaseAddress: byte;
		ec_Shutup: byte;
		ec_Reserved14: byte;
		ec_Reserved15: byte;
		ec_Reserved16: byte;
		ec_Reserved17: byte;
		ec_Reserved18: byte;
		ec_Reserved19: byte;
		ec_Reserved1a: byte;
		ec_Reserved1b: byte;
		ec_Reserved1c: byte;
		ec_Reserved1d: byte;
		ec_Reserved1e: byte;
		ec_Reserved1f: byte;
		end;

	tConfigDev = record
		cd_Node: tNode;
		cd_Flags: byte;
		cd_Pad: byte;
		cd_Rom: tExpansionRom;
		cd_BoardAddr: pointer;
		cd_BoardSize: long;
		cd_SlotAddr: word;
		cd_SlotSize: word;
		cd_Driver: pointer;
		cd_NextCD: pConfigDev;
		cd_Unused: array [0..3] of long;
		end;

	pBootNode = ^tBootNode;
	tBootNode = record
		bn_Node: tNode;
		bn_Flags: word;
		bn_DeviceNode: pointer;
		end;



var
	ExpansionBase: pExpansionBase;


const
	ECIF_INTERRUPTING = $80;
	EBB_DOSFLAG = 3;
	ERFF_ZORRO_III = $10;
	DAC_BUSWIDTH = $C0;
	EBF_DOSFLAG = 8;
	ECIB_INTENA = 1;
	DAC_NIBBLEWIDE = 0;
	EBB_SHORTMEM = 1;
	E_MEMORYBASE = $200000;
	EBB_BADMEM = 2;
	ERTB_CHAINEDCONFIG = 3;
	ECIF_INTENA = 2;
	EZ3_CONFIGAREA = $40000000;
	EBF_SHORTMEM = 2;
	ERT_NEWBOARD = $C0;
	EBF_BADMEM = 4;
	ERTF_CHAINEDCONFIG = 8;
	ERFB_NOSHUTUP = 6;
	ERFF_NOSHUTUP = $40;
	ERT_Z3_SSMASK = $F;
	ERTB_MEMLIST = 5;
	DAC_CONFIGTIME = $10;
	EZ3_CONFIGAREAEND = $7FFFFFFF;
	E_EXPANSIONBASE = $E80000;
	ERTF_MEMLIST = $20;
	ERTB_DIAGVALID = 4;
	E_MEMORYSLOTS = $80;
	ERTF_DIAGVALID = $10;
	ERT_Z3_SSSIZE = 4;
	ECIB_INT2PEND = 4;
	E_MEMORYSIZE = $800000;
	ERT_TYPEMASK = $C0;
	EE_NOBOARD = $2B;
	ERT_MEMMASK = 7;
	ECIB_INT6PEND = 5;
	ECIF_INT2PEND = $10;
	ERT_Z3_SSBIT = 0;
	ECIB_INT7PEND = 6;
	EBB_SILENTSTART = 6;
	ECIF_INT6PEND = $20;
	EE_BADMEM = $2C;
	E_EXPANSIONSLOTS = 8;
	ECIB_RESET = 3;
	ECIF_INT7PEND = $40;
	EBF_SILENTSTART = $40;
	ERT_ZORROIII = $80;
	EBB_KICKBACK33 = 4;
	ECIF_RESET = 8;
	EE_NOMEMORY = $2A;
	EBB_KICKBACK36 = 5;
	EZ3_SIZEGRANULARITY = $80000;
	EBF_KICKBACK33 = $10;
	ERT_TYPESIZE = 2;
	CDB_BADMEMORY = 2;
	EBF_KICKBACK36 = $20;
	E_SLOTSHIFT = $10;
	ERT_MEMSIZE = 3;
	ERFB_MEMSPACE = 7;
	E_EXPANSIONSIZE = $80000;
	EBB_START_CC0 = 7;
	CDF_BADMEMORY = 4;
	ERFF_MEMSPACE = $80;
	ERFB_EXTENDED = 5;
	EBF_START_CC0 = $80;
	ERT_TYPEBIT = 6;
	CDB_PROCESSED = 3;
	ADNB_STARTPROC = 0;
	EZ3_EXPANSIONBASE = $FF000000;
	ERT_MEMBIT = 0;
	ERFF_EXTENDED = $20;
	CDF_PROCESSED = 8;
	ADNF_STARTPROC = 1;
	CDB_CONFIGME = 1;
	EXPANSIONNAME = 'expansion.library';
	DAC_NEVER = 0;
	EE_NOEXPANSION = $29;
	DAC_BINDTIME = $20;
	CDF_CONFIGME = 2;
	CDB_SHUTUP = 0;
	E_SLOTMASK = $FFFF;
	ERT_ZORROII = $C0;
	CDF_SHUTUP = 1;
	EE_OK = 0;
	EBB_CLOGGED = 0;
	DAC_BYTEWIDE = $40;
	EE_LASTBOARD = $28;
	E_SLOTSIZE = $10000;
	EBF_CLOGGED = 1;
	ECIB_INTERRUPTING = 7;
	ERFB_ZORRO_III = 4;
	DAC_BOOTTIME = $30;
	DAC_WORDWIDE = $80;


procedure AddConfigDev (configDev: pConfigDev);
function AddBootNode
		(bootPri: shortint;
		flags: long;
		deviceNode: pDeviceNode;
		configDev: pConfigDev): boolean;

procedure AllocBoardMem (slotSpec: long);
function AllocConfigDev: pConfigDev;
function AllocExpansionMem
		(numSlots: long;
		slotAlign: long): pointer;

procedure ConfigBoard
		(board: pointer;
		configDev: pConfigDev);

procedure ConfigChain (baseAddr: pointer);
function FindConfigDev
		(oldConfigDev: pConfigDev;
		manufacturer: longint;
		product: longint): pConfigDev;

procedure FreeBoardMem
		(startSlot: long;
		slotSpec: long);

procedure FreeConfigDev (configDev: pConfigDev);
procedure FreeExpansionMem
		(startSlot: long;
		numSlots: long);

function ReadExpansionByte
		(board: pointer;
		offset: long): byte;

procedure ReadExpansionRom
		(board: pointer;
		configDev: pConfigDev);

procedure RemConfigDev (configDev: pConfigDev);
procedure WriteExpansionByte
		(board: pointer;
		offset: long;
		byte: long);

procedure ObtainConfigBinding;
procedure ReleaseConfigBinding;
procedure SetCurrentBinding
		(currentBinding: pCurrentBinding;
		bindingSize: long);

function GetCurrentBinding
		(currentBinding: pCurrentBinding;
		bindingSize: long): long;

function MakeDosNode (parmPacket: pointer): pDeviceNode;
function AddDosNode
		(bootPri: shortint;
		flags: long;
		deviceNode: pDeviceNode): boolean;



function ERT_MEMNEEDED (t: Byte): longint;
function ERT_SLOTSNEEDED (t: Byte): integer;
function EC_MEMADDR (slot: Integer): pointer;


IMPLEMENTATION
function ERT_MEMNEEDED;
begin
	if (t and ERT_MEMMASK) <> 0 then
		ERT_MEMNEEDED := $10000 shl ((t and ERT_MEMMASK) - 1)
	else
		ERT_MEMNEEDED := $800000
end;

function ERT_SLOTSNEEDED;
begin
	if (t and ERT_MEMMASK) <> 0 then
		ERT_SLOTSNEEDED := $1 shl ((t and ERT_MEMMASK) - 1)
	else
		ERT_SLOTSNEEDED := 128
end;

function EC_MEMADDR;
begin
	EC_MEMADDR := pointer(longint(slot) shl E_SLOTSHIFT)
end;

procedure AddConfigDev; xassembler;
asm
	move.l	a6,-(sp)
	move.l	8(sp),a0
	move.l	ExpansionBase,a6
	jsr		-$1E(a6)
	move.l	(sp)+,a6
end;

function AddBootNode; xassembler;
asm
	move.l	a6,-(sp)
	lea		8(sp),a6
	move.l	(a6)+,a1
	move.l	(a6)+,a0
	move.l	(a6)+,d1
	move.b	(a6)+,d0
	move.l	ExpansionBase,a6
	jsr		-$24(a6)
	tst.l	d0
	sne		d0
	neg.b	d0
	move.b	d0,$16(sp)
	move.l	(sp)+,a6
end;

procedure AllocBoardMem; xassembler;
asm
	move.l	a6,-(sp)
	move.l	8(sp),d0
	move.l	ExpansionBase,a6
	jsr		-$2A(a6)
	move.l	(sp)+,a6
end;

function AllocConfigDev; xassembler;
asm
	move.l	a6,-(sp)
	move.l	ExpansionBase,a6
	jsr		-$30(a6)
	move.l	d0,8(sp)
	move.l	(sp)+,a6
end;

function AllocExpansionMem; xassembler;
asm
	move.l	a6,-(sp)
	lea		8(sp),a6
	move.l	(a6)+,d1
	move.l	(a6)+,d0
	move.l	ExpansionBase,a6
	jsr		-$36(a6)
	move.l	d0,$10(sp)
	move.l	(sp)+,a6
end;

procedure ConfigBoard; xassembler;
asm
	move.l	a6,-(sp)
	lea		8(sp),a6
	move.l	(a6)+,a1
	move.l	(a6)+,a0
	move.l	ExpansionBase,a6
	jsr		-$3C(a6)
	move.l	(sp)+,a6
end;

procedure ConfigChain; xassembler;
asm
	move.l	a6,-(sp)
	move.l	8(sp),a0
	move.l	ExpansionBase,a6
	jsr		-$42(a6)
	move.l	(sp)+,a6
end;

function FindConfigDev; xassembler;
asm
	move.l	a6,-(sp)
	lea		8(sp),a6
	move.l	(a6)+,d1
	move.l	(a6)+,d0
	move.l	(a6)+,a0
	move.l	ExpansionBase,a6
	jsr		-$48(a6)
	move.l	d0,$14(sp)
	move.l	(sp)+,a6
end;

procedure FreeBoardMem; xassembler;
asm
	move.l	a6,-(sp)
	lea		8(sp),a6
	move.l	(a6)+,d1
	move.l	(a6)+,d0
	move.l	ExpansionBase,a6
	jsr		-$4E(a6)
	move.l	(sp)+,a6
end;

procedure FreeConfigDev; xassembler;
asm
	move.l	a6,-(sp)
	move.l	8(sp),a0
	move.l	ExpansionBase,a6
	jsr		-$54(a6)
	move.l	(sp)+,a6
end;

procedure FreeExpansionMem; xassembler;
asm
	move.l	a6,-(sp)
	lea		8(sp),a6
	move.l	(a6)+,d1
	move.l	(a6)+,d0
	move.l	ExpansionBase,a6
	jsr		-$5A(a6)
	move.l	(sp)+,a6
end;

function ReadExpansionByte; xassembler;
asm
	move.l	a6,-(sp)
	movem.l	8(sp),d0/a0
	move.l	ExpansionBase,a6
	jsr		-$60(a6)
	move.b	d0,$10(sp)
	move.l	(sp)+,a6
end;

procedure ReadExpansionRom; xassembler;
asm
	move.l	a6,-(sp)
	lea		8(sp),a6
	move.l	(a6)+,a1
	move.l	(a6)+,a0
	move.l	ExpansionBase,a6
	jsr		-$66(a6)
	move.l	(sp)+,a6
end;

procedure RemConfigDev; xassembler;
asm
	move.l	a6,-(sp)
	move.l	8(sp),a0
	move.l	ExpansionBase,a6
	jsr		-$6C(a6)
	move.l	(sp)+,a6
end;

procedure WriteExpansionByte; xassembler;
asm
	move.l	a6,-(sp)
	lea		8(sp),a6
	move.l	(a6)+,d1
	move.l	(a6)+,d0
	move.l	(a6)+,a0
	move.l	ExpansionBase,a6
	jsr		-$72(a6)
	move.l	(sp)+,a6
end;

procedure ObtainConfigBinding; xassembler;
asm
	move.l	a6,-(sp)
	move.l	ExpansionBase,a6
	jsr		-$78(a6)
	move.l	(sp)+,a6
end;

procedure ReleaseConfigBinding; xassembler;
asm
	move.l	a6,-(sp)
	move.l	ExpansionBase,a6
	jsr		-$7E(a6)
	move.l	(sp)+,a6
end;

procedure SetCurrentBinding; xassembler;
asm
	move.l	a6,-(sp)
	movem.l	8(sp),d0/a0
	move.l	ExpansionBase,a6
	jsr		-$84(a6)
	move.l	(sp)+,a6
end;

function GetCurrentBinding; xassembler;
asm
	move.l	a6,-(sp)
	movem.l	8(sp),d0/a0
	move.l	ExpansionBase,a6
	jsr		-$8A(a6)
	move.l	d0,$10(sp)
	move.l	(sp)+,a6
end;

function MakeDosNode; xassembler;
asm
	move.l	a6,-(sp)
	move.l	8(sp),a0
	move.l	ExpansionBase,a6
	jsr		-$90(a6)
	move.l	d0,$C(sp)
	move.l	(sp)+,a6
end;

function AddDosNode; xassembler;
asm
	move.l	a6,-(sp)
	lea		8(sp),a6
	move.l	(a6)+,a0
	move.l	(a6)+,d1
	move.b	(a6)+,d0
	move.l	ExpansionBase,a6
	jsr		-$96(a6)
	tst.l	d0
	sne		d0
	neg.b	d0
	move.b	d0,$12(sp)
	move.l	(sp)+,a6
end;

end.
