;------------------------------------------------
;Testen, ob Diskette im Laufwerk schreibgeschützt
;
;RG
;------------------------------------------------


 include "exec/types.i"
 include "exec/memory.i"
 include "exec/io.i"
 include "devices/trackdisk.i"
 include "exec/ports.i"
 include "exec/execbase.i"

CALLSYS	MACRO
	jsr _LVO\1(a6)
	ENDM
XLIB	MACRO
	XREF _LVO\1
	ENDM

 STRUCTURE	global,0
	APTR	MyReplyPort
	APTR	MyIORequest
	LABEL	global_size

 XREF _AbsExecBase
;------------------------------------------------
;Exec

 XLIB AllocMem
 XLIB FreeMem
 XLIB OpenDevice
 XLIB CloseDevice
 XLIB DoIO
 XLIB AllocSignal
 XLIB FreeSignal
 XLIB AddPort

;------------------------------------------------
Laufwerk	EQU	0
Flags	EQU	0


	move.l	_AbsExecBase,a6
	lea	-global_size(a7),a7
	move.l	a7,a5
	suba.l	a0,a0		;keinName (lokaler Port)
	bsr	_CreatePort
	move.l	d0,MyReplyPort(a5)
	beq.s	1$		;kein Port erstellt
	move.l	d0,a0		;Zeiger auf Port
	bsr	_CreateStdIO
	move.l	d0,MyIORequest(a5)
	beq.s	2$		;keine IORequest-Struktur
	bsr	OeffneDevice
	tst.l	d0
	bne.s	3$

	bsr	TestSchutz
	tst.l	d0
	beq	4$		;Disk nicht geschützt

;sonst Disk schreibgeschützt

4$:	bsr	SchliesseDevice
3$:	move.l	MyIORequest(a5),a0
	bsr	_DeleteStdIO
2$:	move.l	MyReplyPort(a5),a0
	bsr	_DeletePort
1$:	lea	global_size(a7),a7
	clr.l	d0
	rts
;------------------------------------------------
;Device für Trackdisk öffnen
;=> D0 = Null => Alles Ok

OeffneDevice:
	lea	DeviceName(pc),a0
	move.l	#Laufwerk,d0
	move.l	MyIORequest(a5),a1
	move.l	#Flags,d1
	CALLSYS	OpenDevice
	rts
;------------------------------------------------
;Device schließen

SchliesseDevice:
	move.l	MyIORequest(a5),a1
	CALLSYS	CloseDevice
	rts
;------------------------------------------------
;Testen, ob Diskkette im Laufwerk schreibgeschützt ist

;=> D0 = Angabe ob Diskette geschützt (D0 = Null => nicht geschützt)

TestSchutz:
	move.l	MyIORequest(a5),a1
	move.w	#TD_PROTSTATUS,IO_COMMAND(a1)
	CALLSYS	DoIO
	move.l	MyIORequest(a5),a1
	move.l	IO_ACTUAL(a1),d0
	rts
;------------------------------------------------
	
;Funktion zum erstellen eines Messageports:

;>= A0 = Zeiger auf Namen des Ports (nur für globale Ports nötig)
;>= D0 = Priorität des Ports (nur für globale Ports nötig)

;=> D0 = Zeiger auf Port. Wenn kein Port erstellt, D0 = Null

_CreatePort:
	movem.l	d2/a2-a3/a6,-(a7)  ;Register retten
	move.w	d0,d2	;Priorität nach D0
	move.l	a0,a2	;Zeiger auf Name
	move.l	_AbsExecBase,a6    ;ExecBase nach A6

;Die Angaben über die Art des zu belegenden Speichers 
;'MEME_PUBLUC' und 'MEMF_CLEAR' sind innerhalb des Include-Files
;'exec/memory.i' geschehen.

	move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1 ;Speicherbeschreibung

;Die Größe der Port Struktur ist über die Struktur 'MP', die
;innerhalb des Include-File 'exec/ports.i' definiert ist
;festgelegt. Die größe ist in 'MP_SIZE' gespeichert.

	move.l	#MP_SIZE,d0	;Größe der Port-Struktur

;CALLSYS ist ein Macro, welches zu Beginn des Programms erstellt wurde

	CALLSYS	AllocMem	;belege Spicher
	tst.l	d0	;wurde Speicher belegt?
	beq.s	1$	;nein, dann Fehler
	move.l	d0,a3	;Zeiger auf Speicher für Port
	move.l	#-1,d0	;Wert für belibiges Signal
	CALLSYS	AllocSignal	;Signal für Port belegen
	tst.b	d0	;konnte Signal belegt werden ?
	bpl.s	2$	;Ja, alles Ok
	move.l	a3,a1	;sonst, Zeiger auf Speicher holen
	move.l	#MP_SIZE,d0	;größe des Speichers nach d0
	CALLSYS	FreeMem	;Speicher freigeben
	clr.l	d0	;D0 löschen (Fehlermeldung)
	bra.s	1$	;Sprung zum Ende

;Durch die zu Beginn angegebenen Includes, wird auch das File
;'exec/nodes.i' automatisch eingelesen. Hier sind die Einträge
;'LN_NAME', 'LN_PRI', 'LN_TYPE' und 'NT_MSGPORT' definiert.

2$:	move.l	a2,LN_NAME(a3) ;Zeiger auf Namen eintragen
	move.b	d2,LN_PRI(a3)  ;Priorität eintragen
	move.b	#NT_MSGPORT,LN_TYPE(a3)  ;Type eintagen

