	title	'Root module of loader BIOS for CP/M 3.0'

	; version 1.0 3-30-83
	; this is the root module provided by digital research
	; modified for use with cpmldr by Edwin E. Smith
	; Tarbell Electronics

true	equ	-1
false	equ	not true

banked	equ	false
	

;		  Copyright (C), 1982
;		 Digital Research, Inc
;		     P.O. Box 579
;		Pacific Grove, CA  93950


;   This is the invariant portion of the modular BIOS and is
;	distributed as source for informational purposes only.
;	All desired modifications should be performed by
;	adding or changing externally defined modules.
;	This allows producing "standard" I/O modules that
;	can be combined to support a particular system 
;	configuration.

	maclib	z80		;use z80 library

    ; user defined character I/O routines

	extrn	?co,?cost		; each take device in <B>
	extrn	?cinit			; (re)initialize device in <C>

    ; disk communication data items

	extrn	@dtbl			; table of pointers to XDPHs
	public	@adrv,@rdrv,@trk,@sect	; parameters for disk I/O
	public	@dma,@cnt		;    ''       ''   ''  ''


    ; general utility routines

	public	?pmsg		; print message

    ; External names for BIOS entry points

	public	?boot,?cono
	public	?home,?sldsk,?sttrk,?stsec,?stdma,?read
	public	?sctrn
	public	?conos
	public	?mltio


    ; BIOS Jump vector.

		; All BIOS routines are invoked by calling these
		;	entry points.

?boot:	jmp	boot	; initial entry on cold start
?wboot:	jmp	empret	; reentry on program exit, warm start

?const:	jmp	empret	; return console input status
?conin:	jmp	empret	; return console input character
?cono:	jmp	conout	; send console output character
?list:	jmp	empret	; send list output character
?auxo:	jmp	empret	; send auxilliary output character
?auxi:	jmp	empret	; return auxilliary input character

?home:	jmp	home	; set disks to logical home
?sldsk:	jmp	seldsk	; select disk drive, return disk parameter info
?sttrk:	jmp	settrk	; set disk track
?stsec:	jmp	setsec	; set disk sector
?stdma:	jmp	setdma	; set disk I/O memory address
?read:	jmp	read	; read physical block(s)
?write:	jmp	empret	; write physical block(s)

?lists:	jmp	empret	; return list device status
?sctrn:	jmp	sectrn	; translate logical to physical sector

?conos:	jmp	conost	; return console output status
?auxis:	jmp	empret	; return aux input status
?auxos:	jmp	empret	; return aux output status
?dvtbl:	jmp	empret	; return address of device def table
?devin:	jmp	empret	; change baud rate of device

?drtbl:	jmp	empret	; return address of disk drive table
?mltio:	jmp	multio	; set multiple record count for disk I/O
?flush:	jmp	empret	; flush BIOS maintained disk caching

?mov:	jmp	?move	; block move memory to memory
?tim:	jmp	empret	; Signal Time and Date operation
?bnksl:	jmp	empret	; select bank for code execution and default DMA
?stbnk:	jmp	empret	; select different bank for disk I/O DMA operations.
?xmov:	jmp	empret	; set source and destination banks for one operation

	jmp	0	; reserved for future expansion
	jmp	0	; reserved for future expansion
	jmp	0	; reserved for future expansion

empret	xra	a
	ret

; block move routine bc is byte count
; de is source and hl is destination

?move	xchg		;swap source and destination
	ldir		;do the move
	xchg		;swap back
	ret

	; BOOT
	;	Initial entry point for system startup.
boot:
	mvi	c,0		; initialize device 0 console
	call	?cinit
	lxi	b,0*256+0
	lxi	h,@dtbl		; init logical disk drive 0
	mov	e,m
	inx	h
	mov	d,m
	inx	h		; grab @drv entry
	xchg			; XDPH address in <HL>
	dcx	h
	dcx	h
	mov	a,m
	sta	@RDRV		; get relative drive code
	mov	a,c
	sta	@ADRV		; get absolute drive code
	dcx	h		; point to init pointer
	mov	d,m
	dcx	h
	mov	e,m		; get init pointer
	xchg
	call	ipchl		; call init routine
	ret			;return to cpmldr



	;	Console Output.  Send character in <C>
	;			to all selected devices

