;HDDMA Set DMA Address Routine
;-----------------------------
;
mwdma:	mov	h,b		;Set DMA address
	mov	l,c
	shld	dmadma
	ret

;HDDMA Set Sector Routine
;------------------------
;
mwsec:	mov	a,c		;Load sector number
	dcr	a		;Range is actaully 0-16
	call	mwdspt		;Figure out head number -> (c)
	adi	mwspt		;Make sector number
	sta	mwsectr
	mov	a,c
	sta	mwhead		;Save head number
	ret

mwdspt:	mvi	c,0		;Clear head counter
mwdsptx:sui	mwspt		;Subtract a tracks worth of sectors
	rc			;Return if all done
	inr	c		;Bump to next head
	jmp	mwdsptx

mwreset:lhld	chan		;Save the command channel for a while
	shld	tempb
	lda	chan+2
	sta	tempb+2
	out	reset		;Send reset pulse to controller
	lxi	h,dmachan	;Address of command channel
	shld	chan		;Default channel address
	xra	a
	sta	chan+2		;Clear extended address byte
	shld	40h		;Set up a pointer to the command channel
	sta	42h
	lhld	dmarg0		;Save the track number
	push	h
	lxi	h,dmasel1	;Load arguments
	lda	mwdrive		;Get the currently selected drive
	ori	03ch		;Raise *step and *dir
	mov	m,a		;Save in drive select register
	lxi	d,5		;Offset to dmarg1
	dad	d
	mvi	m,stepdly	;Load step delay
	inx	h
	mvi	m,headdly	;Head settle delay
	inx	h
	mvi	m,sectsiz	;Sector size code
	inx	h
	mvi	m,dmalcon	;Load constants command
	call	mwissue		;Do load constants
	pop	h		;Restore the track number
	shld	dmarg0
	push	psw		;Save status
	lhld	tempb		;Restore memory used for the channel pointer
	shld	chan
	lda	tempb+2
	sta	chan+2
	pop	psw
	ret

;HDDMA Read/Write Sector Routines
;--------------------------------
;
mwread:	mvi	a,dmaread	;Load disk read commnd
	jmp	mwprep

mwwrite:mvi	a,dmawrit	;Load disk write command

mwprep:	sta	dmaop		;Save command channel op code
	mvi	c,band1
	lhld	dmarg0
	lxi	d,precomp
	call	mwhlcde
	jc	mwpreps

	mvi	c,band2
	lxi	d,lowcurr
	call	mwhlcde
	jc	mwpreps

	mvi	c,band3		;cylinder > low_current
mwpreps:lda	mwhead		;Load head address
	sta	dmarg2
	cma			;Negative logic for the controller
	ani	7		;3 bits of head select
	rlc			;Shove over to bits 2 - 4
	rlc
	ora	c		;Add on low current and precomp bits
	mov	c,a
	lda	mwdrive		;Load drive address
	ora	c		;Slap in drive bits
	sta	dmasel1		;Save in command channel head select
	lda	mwsectr		;Load sector address
	sta	dmarg3

	if	0		;Set to 1 for MW error reporter
mwissue:call	mwdoit		;Do desired operation
	rnc			;Do nothing if no error
	push	psw		;Save error info
	call	hexout		;Print status
	call	dspout		;   and a space
	lxi	h,dmachan
	mvi	c,16		;16 bytes of status
mwerr:	push	b
	push	h
	mov	a,m
	call	hexout		;Print a byte of the status line
	call	spout
	pop	h
	pop	b
	inx	h		;Bump command channel pointer
	dcr	c
	jnz	mwerr
	mvi	c,0ah		;Terminate with a CRLF
	call	pout
	mvi	c,0dh
	call	pout
	pop	psw		;Restore error status
	ret

dspout:	call	spout		;Print two spaces
spout:	mvi	c,' '		;Print a space
	jmp	pout

hexout:	push	psw		;Poor persons number printer
	rrc
	rrc
	rrc
	rrc
	call	nibout
	pop	psw
nibout:	ani	0fh
	adi	'0'
	cpi	'9'+1
	jc	nibok
	adi	27h
nibok:	mov	c,a
	jmp	pout

mwdoit	equ	$

	else

mwissue	equ	$		;Do a disk command, handle timeouts + errors

	endif

	lxi	h,dmastat	;Clear status byte
	mvi	m,0
	out	attn		;Start the controller
	lxi	d,0		;Time out counter (65536 retries)
