* this bios has IOBYTE implemented
* as68 -u -l -s 0: biosa.s

*	@(#)biosa.s	2.3	
	.text
*
*	Global Code addresses
*
	.globl	_init
	.globl	_biosinit
	.globl	_flush
	.globl	_wboot
	.globl	_cbios
	.globl	_setimask
	.globl	_ccp
	.globl	cpm			*	Lowest addr of CP/M 
	.globl	_end			*	Highest addr of CP/M
*
*	Global data addresses
*
	.globl	_memtab		*	memory region table
	.globl	_dpb3			*	RAM disk dpb address
	.globl	_memdsk		*	-> First memory disk location
	.globl	_iobyte
*
*	Vector Addresses
*
trap3:	.equ	$8c			*	Trap 3 vector
buserr:	.equ	$8			*	Bus error vector
*
*
_init:
	lea		trap3h,a0
	move.l	a0,trap3
*
*	set initial IOBYTE
*
	move.w	#$80,_iobyte	* 	LST:=LPT:,AUXO:=TTY:,AUXI:=TTY:,CON:=TTY:
*
*	Auto-Size TPA
*
	lea		_memtab,a0		*	a0 -> Memory region table
	move.w	#1,(a0)+		*	1 region
	move.l	#$b00,(a0)+		*	TPA starts at b00
	move.l	#cpm-$b08,(a0)+	*	Ends where CP/M begins
*
*	Auto-Size RAM disk
*
	move.l	buserr,-(sp)	*	Push bus err vector
	lea		_end,a0		*	a0 -> Last location in CP/M
	add.l		#cpm,a0		*	Linker doesn't reloc this!!
	move.l	a0,_memdsk		*	-> first location in RAM disk
	move.l	#quit,buserr	*	set up vector -> ourselves
loop:
	tst.w	(a0)+				*	Find
	bra	loop				*		End of memory
quit:
	add.l		#58,a7		*	Clear buserr gorp
	move.l	(a7)+,buserr	*	Pop buserr vector
	sub.l		#_end,a0		*	a0 = # bytes in RAM disk
	sub.l		#cpm,a0		*	Relocation bug
	move.l	a0,d0			*	Into D reg for shift
	move.l	#11,d1		*	Load shift count
	lsr.l		d1,d0			*	Divide by 2048
	move.w	d0,_dpb3+6		*	Load DRM field of dpb

	move		#$2000,sr
	jsr		_biosinit
	move.w 	#2,d0			*Drive C: and user zero
 	rts
*
_wboot:
	clr.l		d0
	jmp		_ccp
*
trap3h:
	cmpi.w	#nfuncs,d0
	bcc		trapng
	move.w	d0,d4
	lsl.w		#2,d4			* multiply bios function by 4
	lea		biosbase,a0
	add.w		d4,a0			* get handler address
	move.l	(a0),a0
	jsr		(a0)			* call handler
trapng:
	rte

biosbase:
	dc.l  entry		*_init
	dc.l  entry		*wboot
	dc.l  ConInSt
	dc.l  ConIn
	dc.l  ConOut
	dc.l  LstOut
	dc.l  AuxOut
	dc.l  AuxIn
	dc.l  entry		*home
	dc.l  entry		*seldsk
	dc.l  entry		*settrk
	dc.l  entry		*setsec
	dc.l  entry		*setdma
	dc.l  entry		*read
	dc.l  entry		*write
	dc.l  LstOutSt
	dc.l  entry		*sectran
	dc.l  entry		*setdma
	dc.l  entry		*getseg
	dc.l  entry		*getiob
	dc.l  entry		*setiob
	dc.l  entry		*flush
	dc.l  entry		*setexc

tvalue	equ		*-biosbase
nfuncs	equ		tvalue/4

entry:
	move.l	d2,-(a7)
	move.l	d1,-(a7)
	move.w	d0,-(a7)
	jsr		_cbios
	add		#10,a7
	rts
*
_setimask: move sr,d0
	lsr	#8,d0
	and.l	#7,d0
	move	sr,d1
	ror.w	#8,d1
	and.w	#$fff8,d1
	add.w	4(a7),d1
	ror.w	#8,d1
	move	d1,sr
	rts	
*
	.globl	_rddat
	.globl	_wrdat
*
* without considering wait states movep.l makes
* the faster loop.  however, accounting for wait
* states makes the 68010 loop mode faster.
*
_rddat:
	move.l	4(sp),a0
	move.w	#127,d0
	move.l	#$f1c0d9,a1
rdlp:	move.b	(a1),(a0)+
	dbf		d0,rdlp
	rts
*
_wrdat:
	move.l	4(sp),a0
	move.w	#127,d0
	move.l	#$f1c0d9,a1
wrlp:	move.b	(a0)+,(a1)
	dbf		d0,wrlp
	rts
*
	.globl	_no_device
*
_no_device:
	move.l	4(sp),a0
	move.l	buserr,-(sp)
	move.l	#ndber,buserr
	move.b	(a0),d0
	moveq.l	#0,d0
	move.l	(sp)+,buserr
	rts
ndber:
	moveq.l 	#1,d0
	add.l		#58,sp
	move.l	(sp)+,buserr
	rts

* below, implements IOBYE
* ALL vme10 drivers are replaced with new drivers,EXCEPT UC1
* UC1 invokes the normal VME10 drivers for the Screen Keyboard

* 	LST   AUXOUT	AUXIN   	CON
* 0	TTY	 TTY		 TTY		TTY
* 1	CRT	 PTP		 PTR		CRT
* 2	LPT	 UP1		 UR1		BAT
* 3	UL1	 UP2		 UR2		UC1

TblCIS
	dc.l		TTYInSt	* TTY
	dc.l		CRTInSt	* CRT
	dc.l		AuxInSt	* BAT
	dc.l		UC1InSt	* UC1
TblCI
	dc.l		TTYIn		* TTY
	dc.l		CRTIn		* CRT
	dc.l		AuxIn		* BAT
	dc.l		UC1In		* UC1
TblCOS
	dc.l		TTYOutSt	* TTY
	dc.l		CRTOutSt	* CRT
	dc.l		LstOutSt	* BAT
	dc.l		UC1OutSt	* UC1
TblCO
	dc.l		TTYOut	* TTY
	dc.l		CRTOut	* CRT
	dc.l		LstOut	* BAT
	dc.l		UC1Out	* UC1

TblAIS
	dc.l		TTYInSt	* TTY
	dc.l		TTYInSt	* RDR
	dc.l		TTYInSt	* UR1
	dc.l		TTYInSt	* UR2
TblAI
	dc.l		TTYIn		* TTY
	dc.l		TTYIn		* RDR
	dc.l		TTYIn		* UR1
	dc.l		TTYIn		* UR2
TblAOS
	dc.l		TTYOutSt	* TTY
	dc.l		TTYOutSt	* PTP
	dc.l		TTYOutSt	* UP1
	dc.l		TTYOutSt	* UP2
TblAO
	dc.l		TTYOut	* TTY
	dc.l		TTYOut	* PTP
	dc.l		TTYOut	* UP1
	dc.l		TTYOut	* UP2

TblLOS
	dc.l		TTYOutSt	* TTY
	dc.l		CRTOutSt	* CRT
	dc.l		LPTOutSt	* LPT
	dc.l		UL1OutSt	* UL1
TblLO
	dc.l		TTYOut	* TTY
	dc.l		CRTOut	* CRT
	dc.l		LPTOut	* LPT
	dc.l		UL1Out	* UL1

ConInSt:
	lea		TblCIS,a2
CIS	move.w	_iobyte,d4
	and.w		#$3,d4
	lsl.w		#2,d4
	move.l	0(a2,d4),a2
	jmp		(a2)
ConIn:
	lea		TblCI,a2
	bra		CIS
ConOutSt:
	lea		TblCOS,a2
	bra		CIS
ConOut:
	lea		TblCO,a2
	bra		CIS

AuxInSt:
	lea		TblAIS,a2
AIS	move.w	_iobyte,d4
	and.w		#$c,d4
	move.l	0(a2,d4),a2
	jmp		(a2)
AuxIn:
	lea		TblAI,a2
	bra		AIS

AuxOutSt:
	lea		TblAOS,a2
AOS	move.w	_iobyte,d4
	and.w		#$30,d4
	lsr.w		#2,d4
	move.l	0(a2,d4),a2
	jmp		(a2)
AuxOut:
	lea		TblAO,a2
	bra		AOS

LstOutSt:
	lea		TblLOS,a2
LOS	move.w	_iobyte,d4
	and.w		#$C0,d4
	lsr.w		#4,d4
	move.l	0(a2,d4),a2
	jmp		(a2)
LstOut:
	lea		TblLO,a2
	bra		LOS

UC1InSt:
	jmp	entry
UC1In:
	jmp	entry
UC1OutSt:
	move.w	#$00ff,d0		* set result to Ready
	rts
UC1Out:
	jmp 	entry


TTYDR 		equ		$f1c1c9
TTYSR			equ		$f1c1cd
TTYRxRDY		equ		$1
TTYTxRDY		equ		$4

TTYInSt:
	move.b	TTYSR,d0		* get status byte
	andi.b	#TTYRxRDY,d0	* data available bit on?
	beq		TTYInNR		* branch if not
	move.w	#$00FF,d0		* set result to ready
	rts
TTYInNR:
	clr.w		d0			* set result to not ready
	rts

TTYIn:
	bsr		TTYInSt		* see if key pressed
	tst.w		d0
	beq		TTYIn			* wait until key pressed
	move.b	TTYDR,d0		* get key
	and.w		#$7f,d0		* clear all but low 7 bits
	cmpi.b	#1,d0
	beq		break
	rts
break:
	trap		#15
	dc.w		0			* return to TenBUG
	rts

TTYOutSt:
	move.b	TTYSR,d0		* get status
	and.b		#TTYTxRDY,d0	* check for transmitter buffer empty
	beq		TTYOutNR		* wait until data can go...
	move.w	#$00FF,d0		* set result to ready
	rts
TTYOutNR:
	clr.w		d0			* set result to not ready
	rts

TTYOut:
	bsr		TTYOutSt		* see if key pressed
	tst.w		d0
	beq		TTYOut		* wait until data can go...
	move.b	d1,TTYDR 		* and output it
	rts					* and exit

CRTDR 		equ		$f1c1cb
CRTSR			equ		$f1c1cf
CRTRxRDY		equ		$1
CRTTxRDY		equ		$4

CRTInSt:
	move.b	CRTSR,d0		* get status byte
	andi.b	#CRTRxRDY,d0	* data available bit on?
	beq		CRTInNR		* branch if not
	move.w	#$00FF,d0		* set result to ready
	rts
CRTInNR:
	clr.w		d0			* set result to not ready
	rts

CRTIn:
	bsr		CRTInSt		* see if key pressed
	tst.w		d0
	beq		CRTIn			* wait until key pressed
	move.b	CRTDR,d0		* get key
	and.w		#$7f,d0		* clear all but low 7 bits
	cmpi.b	#1,d0
	beq		CRTbrk
	rts
CRTbrk:
	trap		#15
	dc.w		0			* return to TenBUG
	rts

CRTOutSt:
	move.b	CRTSR,d0		* get status
	and.b		#CRTTxRDY,d0	* check for transmitter buffer empty
	beq		CRTOutNR		* wait until data can go...
	move.w	#$00FF,d0		* set result to ready
	rts
CRTOutNR:
	clr.w		d0			* set result to not ready
	rts

CRTOut:
	bsr		CRTOutSt		* see if key pressed
	tst.w		d0
	beq		CRTOut		* wait until data can go...
	move.b	d1,CRTDR 		* and output it
	rts					* and exit

PBASE1	equ		$f1c1e1
PBASE2	equ		$f1c1e9
PDATA  	equ		$0
PDATB		equ		$4
PCNTRLA	equ		$2
PCNTRLB	equ		$6
PSTATA	equ		PCNTRLA
PSTATB	equ		PCNTRLB
PDDRA		equ		PDATA
PDDRB		equ		PDATB

PACKN		equ		PSTATA
PSTRB		equ		PCNTRLA
PRDY		equ		PDATB

LPTOutSt:
	lea		PBASE1,a2

	move.b	PRDY(a2),d0
	and.b		#3,d0
	sub.b		#1,d0
	bne.b		LPTNR			* error if not zero
	move.w	#$00ff,d0		* set result to Ready
	rts
LPTNR
	clr.w		d0			* set result to Not Ready
	rts

LPTOut:
	bsr		LPTOutSt		* see if printer online
	tst.w		d0
	beq		LPTOut		* wait until data can go...

	lea		PBASE1,a2

	move.b	d1,PDATA(a2)	* send character
	move.b	PDATA(a2),d1	* clear ack

	move.b	#$34,PSTRB(a2)	* strobe LOW
	move.b	#$3c,PSTRB(a2)	* destrobe

LPTNACK
	btst.b	#7,PACKN(a2)	*check for Ack
	beq.b		LPTNACK

	rts

* User List 1
UL1OutSt:
	lea		PBASE2,a2

	move.b	PRDY(a2),d0
	and.b		#3,d0
	sub.b		#1,d0
	bne.b		UL1NR			* error if not zero
	move.w	#$00ff,d0		* set result to Ready
	rts
UL1NR
	clr.w		d0			* set result to Not Ready
	rts

UL1Out:
	bsr		UL1OutSt		* see if printer online
	tst.w		d0
	beq		UL1Out		* wait until data can go...

	lea		PBASE2,a2

	move.b	d1,PDATA(a2)	* send character
	move.b	PDATA(a2),d1	* clear ack

	move.b	#$34,PSTRB(a2)	* strobe LOW
	move.b	#$3c,PSTRB(a2)	* destrobe

UL1NACK
	btst.b	#7,PACKN(a2)	*check for Ack
	beq.b		UL1NACK

	rts

* Aux - PTP RDR
PTPOutSt:
	move.w	#$00ff,d0		* set result to Ready
	rts
PTPOut:
	bsr		PTPOutSt		* see if punch ready
	tst.w		d0
	beq		PTPOut		* wait until data can go...
	rts

PTRInSt:
	move.w	#$00ff,d0		* set result to Ready
	rts
PTRIn:
	bsr		PTRInSt		* see if Reader ready
	tst.w		d0
	beq		PTRIn		* wait until data availible...
	move.w	#$001a,d0
	rts

	.end
