
		include	gst:OS3_GST.i		* all OS3 includes in 1 file *

;		INCLUDE exec/exec.i
;		INCLUDE libraries/exec_lib.i
;		INCLUDE intuition/intuition.i
;		INCLUDE libraries/intuition_lib.i
;		INCLUDE devices/serial.i
;		INCLUDE devices/console.i

SerBuf		=	128	; Serial incoming buffer in bytes

		RSRESET
ConWritePort	rs.l	1	; Console Write Port
ConWriteReq	rs.l	1	; Console Write Request
ConReadPort	rs.l	1	; Console Read Port
ConReadReq	rs.l	1	; Console Read Request
ConsoleBit	rs.w	1	; Console Signal Bits 

SerWritePort	rs.l	1	; Serial Write Port
SerWriteReq	rs.l	1	; Serial Write Request
SerReadPort	rs.l	1	; Serial Read Port
SerReadReq	rs.l	1	; Serial Read Request
SerialBit	rs.w	1	; Serial Signal Bits

_IntuitionBase	rs.l	1	; Intuition Base
WindowPtr	rs.l	1	; Window Base
WaitState	rs.l	1	; State of the sigbits after a wait
WindowBit	rs.w	1	; SigBit for the window
conbuffer	rs.w	1	; buffer for the important stuff

serbuffer	rs.b	SerBuf

GT_VarLength	rs.l	1

		RSRESET
WritePort	rs.l	1   ; Location of the write port
WriteReq	rs.l	1   ; Location of the write request
ReadPort	rs.l	1   ; Location of the read port
ReadReq 	rs.l	1   ; Location of the read request
SignalBit	rs.w	1   ; Location of the SigBit


GT		link	a5,#-(GT_VarLength)     ; Get the global variable memory.
		lea	-(GT_VarLength)(a5),a5	; give us some varmem please!

*-------------- Open intuition library

		movea.l 4.w,a6			; Load ExecBase in a6
		lea	IntuiName(pc),a1	; Put the Intuition name in a1
		jsr	_LVOOldOpenLibrary(a6)	; Open it.
		move.l	d0,_IntuitionBase(a5)   ; Move the base pointer into the global var.
		beq.w	KillMem 		; If not free mem.

*-------------- Open Term Window..

		movea.l d0,a6
		suba.l	a0,a0			; Quickly put a 0 into a0
		lea	windowtags(pc),a1	; Put the window tags into a1
		jsr	_LVOOpenWindowTagList(a6) ; Open the window.
		move.l	d0,WindowPtr(a5)        ; Store the window ptr into global var.
		beq.w	KillLib 		; If not close lib.

		move.l	d0,a0			; Put window ptr into a0
		move.l	wd_UserPort(a0),a1      ; Put UserPort into a1
		move.b	MP_SIGBIT(a1),WindowBit(a5) ; Store window's sigbit in global va

*-------------- Allocate a Console IO..

		movea.l 4.w,a6			; Load ExecBase back in a6
		moveq	#IOSTD_SIZE,d4		; Push the size of the requests we need
		lea	ConWritePort(a5),a4	; Push the beginning of the data structure
		bsr.w	AllocPorts		; Call the handy AllocPorts command
		tst.l	d0			; Test and see if everything opened
		beq.w	KillWindow		; If not close the window

		movea.l ConWriteReq(a5),a1      ; Move the write request into a1
		move.l	WindowPtr(a5),IO_DATA(a1) ; Shove the window ptr into io_data
		move.l	#wd_Size,IO_LENGTH(a1)  ; Put the window size into length

*-------------- Open Console Device..

		moveq	#0,d0			; This is the con unit number
		move.l	d0,d1			; clear out d1
		lea	ConName(pc),a0		; Load the console name into a0
		jsr	_LVOOpenDevice(a6)      ; Open it
		tst.l	d0			; See if it was opened
		bne.w	KillConPorts		; If not kill the ports

		move.l	ConWriteReq(a5),a0      ; Move write request into a0
		move.l	ConReadReq(a5),a1       ; Move read request into a1
		move.l	IO_DEVICE(a0),IO_DEVICE(a1) ; Copy the IO_DEVICE and the IO_UNIT
		move.l	IO_UNIT(a0),IO_UNIT(a1) ; From the write request to the read request

*-------------- Allocate a Serial IO

		moveq	#IOEXTSER_SIZE,d4	; d4=serial request size
		lea	SerWritePort(a5),a4	; beginning of the data structure
		bsr.w	AllocPorts		; Get the ports
		tst.l	d0			; See if it all opened
		beq.w	CloseConsole		; If not close the console