mwiloop:mov	a,m		;Get status
	ora	a		;Set up CPU flags
	rm			;Return no error (carry reset)
	stc
	rnz			;Return error status
	xthl			;Waste some time
	xthl
	xthl
	xthl
	dcx	d		;Bump timeout counter
	mov	a,d
	ora	e
	jnz	mwiloop		;Loop if still busy
	stc			;Set error flag
	ret

mwptr:	lda	mwdrive		;Get currently select drives track address
	rlc
	mov	e,a
	mvi	d,0
	lxi	h,mwtab
	dad	d		;Offset into track table
	ret

mwtran:	mov	h,b
	mov	l,c
	inx	h
	ret

mwneghl:mov	a,h
	cma
	mov	h,a
	mov	a,l
	cma
	mov	l,a
	inx	h
	ret

mwhlmde:xchg
	call	mwneghl
	xchg
	dad	d
	ret

mwhlcde:mov	a,h
	cmp	d
	rnz
	mov	a,l
	cmp	e
	ret

mwtab	equ	$		;Collection of track addresses
	rept	maxmw
	db	0ffh		;Initialize to (way out on the end of the disk)
	db	0ffh
	endm
	db	0ffh

mwcurl:	db	0		;Current logical drive
mwdrive:db	0ffh		;Currently selected drive
mwhead:	db	0		;Currently selected head
mwsectr:db	0		;Currently selected sector

dmachan	equ	$		;Command channel area
dmasel0:db	0		;Drive select
dmastep:dw	0		;Relative step counter
dmasel1:db	0		;Head select
dmadma:	dw	0		;DMA address
	db	0		;Extended address
dmarg0:	db	0		;First argument
dmarg1:	db	0		;Second argument
dmarg2:	db	0		;Third argument
dmarg3:	db	0		;Fourth argument
dmaop:	db	0		;Operation code
dmastat:db	0		;Controller status byte
dmalnk:	dw	dmachan		;Link address to next command channel
	db	0		;extended address
tempb:	ds	4		;Command Channel Pointer Buffer

	endif
	page

	if	maxhd ne 0	;Want HDC3 or 4 controller included ?
;****************************************************************************
; Begin the HDCA Driver (DDRV4)
;******************************
;
;HDCA equates
;------------
;
hdorg	equ	50h			;Hard Disk Controller origin

hdstat	equ	hdorg			;Disk Status
hdcntl	equ	hdorg			;Disk Control
hdreslt	equ	hdorg+1			;Disk Results
hdcmnd	equ	hdorg+1			;Disk Commands
hdskomp	equ	hdorg+2			;Seek complete clear port (on HDC4)
hdfunc	equ	hdorg+2			;Function port
hddata	equ	hdorg+3			;Data port

;	Status port (50)

tkzero	equ	01h			;Track zero
opdone	equ	02h			;Operation done
complt	equ	04h			;Seek complete
tmout	equ	08h			;Time out
wfault	equ	10h			;Write fault
drvrdy	equ	20h			;Drive ready
index	equ	40h			;Delta index

;	Control port (50)

hdfren	equ	01h			;Enable external drivers
hdrun	equ	02h			;Enable controllers state machine
hdclok	equ	04h			;Clock source control bit, high = disk
hdwprt	equ	08h			;Write protect a drive

;	Result port (51)

retry	equ	02h			;Retry flag

;	Command port (51)

idbuff	equ	0			;Initialize data buffer pointer
rsect	equ	1			;Read sector
wsect	equ	5			;Write sector
isbuff	equ	8			;Initialize header buffer pointer

;	Function port (52)


hdtrak:	db	0ffh			;Track pointer for each drive
	db	0ffh			;All drive default to an uncalibrated
	db	0ffh			;   state (ff)
	db	0ffh

settle:	dw	0			;Time delay constant for head settle
	endif
	page

;********************
; End of Disk Drivers
;********************
;
; Cbios ram locations that don't need initialization.
;====================================================
;
	if	nostand ne 0	;Unallocated writting variables
unaloc:	db	0		;Unallocated write in progress flag
oblock:	dw	0		;Last unallocated block number written
unadrv:	db	0		;Drive that the block belongs to
	endif

cpmsec:	dw	0		;CP/M sector #

cpmdrv:	db	0		;CP/M drive #
cpmtrk: dw	0		;CP/M track #
truesec:dw	0		;Physical sector that contains CP/M sector

error:	db	0		;Buffer's error status flag
bufdrv:	db	0		;Drive that buffer belongs to
buftrk:	dw	0		;Track that buffer belongs to
bufsec:	dw	0		;Sector that buffer belongs to

