;////////////////////////////////////////////////////////////////////////
;									/
;	Interface between the disk formatter program and the disk	/
;	driver.  The formatter is running in user non-seg mode, and	/
;	the disk driver must run supervisor segmented.  Thus this	/
;	routine must bridge the gap both ways.				/
;									/
;									/
;	Written by F Zlotnick (Zilog) 29 Oct 82				/
;									/
;////////////////////////////////////////////////////////////////////////

	.global	_writ_im
	.global	_bdos


ARG1	.equ	2
ARG2	.equ	4
ARG3	.equ	6
ARG4	.equ	8

SUPV	.equ	62		; Supervisor State BDOS call
BDOS_SC	.equ	2		; System call number

;
;	Space to save registers
;
regsave:
	.block	14
;
;	Following macro stolen from Steve Savitzky
;

scall	.MACRO			; segmented address argument

	.word	05F00h		; 5F00 = segmented call
	.long	?1

	.ENDM


.code	.sect
;
;	Start by saving registers 8 - 14. C expects this.
;

_writ_im:
	sub	r15,#14			; Make space on the stack...
	ldm	@r15,r8,#7		; ...and copy r8-r14 there.
;
;	Put arguments where the driver expects them:
;		rr10 = segmented address of the buffer
;		r9 = logical block number (see description below)
;		r8 = number of blocks to transfer = 1
;		rh7 = drive number (0, or 1, or 10 for a hard disk)
;		rl7 = Command = 2 for format (Write Track Cmd)
;
	ldl	rr10,ARG4+14(r15)	; Segmented buffer address
	ld	r9,#0			; Block #
	ld	r8,#1			; # Blocks
	ldb	rh7,ARG1+15(r15)	; Drive
	ldb	rl7,#2			; Command
;
;	Must set up r9 to contain the track and side number in a strange
;	way.  The track number goes in shifted left logical, 5 bits, and
;	then bit 4 is set if it's side 1, or don't set it if it's side zero.
;	Weird.  We use r1 as a scratch register.
;
	ld	r1,ARG2+14(r15)		; Track
	sll	r1,#5			; That's what the driver expects
	test	ARG3+14(r15)		; Side
	jr	z,side0
	set	r1,#4			; Side flag in logical block #
side0:
	ld	r9,r1			; Where driver expects it.
;	Before calling the BDOS, save regs 7-13.
;
	ldm	regsave,r7,#7
;
;	Now we must call the BDOS to get into segmented supervisor
;	mode.  Dangerous!
;
	ldl	rr6,#0			; Must be long
	ld	r5,#SUPV		; BDOS function
	sc	#BDOS_SC
;
;	Restore registers 7-13
;
	.word	05C01h
	.word	0706h
	.word	8A00h
	.word	regsave
;
;	Watch it!  Now in system mode, and the stack pointer isn't yours!
;
	scall	84000068h
;
;	That's all in segmented mode;  Now lets get back to
;	user nonseg as fast as possible.
;
	ldctl	r1,FCW			; Get FCW in r1
	and	r1,#03FFFh		; Mask seg and sysmode
;
;//////////////////////////////////////////////////////////////////
;                                                                 /
;       The following sequence has been restored from diskio.z8k, /
;       because the original file was corrupt. I'm not sure if    /
;       it works, so please let me know the results if you have   /
;       the possibility to try. Thanks, Gaby Chaudry              /
;                                                                 /
;//////////////////////////////////////////////////////////////////
;
	ldctl	FCW,r1			; BOOM!
			;r8  = block count not transferred
			;rh7 = #retries
			;rl7 = final error code (RETURNED)
			;rh6 = error retried

	and	r7,#0FFh	;value returned in r7

	ldm	r8,@r15,#7	;restore regs
	inc	r15,#14
	ret