;Wenn eine Nachricht an den Port gelangt, soll ein Signal am Task
;gesetzt werde. Hierfür muß das MsgPort-Flag entsprechend gesetzt
;werden.

	move.b	#PA_SIGNAL,MP_FLAGS(a3)
	move.b	d0,MP_SIGBIT(a3)

;Um den Zeiger auf den eigenen Task zu erhalten, gibt es zum einen die
;Möglichkeit, ihn mit der 'FindTask'-Funktion zu holen oder schneller
;ihn einfach aus der ExecBase-Struktur auszulesen. Um das letztere
;praktitieren zu können müssen wir uns aus dem Include-File
;'exec/execbase.i' den Offset diese Eintrags holen. Der Offset ist
;in 'ThisTask' gespeichert.

	move.l	ThisTask(a6),MP_SIGTASK(a3)  ;Zeiger auf Task holen

;Damit unser Port Nachrichten in Form einer Liste "aufbewaren" kann,
;muß in ihm eine soche List-Struktur initialisiert werden. Dies
;geschieht über ein Macro, welches in dem Include-File 'exec/lists.i'
;eingetragen ist. Dieses File wird automatisch beim öffnen des Files
;'exec/ports.i' eingelesen. Das Macro heißt NEWLIST und initialisiert
;eine List-Struktur. Als Parameter muß der Zeiger auf die
;List-Struktur in einem Adressregister übergeben werden.

	lea	MP_MSGLIST(a3),a1	;Zeiger auf List-Struktur
	NEWLIST	A1	;Macroaufruf
	move.l	a2,d0	;Zeiger auf Namen des Posts
	beq.s	3$	;verzweige, wenn kein Name angegeben
	move.l	a3,a1	;Zeiger auf Port-Struktur
	CALLSYS	AddPort	;Port in globale Liste eintragen
3$:	move.l	a3,d0	;Zeiger auf Port nach D0
1$:	movem.l	(a7)+,d2/a2-a3/a6  ;Register zurückholen
	rts		;Rücksprung

;------------------------------------------------

;Funkton zu Löschen eines Ports
;>= A0 = Zeiger auf den Port


_DeletePort:
	movem.l	a2/a6,-(a7)  ;Register retten
	move.l	a0,a2	       ;Zeiger auf Port
	move.l	_AbsExecBase,a6    ;ExecBase nach A6

	move.l	LN_NAME(a2),d0	;Name eingetragen
	beq.s	1$		;nein, nicht global

	move.l	a2,a1

;'REMOVE' ist ein Macro, das innerhalb des Include-Files 'exec/lists.i'
;zu finden ist. Dieses Macro entfernt eine Node-Struktur aus der 
;zugehörigen Liste. Es handelt sich um die gleiche Funktion wie die
;Exec-Funktion 'Remove'.

	REMOVE		;Port aus Portliste löschen

1$:	move.b	MP_SIGBIT(a2),d0
	ext.w	d0
	ext.l	d0
	CALLSYS	FreeSignal	;Signal für Port belegen

;Die Größe der Port Struktur ist über die Struktur 'MP', die
;innerhalb des Include-File 'exec/ports.i' definiert ist
;festgelegt. Die größe ist in 'MP_SIZE' gespeichert.

	move.l	#MP_SIZE,d0	;Größe der Port-Struktur
	move.l	a2,a1	;Zeiger auf Port

;CALLSYS ist ein Macro, welches zu Beginn des Programms erstellt wurde

	CALLSYS	FreeMem	;Spicher freigeben
	movem.l	(a7)+,a2/a6  ;Register zurückholen
	rts		;Rücksprung

;------------------------------------------------
;IORequest erstellen

;>= D0 = Größe der IO-Struktur
;>= A0 = Zeiger auf Messageport

;=> D0 = Zeiger auf IO-Struktur oder Null => Fehler aufgetreten

_CreateIO:
	movem.l	d2/a2/a6,-(a7)	;Register retten
	move.l	a0,a2		;Zeiger auf den Port
	move.l	d0,d2		;Länge der Struktur
	move.l	_AbsExecBase,a6	;Zeiger auf ExecBase
	move.l	a0,d0		;ist ein Port angegeben
	beq.s	1$		;Fehler, kein Port
	move.l	d2,d0		;Länge übergeben
	move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1 ;Speicherangabe
	CALLSYS	AllocMem		;Speicher belegen
	tst.l	d0		;wurde Speicher belegt
	beq.s	1$		;kein Speicher belegt
	move.l	d0,a1		;Zeiger auf Speicher
	move.b	#NT_MESSAGE,LN_TYPE(a1)	;Type eintragen
	move.w	d2,MN_LENGTH(a1)	;Länge eintagen
	move.l	a2,MN_REPLYPORT(a1)	;Zeiger auf Port eintragen
1$:	movem.l	(a7)+,d2/a2/a6	;Register zurückgeben
	rts			;Rücksprung

;------------------------------------------------
;>= A0 = Zeiger auf Messageport

_CreateStdIO:
	move.l	#IOSTD_SIZE,d0	;Länge der StdIO-Struktur
	bsr	_CreateIO		;Struktur erstellen
	rts

;------------------------------------------------
;IORequest löschen

;>= A0 = Zeiger IORequest-Struktur

_DeleteIO:
_DeleteStdIO:
	move.l	a6,-(a7)
	move.l	_AbsExecBase,a6
	move.w	MN_LENGTH(a0),d0
	ext.l	d0
	move.l	a0,a1
	CALLSYS	FreeMem
	move.l	(a7)+,a6
	rts
;------------------------------------------------

DeviceName:	dc.b	'trackdisk.device',0

	END