*-------------- Open Serial Device..

		move.l	SerWriteReq(a5),a1      ; Move the write request into a1
		move.b	#SERF_SHARED,IO_SERFLAGS(a1) ; Set the flags
		moveq	#0,d0			; Unit 0
		move.l	d0,d1			; No flags
		lea	SerName(pc),a0		; Put the ser name into a0
		jsr	_LVOOpenDevice(a6)      ; Open the device
		tst.l	d0			; See if it opened
		bne.w	KillSerPorts		; If not kill the ports

		move.l	SerWriteReq(a5),a0      ; Move the write request into a0
		move.l	SerReadReq(a5),a1       ; Move the read  request into a1
		move.l	IO_DEVICE(a0),IO_DEVICE(a1) ; Copy IO_DEVICE and IO_UNIT
		move.l	IO_UNIT(a0),IO_UNIT(a1) ; from the write request into the read request

		bsr.w	ConGet			; Send out a read request for the console.
		bsr.w	SerGet			; Send out a read request for the serial port.

Mainloop:	moveq	#0,d0			; Clear out d0.
		move.b	WindowBit(a5),d1        ; Put window's sigbit into d1.
		bset.l	d1,d0			; Set it in d0.
		move.b	ConsoleBit(a5),d1       ; Put console's sigbit into d1.
		bset.l	d1,d0			; Set it in d0.
		move.b	SerialBit(a5),d1        ; Put serial's sigbit into d1.
		bset.l	d1,d0			; Set it in d0.
		jsr	_LVOWait(a6)            ; Wait for any of the sigbits.
		move.l	d0,WaitState(a5)        ; Save the sigbits that woke us up in a global var.

		move.b	ConsoleBit(a5),d1       ; Put console's sigbit in d1.
		btst.l	d1,d0			; See if it is one of the bits that woke us.
		beq.b	ntest			; If not go to next test.
		move.l	SerWriteReq(a5),a1      ; Move the serial write request into a1
		move.w	#CMD_WRITE,IO_COMMAND(a1) ; Prepare to write
		lea	conbuffer(a5),a0        ; Load the conbuffer into the data
		move.l	a0,IO_DATA(a1)          ; Load its length into the length
		moveq	#1,d0
		move.l	d0,IO_LENGTH(a1)
		jsr	_LVODoIO(a6)            ; Write it
		bsr.w	ConGet			; Send out the console read request again

ntest:		move.l	WaitState(a5),d0        ; Load the wakeup bits again
		move.b	SerialBit(a5),d1        ; Put the serial sigbit into d1
		btst.l	d1,d0			; See if we have the ser bit
		beq.b	.2			; If not go to .2
		move.l	ConWriteReq(a5),a1      ; Else put the console write request into a1
		move.w	#CMD_WRITE,IO_COMMAND(a1) ; Prepare to write
		lea	serbuffer(a5),a0        ; Load the serbuffer as the data
		move.l	a0,IO_DATA(a1)
		moveq	#-1,d0
		move.l	d0,IO_LENGTH(a1)       ; Set length for a null terminated string
		jsr	_LVODoIO(a6)            ; Write it
		bsr.w	SerGet			; Send out the serial read request again

.2		move.l	WaitState(a5),d0        ; Load the wakeup bits yet again
		move.b	WindowBit(a5),d1        ; Load the window's sigbit into d1
		btst.l	d1,d0			; See if we got a close gadget hit
		beq.b	Mainloop		; If not loop again

_Close		movea.l SerReadReq(a5),a1       ; Load the serial read request into a1
		jsr	_LVOCheckIO(a6)         ; See if it's still out
		tst.l	d0
		bne.b	.1			; If not jump to .1
		movea.l SerReadReq(a5),a1       ; Load the read request again
		jsr	_LVOAbortIO(a6)         ; Abort it
		movea.l SerReadReq(a5),a1       ; Load the read request again
		jsr	_LVOWaitIO(a6)          ; Wait for it to be aborted

.1		movea.l SerWriteReq(a5),a1      ; Load the write request into a1
		jsr	_LVOCloseDevice(a6)     ; Close the serial port

KillSerPorts:	lea	SerWritePort(a5),a4	; Push the begining of the data structure
		bsr.w	FreePorts		; Free the ports

CloseConsole:	movea.l ConReadReq(a5),a1       ; Load the console write port into a1
		jsr	_LVOCheckIO(a6)         ; See if it's still out
		tst.l	d0
		bne.b	.1			; If not jump to .1
		movea.l ConReadReq(a5),a1       ; Load the read request again
		jsr	_LVOAbortIO(a6)         ; Abort the request
		movea.l ConReadReq(a5),a1       ; Load the read request again
		jsr	_LVOWaitIO(a6)          ; Wait for it to be aborted

.1		movea.l ConWriteReq(a5),a1      ; Load the write request into a1
		jsr	_LVOCloseDevice(a6)     ; Close the console

KillConPorts	lea	ConWritePort(a5),a4	; begining of the data structure
		bsr.b	FreePorts		; Free the ports

*-------------- Close Term Window

KillWindow:	move.l	WindowPtr(a5),a0        ; Move the window ptr into a0
		movea.l _IntuitionBase(a5),a6   ; Load IntuitionBase into a6
		jsr	_LVOCloseWindow(a6)     ; Close the window

*-------------- Close Intuition Library

KillLib		move.l	_IntuitionBase(a5),a1   ; Move IntuitionBase into a1
		movea.l 4.w,a6			; Load ExecBase into a6
		jsr	_LVOCloseLibrary(a6)    ; Close Intuition