alttrk:	dw	0		;Alternate track
altsec:	dw	0		;Alterante sector
lastdrv:db	0		;Last selected drive

;***************************************************************;
;								;
; DPB and DPH area.						;
;								;
;***************************************************************;

	if	maxhd ne 0

dphdsk	set	0		;Generate DPH's for the HDCA hard disks
	rept	maxhd
ldsk	set	0
	rept	hdlog
	dphgen	hd,%dphdsk,dpbhd,%ldsk
ldsk	set	ldsk+1
dphdsk	set	dphdsk+1
	endm
	endm

	if	m26 ne 0
dpbhd0:	dw	1024		;CP/M sectors/track
	db	5		;BSH
	db	31		;BLM
	db	1		;EXM
	dw	2015		;DSM
	dw	511		;DRM
	db	0ffh		;AL0
	db	0ffh		;AL1
	dw	0		;CKS
	dw	1		;OFF
	db	3		;SECSIZ

dpbhd1:	dw	1024		;CP/M sectors/track
	db	5		;BSH
	db	31		;BLM
	db	1		;EXM
	dw	2015		;DSM
	dw	511		;DRM
	db	0ffh		;AL0
	db	0ffh		;AL1
	dw	0		;CKS
	dw	64		;OFF
	db	3		;SECSIZ

dpbhd2:	dw	1024		;CP/M sectors/track
	db	5		;BSH
	db	31		;BLM
	db	1		;EXM
	dw	2047		;DSM
	dw	511		;DRM
	db	0ffh		;AL0
	db	0ffh		;AL1
	dw	0		;CKS
	dw	127		;OFF
	db	3		;SECSIZ
	endif

	if	m10 ne 0
dpbhd0:	dw	336		;CP/M sectors/track
	db	5		;BSH
	db	31		;BLM
	db	1		;EXM
	dw	1269		;DSM
	dw	511		;DRM
	db	0ffh		;AL0
	db	0ffh		;AL1
	dw	0		;CKS
	dw	1		;OFF
	db	3		;SECSIZ

dpbhd1:	dw	336		;CP/M sectors/track
	db	5		;BSH
	db	31		;BLM
	db	1		;EXM
	dw	1280		;DSM
	dw	511		;DRM
	db	0ffh		;AL0
	db	0ffh		;AL1
	dw	0		;CKS
	dw	122		;OFF
	db	3		;SECSIZ
	endif

	if	m20 ne 0
dpbhd0:	dw	672		;CP/M sectors/track
	db	5		;BSH
	db	31		;BLM
	db	1		;EXM
	dw	2036		;DSM
	dw	511		;DRM
	db	0ffh		;AL0
	db	0ffh		;AL1
	dw	0		;CKS
	dw	1		;OFF
	db	3		;SECSIZ

dpbhd1:	dw	672		;CP/M sectors/track
	db	5		;BSH
	db	31		;BLM
	db	1		;EXM
	dw	2036		;DSM
	dw	511		;DRM
	db	0ffh		;AL0
	db	0ffh		;AL1
	dw	0		;CKS
	dw	98		;OFF
	db	3		;SECSIZ

dpbhd2:	dw	672		;CP/M sectors/track
	db	5		;BSH
	db	31		;BLM
	db	1		;EXM
	dw	1028		;DSM
	dw	511		;DRM
	db	0ffh		;AL0
	db	0ffh		;AL1
	dw	0		;CKS
	dw	195		;OFF
	db	3		;SECSIZ
	endif
	endif			;End of HD DPH's and DPB's

; DPH's for DJ2DB
;----------------
;
	if	maxfd ne 0
dn	set	0
	rept	maxfd
	dphgen	fd,%dn,0,0
dn	set	dn+1
	endm
	endif

	if	maxmw ne 0

;***************************************************************;
;								;
; mwsectp is the number of 128 byte sectors per cylinder.	;
; mwsectp = 72 * heads						;
;								;
; mwtrks is the total number of data cylinders.			;
; mwtrks = tracks - 1						;
;								;
;***************************************************************;

	if	st506 ne 0
	mwsecpt	equ	288		;Sectors per track
	mwtrks	equ	152		;Total data tracks
	endif

	if	st412 ne 0
	mwsecpt	set	288
	mwtrks	set	305
	endif

	if	cm5619 ne 0
	mwsecpt	set	432
	mwtrks	set	305
	endif

