
;****************************************************************
;*								*
;*	CP/M-Z8K Basic Disk Operating System interface module	*
;*		For "C" version of CP/M-Z8K    			*
;*								*
;*	Copyright (c) 1982 Digital Research, Inc.		*
;*								*
;*	Version 0.2 -- September 22, 1982			*
;*	Z8000 version -- 821014					*
;*								*
;****************************************************************

__text:	.sect

;****************************************************
;*
;*  Globals
;*
;****************************************************


	.global	_bios1		; 6 BIOS entry points from BDOS
	.global	_bios2
	.global	_bios3
	.global	_bios4
	.global	_bios5
	.global _bios6
	.global	_traphnd	; trap #2 handler
	.global	_swap		; byte swapper
	.global	_udiv		; unsigned divide routine

;****************************************************
;*
;* Externals and Constants
;*
;****************************************************

	.global	__bdos		; BDOS entry point in bdosmain

;* The following were put in so that all BDOS modules were
;* referenced, so they could be put in a library

	.global _constat	; references conbdos.o
	.global _dirscan	; references dskutil.o
	.global _create		; references fileio.o
	.global _bdosrw		; references bdosrw.o

biosf	.equ 50
setsupf	.equ 62

;****************************************************
;*
;* Trap Handler
;*
;* rcode = bdos(command, (long)parameter)
;*
;*	rr6: parameter
;*	 r5: command
;*	   returns
;*	 r7: result
;*
;*	called SEGMENTED with caller's registers
;*	saved on stack, and all but rr0 intact in
;*	registers.
;*
;*	Calls __bdos(cmd, (word)param, (addr)param)
;*
;****************************************************

_traphnd:
	ldctl	r0,FCW		;go non-segmented
	res	r0,#15
	ldctl	FCW,r0
;
;	check for functions handled by assembly 
;	language routines
;
	cp	r5,#setsupf	; set system mode
	jr eq	setsup
	cp	r5,#biosf	; call bios direct
	jr eq	bioscall
;
;	If caller was non-segmented user program,
;	get segment number from his program counter
;
	ldl	rr2,rr6
	ld	r0,34+4(r15)	;caller's fcw
	bit	r0,#15
	jr nz	callC		;  segmented
	bit	r0,#14
	jr nz	callC		;  system
	ld	r2,36+4(r15)	;  user nonseg.
				;  set seg from PC
;
;	Call C main routine
;
callC:
	pushl	@r15,rr2	; xaddr param.
	push	@r15,r7		; word  param
	push	@r15,r5		; command
	call	__bdos
	add	r15,#8
;
;	Return result in caller's r7.
;	Restore segmented mode and return
;
	ld	14+4(r15),r7

	ldctl	r0,FCW		;go segmented
	set	r0,#15
	ldctl	FCW,r0

	ret

;
; direct BIOS call function
;
bioscall:
;
;	If caller was non-segmented user program,
;	get segment number from his program counter
;
	ld	r0,34+4(r15)	;caller's fcw
	bit	r0,#15
	jr nz	callBios	;  segmented
	bit	r0,#14
	jr nz	callBios	;  system
	ld	r6,36+4(r15)	;  user nonseg.
	ld	r2,r6		;  set seg from PC
				;  save in r2, also
	ldctl	r0,FCW		;go segmented
	set	r0,#15
	ldctl	FCW,r0

	ldm	r3,@r6,#5	;get parameters
	ld	r4,r2		;set segments
	ld	r6,r2

	sc	#3		;call BIOS
	ret			;done

callBios:
	ldctl	r0,FCW		;go segmented
	set	r0,#15
	ldctl	FCW,r0

	ldm	r3,@r6,#5	;get parameters

	sc	#3		;call BIOS
	ret			;done
;
; Set supervisor mode procedure -- VERY DANGEROUS
;
;	Status is set to SYSTEM, SEGMENTED.
;	Interrupt status will be that at the time
;	of the call.
;
setsup:
	ld	r0,34+4(r15)
	set	r0,#14		;set system 
	set	r0,#15		;    and segmented
	ld	34+4(r15),r0	;  in user FCW

	ldctl	r0,FCW		;go segmented
	set	r0,#15
	ldctl	FCW,r0

	ret			;return

;****************************************************
;*
;* BIOS Interface Routines
;*
;*  Note - there are 6 BIOS entry points from the BDOS, 
;*	labelled BIOS1 - BIOS6, depending on the 
;*	parameters passed.
;*
;****************************************************

_bios5:
; For BIOS functions sectran and set exception vector
; (funct, word, long) 	offsets 2, 4, 6

	ldl	rr6,6(r15)	; get 2nd param (long)
	jp	_bios2		; join common routine

_bios4:
; For BIOS function seldsk
; (func, word, word) 	offsets 2, 4, 6
	ld	r7,6(r15)	; get 2nd param (word)
	clr	r6		; extend to ulong
	jp	_bios2		; join common routine

_bios3:
; For BIOS function set dma
; (func, long)		offsets 2, 4
	ldl	rr4,4(r15)	; get 1st param (long)
	subl	rr6,rr6		; clear second
	jp	_bios1		; join common routine

_bios2:
; For all BIOS functions with a word parameter
; (func, word)		offsets 2, 4
	ld	r5,4(r15)	; get 1st param (word)
	clr	r4		; extend to ulong

_bios6:
_bios1:
; For all BIOS functions that have no parameter 
; other than function number
	ld	r3,2(r15)	; get function number
	sc	#3		; do BIOS call
	ret			; returns value in rr7

;****************************************************
;*
;*  Utility Subroutines
;*
;*  swap(word)		swap bytes of a word
;*
;*  uword udiv((long)   dividend, 
;*	       (uword)  divisor, 
;*	       (uword *)rem    )
;*
;****************************************************

_swap:
	ld	r7,2(r15)
	exb	rh7,rl7
	ret

_udiv:
	ldl	rr2,2(r15)	;long dividend
	subl	rr0,rr0		;  as unsigned quad
	ld	r5,6(r15)	;word divisor
	clr	r4		;  as unsigned long
	ldl	rr6,8(r15)	;->result

	divl	rq0,rr4

	ld	@r7,r1		; store remainder
	ld	r7,r3		; return quotient
	clr	r6


	ret


