
; Exec-Support-Routinen.  Compress-Tab 8.

	NOLIST
	INCLUDE	"exec/types.i"
	INCLUDE	"exec/nodes.i"
	INCLUDE	"exec/lists.i"
	INCLUDE	"exec/memory.i"
	INCLUDE	"exec/interrupts.i"
	INCLUDE	"exec/ports.i"
	INCLUDE	"exec/io.i"
	INCLUDE	"exec/libraries.i"
	INCLUDE	"exec/tasks.i"
	INCLUDE	"exec/execbase.i"
	INCLUDE	"lvo/exec.i"
	LIST



_SysBase	EQU	4

CALL	MACRO
	IFEQ NARG-2
	move.l	\2,a6
	ENDC
	IFLE NARG-2
	jsr	_LVO\1(a6)
	MEXIT
	ENDC
	FAIL	CALL MACRO: PARAMETERFEHLER
	ENDM










; NewList.

	IFD	NewList

	XDEF	_NewList

_NewList
	move.l	4(SP),a0
	NEWLIST	a0
	rts

	ENDC










; BeginIO.

	IFD	BeginIO

	XDEF	_BeginIO

_BeginIO
	move.l	4(SP),a1
	BEGINIO
	rts

	ENDC










; CreatePort und DeletePort.

	IFD	CreatePort

	XDEF	_CreatePort,_DeletePort





; Portzeiger = CreatePort (Namenzeiger,	Priorität)
; Rückgabewert in D0; gibt Null	zurück,	wenn Port nicht	erzeugbar ist.

_CreatePort_REG	REG	d1/d7/a0-a2/a6	; 6 Register
REGISTER	SET	6

_CreatePort
	; Hole ein Signalbit.
	movem.l	_CreatePort_REG,-(SP)
	moveq	#-1,d0			; beliebiges Bit
	CALL	AllocSignal,_SysBase
	move.l	d0,d7			; belegt ?
	bmi.s	1$			; nein,	gib Null zurück

	; Belege die Port-Struktur.
	moveq	#MP_SIZE,d0
	move.l	#MEMF_CLEAR!MEMF_PUBLIC,d1
	CALL	AllocMem
	tst.l	d0			; belegt ?
	bne.s	2$
	move.l	d7,d0			; nein,	Signal freigeben
	CALL	FreeSignal
1$	moveq	#0,d0			; gib Null zurück
	bra.s	0$

	; Initialisiere	den Port.
2$	move.l	d0,a2
	move.l	REGISTER*4+4(SP),LN_NAME(a2)	; Name
	move.b	REGISTER*4+8+3(SP),LN_PRI(a2)	; Priorität, nimm nur 8	Bits !
	move.b	#NT_MSGPORT,LN_TYPE(a2)	; Typ
	move.b	#PA_SIGNAL,MP_FLAGS(a2)
	move.b	d7,MP_SIGBIT(a2)	; Signalbit
	suba.l	a1,a1
	CALL	FindTask		; finde	uns selber
	move.l	d0,MP_SIGTASK(a2)

	; Melde	den Port an das	System.
	tst.l	REGISTER*4+4(SP)	; ist Namenzeiger Null ?
	beq.s	3$
	move.l	a2,a1
	CALL	AddPort			; nein
	bra.s	4$

3$	lea	MP_MSGLIST(a2),a0	; wenn Nullzeiger
	NEWLIST	a0
4$	move.l	a2,d0			; Portzeiger

	; Fertig.
0$	movem.l	(SP)+,_CreatePort_REG
	rts





; DeletePort (Portzeiger)

_DeletePort_REG	REG	d0-d1/a0-a2/a6	; 6 Register
REGISTER	SET	6

_DeletePort
	; Entferne den Port aus	dem System.
	movem.l	_DeletePort_REG,-(SP)
	move.l	_SysBase,a6
	move.l	REGISTER*4+4(SP),a2
	move.l	LN_NAME(a2),d0
	beq.s	1$
	move.l	a2,a1
	CALL	RemPort

	; Lösche Portwerte.
1$	moveq	#-1,d0
	move.b	d0,LN_TYPE(a2)
	move.l	d0,MP_MSGLIST+LH_HEAD(a2)

	; Gib das Signalbit und	den Speicher frei.
	moveq	#0,d0			; FreeSignal braucht 32-Bit-Wert !
	move.b	MP_SIGBIT(a2),d0
	CALL	FreeSignal
	move.l	a2,a1
	moveq	#MP_SIZE,d0
	CALL	FreeMem

	; Fertig.
	movem.l	(SP)+,_DeletePort_REG
	rts





	ENDC










; CreateStdIO, DeleteStdIO, CreateExtIO	und DeleteExtIO.

	IFD	CreateIO

	XDEF	_CreateStdIO,_DeleteStdIO,_CreateExtIO,_DeleteExtIO





; IOStdReq-Zeiger = CreateStdIO	(ioReplyPort)
; Rückgabe in D0; gibt Null zurück, wenn etwas schiefging.

_CreateStdIO
	pea	IOSTD_SIZE
	move.l	4+4(SP),-(SP)
	bsr.s	_CreateExtIO
	addq	#2*4,SP			; korrigiere Stack
	rts





; IORequest-Zeiger = CreateExtIO (ioReplyPort, Requestgröße)
; Rückgabe in D0; gibt Null zurück, wenn etwas schiefging.

_CreateExtIO_REG	REG	d1/a0-a1/a6	; 4 Register
REGISTER	SET	4