dphdsk	set	0		;Generate DPH's for the HDDMA hard disks
	rept	maxmw
ldsk	set	0
	rept	mwlog
	dphgen	mw,%dphdsk,dpbmw,%ldsk
dphdsk	set	dphdsk+1
ldsk	set	ldsk+1
	endm
	endm

off	set	1			;Initial system track offset
trkoff	set	8192/(mwsecpt/8)+1	;The number of tracks in a partition
blocks	set	mwsecpt/8*mwtrks	;The number of blocks on the drive
psize	set	trkoff*(mwsecpt/8)	;The number of blocks in a partition
ldsk	set	0

	rept	blocks/8192	;Generate some 8 megabyte DPB's
	dpbgen	mw,%ldsk,%mwsecpt,5,31,1,2047,1023,0ffh,0ffh,0,%off,4
off	set	off+trkoff
blocks	set	blocks-psize
ldsk	set	ldsk+1
	endm
blocks	set	blocks/4
	if	blocks gt 256	;If there is any stuff left, then use it
blocks	set	blocks-1
	dpbgen	mw,%ldsk,%mwsecpt,5,31,1,%blocks,1023,0ffh,0ffh,0,%off,4
	endif
	endif

;*********************************************************
;Begin Definitions for the Console and List Device Drivers
;*********************************************************
;
;Define Printer Character Constants
;----------------------------------
acr	equ	0Dh		;Carriage return
alf	equ	0Ah		;Line Feed
clear	equ	1Ah		;Clear screen on an ADM 3
xoff	equ	13h		;Xoff character
xon	equ	11h		;Xon character

	if	(contyp eq 2) or (lsttyp ge 2)	;Multio or Wunderbuss

;Multio/Wunderbuss Equates
;-------------------------
;	The following equates will define the Decision I mother
;	board I/O or the Multi I/O environments if needed.
;
;Location Definitions
;--------------------
mbase	equ	48h		;Base address of Multi I/O or Decision I
rbr	equ	mbase		;Read data buffer
thr	equ	mbase		;Tranmitter data buffer
dll	equ	mbase		;Divisor (lsb)
strobe	equ	mbase		;parallel port strobe out
status	equ	mbase		;parallel port status in
dlm	equ	mbase+1		;Divisor (msb)
ier	equ	mbase+1		;Interupt enable register
sensesw	equ	mbase+1		;Sense switches, only in gp 06
data	equ	mbase+1		;parallel port data buffer
clk	equ	mbase+2		;WB14 printer select port
lcr	equ	mbase+3		;Line control register
mcr	equ	mbase+4
lsr	equ	mbase+5		;Line status register
msr	equ	mbase+6
grpsel	equ	mbase+7		;Group select port
;
;Define Transmitter/Reciever Mask Bytes
;--------------------------------------
dr	equ	01h		;Line status DR bit
cts	equ	10h		;Clear to send
dsr	equ	20h		;Data set ready
thre	equ	20h		;Status line THRE bit
dlab	equ	80h		;Divisor latch access bit
;
wls0	equ	1		;Word length select bit 0
wls1	equ	2		;Word length select bit 1 for 8 bit word
stb	equ	4		;Stop bit count - 2 stop bits
;
; Define Modem Control Register bits
;-----------------------------------
dtrenb	equ	1		;DTR enable
rtsenb	equ	2		;RTS enable
;
;Define group select Masks
;-------------------------
spp	equ	0		;select parallel port
s0	equ	01h		;Group number (0-3)
s1	equ	02h
smask	equ	03h
bank	equ	04h
enint	equ	08h
restor	equ	10h		;Printer restore on Multi I/O
busy	equ	20h		;parallel printer busy mask
denable	equ	20h		;Driver enable on Multi I/O
;
;Group Port Assignments
;----------------------
congrð	eqõ	±		;Consolå porô (1=p1¬ 2=p2¬ 3=p3)
lstgrp	equ	3		;Printer port (1=p1, 2=p2, 3=p3)

	endif			;For Multio/Wunderbuss Definitions
	page

;****************************
;Begin Console Device Drivers
;****************************

	if	contyp eq 0
;************************
;Begin Prom Patch (CDRV0)
;************************
;	This driver simply defines the four jumps normally needed to get to
;	your actual console drivers. The assumption is that you already have
;	these drivers in a ROM; And, furthermore, that the ROM'ed drivers
;	exactly match the specs given in the CPM alteration guide for CONIN,
;	CONOUT and CONST. Conint is involked du