conout:	
	mvi	b,0		;device 0
	jmp	?co

	; CONOST
	;	Console Output Status.  Return true if
	;		all selected console output devices
	;		are ready.

conost:
	mvi	b,0		;device 0
	jmp	?cost

;	Utility Subroutines


ipchl:				; vectored CALL point
	pchl


?pmsg:		; print message @<HL> up to a null
		; saves <BC> & <DE>
	push	b
	push	d
pmsg$loop:
	mov	a,m
	ora	a
	jz	pmsg$exit
	mov	c,a
	push	h
	call	?cono
	pop	h
	inx	h
	jmp	pmsg$loop
pmsg$exit:
	pop	d
	pop	b
	ret

;	Disk I/O interface routines


	; SELDSK
	;	Select Disk Drive.  Drive code in <C>.
	;		Invoke login procedure for drive
	;		if this is first select.  Return
	;		address of disk parameter header
	;		in <HL>

seldsk:
	mov	a,c
	sta	@adrv		; save drive select code
	mov	l,c
	mvi	h,0
	dad	h		; create index from drive code
	lxi	b,@dtbl
	dad	b		; get pointer to dispatch table
	mov	a,m
	inx	h
	mov	h,m
	mov	l,a		; point at disk descriptor
	ora	h
	rz			; if no entry in table, no disk
	mov	a,e
	ani	1
	jnz	not$first$select	; examine login bit
	push	h
	xchg			; put pointer in stack & <DE>
	lxi	h,-2
	dad	d
	mov	a,m
	sta	@RDRV		; get relative drive
	lxi	h,-6
	dad	d		; find LOGIN addr
	mov	a,m
	inx	h
	mov	h,m
	mov	l,a		; get address of LOGIN routine
	call	ipchl		; call LOGIN
	pop	h		; recover DPH pointer
not$first$select:
	ret


	; HOME
	;	Home selected drive.  Treated as SETTRK(0).

home:
	lxi	b,0		; same as set track zero


	; SETTRK
	;	Set Track. Saves track address from <BC> 
	;		in @TRK for further operations.

settrk:
	mov	l,c
	mov	h,b
	shld	@trk
	ret


	;SETSEC
	;	Set Sector.  Saves sector number from <BC>
	;		in @sect for further operations.

setsec:
	mov	l,c
	mov	h,b
	shld	@sect
	ret


	; SETDMA
	;	Set Disk Memory Address.  Saves DMA address
	;		from <BC> in @DMA and sets @DBNK to @CBNK
	;		so that further disk operations take place
	;		in current bank.

setdma:
	mov	l,c
	mov	h,b
	shld	@dma
	ret

	; SECTRN
	;	Sector Translate.  Indexes skew table in <DE>
	;		with sector in <BC>.  Returns physical sector
	;		in <HL>.  If no skew table (<DE>=0) then
	;		returns physical=logical.

sectrn:
	mov	l,c
	mov	h,b
	mov	a,d
	ora	e
	rz
	xchg
	dad	b
	mov	l,m
	mvi	h,0
	ret


	; READ
	;	Read physical record from currently selected drive.
	;		Finds address of proper read routine from
	;		extended disk parameter header (XDPH).

read:
	lhld	@adrv
	mvi	h,0
	dad	h		; get drive code and double it
	lxi	d,@dtbl
	dad	d		; make address of table entry
	mov	a,m
	inx	h
	mov	h,m
	mov	l,a		; fetch table entry
	push	h		; save address of table
	lxi	d,-8
	dad	d		; point to read routine address
	mov	a,m
	inx	h
	mov	h,m
	mov	l,a		;get address of routine
	pop	d		;recover address of table
	dcx	d
	dcx	d		; point to relative drive
	ldax	d
	sta	@rdrv		; get relative drive code and post it
	inx	d
	inx	d		; point to DPH again
	pchl			;leap to driver


	; MULTIO
	;	Set multiple sector count. Saves passed count in
	;		@CNT

multio:
	sta	@cnt
	ret

    ; disk communication data items

@adrv	ds	1		; currently selected disk drive
@rdrv	ds	1		; controller relative disk drive
@trk	ds	2		; current track number
@sect	ds	2		; current sector number
@dma	ds	2		; current DMA address
@cnt	db	0		; record count for multisector transfer

	end