*-------------- Free RS Area

KillMem		lea	(GT_VarLength)(a5),a5	; Add our global variable length to a5
		unlk	a5			; Free our global variables
		moveq	#0,d0			; This returns "no errors" to AmigaDOS
ending		rts				; Return



; AllocPorts ( baseaddr, size )

AllocPorts	jsr	_LVOCreateMsgPort(a6)   ; Create a msg port
		move.l	d0,WritePort(a4)        ; Save it in the write port
		beq.b	PortsEnding		; If we didn't get it then end

		movea.l d0,a0			; Move the port into a0
		move.l	d4,d0			; Move the size into d0
		jsr	_LVOCreateIORequest(a6) ; Create an I/O Request
		move.l	d0,WriteReq(a4)         ; Save it's addr
		beq.b	FreeWritePort		; If we didn't get it then free the write port

		jsr	_LVOCreateMsgPort(a6)   ; Create a read port
		move.l	d0,ReadPort(a4)         ; Save it's addr
		beq.b	FreeWriteReq		; If we didn't get it then free the write req
		movea.l d0,a0			; Move the port into a0
		move.b	MP_SIGBIT(a0),SignalBit(a4) ; Save it's sigbit

		move.l	d4,d0			; Move the size into d0
		jsr	_LVOCreateIORequest(a6) ; Create a read request
		move.l	d0,ReadReq(a4)          ; Save it's addr
		beq.b	FreeReadPort		; If we didn't get it free the read port
		moveq	#1,d0			; Put a 1 in d0 to show we opened everything
		rts

FreePorts:	move.l	ReadReq(a4),a0          ; Move the read request into a0
		jsr	_LVODeleteIORequest(a6) ; Delete it
FreeReadPort:	move.l	ReadPort(a4),a0         ; Move the read port into a0
		jsr	_LVODeleteMsgPort(a6)   ; Delete it
FreeWriteReq:	move.l	WriteReq(a4),a0         ; Move the write request into a0
		jsr	_LVODeleteIORequest(a6) ; Delete it
FreeWritePort:	move.l	WritePort(a4),a0        ; Move the write port into a0
		jsr	_LVODeleteMsgPort(a6)   ; Delete it
PortsEnding:	moveq	#0,d0			; Clear d0 to indicate Alloc ports failed
		rts


SerGet		lea	serbuffer(a5),a0        ; Load address of serbuffer into a0
		moveq	#SerBuf-1,d0		; Just a quick routine to clear
cls:		sf.b	(a0)+           	; the serial buffer
		dbf	d0,cls

		move.l	SerReadPort(a5),a0      ; Move the address of the ReadPort into a0
		jsr	_LVOGetMsg(a6)          ; Get the message in the port.

		move.l	SerWriteReq(a5),a1      ; Move our write request into a1
		move.w	#SDCMD_QUERY,IO_COMMAND(a1) ; Get it ready for a querry
		jsr	_LVODoIO(a6)            ; Do it.
		move.l	SerWriteReq(a5),a0      ; Load the write request into a0
		move.l	IO_ACTUAL(a0),d0        ; Put the number of chars got into d0
		bne.b	.1			; Jump to .1 if it's not zero
		moveq	#1,d1			; Ask for 1 char
		bra.s	send_it			; Jump to .3	

.1		moveq	#SerBuf-1,d2		; Else move the buffer size into d1
		cmp.l	d2,d0			; Compare the number to the size of the buffer
		ble.s	num_ch			; If chars waiting is greater than the buffer then jump to .2
		move.l	d2,d1
		bra.s	send_it			; Jump to .3

num_ch:		move.l	d0,d1			; Move the number of chars waiting into d1
send_it:	move.l	SerReadReq(a5),a1       ; Put the read request into a1
		lea	serbuffer(a5),a0        ; Load the address of the buffer into a0
send:		move.w	#CMD_READ,IO_COMMAND(a1) ; Prepare to read
		move.l	a0,IO_DATA(a1)
		move.l	d1,IO_LENGTH(a1)        ; Load 1 as the length
		jmp	_LVOSendIO(a6)          ; Send it out

ConGet:		movea.l ConReadPort(a5),a0      ; Move the read port into a0
		jsr	_LVOGetMsg(a6)          ; Get the message in it
		movea.l ConReadReq(a5),a1       ; Move the read request into a1
		lea	conbuffer(a5),a0	; Load the conbuffer into the data
		moveq	#1,d1
		bra.s	send

windowtags:	dc.l	WA_Left,0
		dc.l	WA_Top,11
		dc.l	WA_Width,640
		dc.l	WA_Height,256-11
		dc.l	WA_IDCMP,IDCMP_CLOSEWINDOW
		dc.l	WA_Flags,WFLG_DRAGBAR!WFLG_DEPTHGADGET!WFLG_CLOSEGADGET!WFLG_ACTIVATE!WFLG_SIMPLE_REFRESH
		dc.l	TAG_DONE

IntuiName	dc.b    'intuition.library',0
SerName		dc.b    'serial.device',0
ConName		dc.b    'console.device',0
		END