_CreateExtIO
	; Ist der Portzeiger Null ?
	movem.l	_CreateExtIO_REG,-(SP)
	move.l	REGISTER*4+4(SP),d0
	beq.s	0$			; ja, Ende mit Null

	; Belege die Request-Struktur.
	move.l	REGISTER*4+8(SP),d0	; Requestgröße
	move.l	#MEMF_CLEAR!MEMF_PUBLIC,d1
	CALL	AllocMem,_SysBase
	tst.l	d0			; belegt ?
	beq.s	0$			; nein,	Ende mit Null

	; Initialisiere	die Struktur.
	move.l	d0,a0
	move.b	#NT_MESSAGE,LN_TYPE(a0)
	move.w	REGISTER*4+8+2(SP),MN_LENGTH(a0)	; nimm nur 16 Bit !
	move.l	REGISTER*4+4(SP),MN_REPLYPORT(a0)

	; Fertig.
0$	movem.l	(SP)+,_CreateExtIO_REG
	rts





; DeleteExtIO (ioExt)
; DeleteStdIO ist funktionell identisch	!

_DeleteExtIO_REG	REG	d0-d1/a0-a1/a6	; 5 Register
REGISTER	SET	5

_DeleteStdIO
_DeleteExtIO
	; Wurde	ein Nullzeiger übergeben ?
	movem.l	_DeleteExtIO_REG,-(SP)
	move.l	REGISTER*4+4(SP),d0
	beq.s	0$			; ja, Ende
	
	; Mache	den Request kaputt und gib ihn frei.
	move.l	d0,a1
	moveq	#-1,d0
	move.b	d0,LN_TYPE(a1)
	move.l	d0,IO_DEVICE(a1)
	move.l	d0,IO_UNIT(a1)
	moveq	#0,d0			; FreeMem braucht 32 Bit !
	move.w	MN_LENGTH(a1),d0
	CALL	FreeMem,_SysBase

	; Fertig.
0$	movem.l	(SP)+,_DeleteExtIO_REG
	rts





	ENDC










; CreateTask.

	IFD	CreateTask

	XDEF	_CreateTask,_DeleteTask





; Taskzeiger = CreateTask (Namenzeiger,	Priorität, AnfangsPC, Stackgröße)
; Rückgabe in D0; gibt im Fehlerfall Null zurück.

ML_GROESSE	EQU	ML_SIZE+2*ME_SIZE

_CreateTask_REG	REG	d1/d7/a0-a4/a6
REGISTER	SET	8

_CreateTask
	; Runde	die Stackgröße auf Langwortgrenze.
	movem.l	_CreateTask_REG,-(SP)
	link	a4,#-ML_GROESSE		; Platz	für zweite MemList
	move.l	REGISTER*4+8+4*3(a4),d7	; Stackgröße
	addq.l	#3,d7
	and	#~3,d7

	; Benutze die zweite MemList, damit CreateTask reentrant ist.
	lea	_TaskMemTemplate(PC),a2	; Quelle
	move.l	SP,a1			; Ziel
	move.l	a1,a0			; für AllocEntry
	moveq	#(ML_GROESSE/2)-1,d0
1$	move.w	(a2)+,(a1)+
	dbra	d0,1$
	move.l	d7,-ML_GROESSE+ML_SIZE+ME_SIZE+ME_LENGTH(a4)	; Stackgröße

	; Belege den Speicher.
	CALL	AllocEntry,_SysBase
	bclr	#31,d0			; alles	Ok ?
	beq.s	2$
	moveq	#0,d0			; nein
	bra.s	0$

	; Hole die Speicherzeiger.
2$	move.l	d0,a1
	move.l	ML_SIZE+ME_ADDR(a1),a2	; Task-Struktur
	move.l	ML_SIZE+ME_SIZE+ME_ADDR(a1),a0	; Stack

	; Setze	die Stackwerte.
	move.l	a0,TC_SPLOWER(a2)
	add.l	d7,a0			; addiere Stackgröße
	move.l	a0,TC_SPUPPER(a2)
	move.l	a0,TC_SPREG(a2)

	; Setze	Taskwerte.
	move.b	#NT_TASK,LN_TYPE(a2)
	move.b	REGISTER*4+8+4*1+3(a4),LN_PRI(a2)	; Priorität, nimm 8 Bits
	move.l	REGISTER*4+8+4*0(a4),LN_NAME(a2)	; Name

	; Klebe	die MemList an die Task.
	lea	TC_MEMENTRY(a2),a0
	NEWLIST	a0
	CALL	AddHead			; statt	des Makro, damit's kurz	ist

	; Melde	dem System die Task.
	move.l	a2,a1			; Task
	move.l	a2,d7			; merken
	move.l	REGISTER*4+8+4*2(a4),a2	; Anfangs-PC
	suba.l	a3,a3			; finalPC
	CALL	AddTask
	move.l	d7,d0			; Rückgabewert:	Taskzeiger

	; Fertig.
0$	unlk	a4
	movem.l	(SP)+,_CreateTask_REG
	rts





; DeleteTask (Taskzeiger)

_DeleteTask_REG	REG	d0-d1/a0-a1/a6
REGISTER	SET	5

_DeleteTask
	movem.l	_DeleteTask_REG,-(SP)
	move.l	REGISTER*4+4(SP),a1	; das Freigeben	der Taskstruktur und des
	CALL	RemTask,_SysBase	; Stacks wird von RemTask erledigt
	movem.l	(SP)+,_DeleteTask_REG
	rts





_TaskMemTemplate
	; Die Memory-Liste
	dcb.b	LN_SIZE,0	; kein Node
	dc.w	2		; 2 Einträge:
	dc.l	MEMF_PUBLIC!MEMF_CLEAR,TC_SIZE	; für die Task-Struktur
	dc.l	MEMF_CLEAR,0	; für den Stack, Größe wird später eingetragen





	ENDC










	END

