	title	'hdsyside, harddisk i/o module'

	.z80
	cseg
;
; Update:	
; 20.05.2006	ide_init & wr_lba	Set LBA Modus
;		ide_ready_busy		Time Out Check	
;		ide_hard_reset		call ide_wait_not_busy
; 22.05.2006	hdlogin			nothing to do
;
; 25.05.2006	ide_hard_reset		10ms delay
;		hd_init			only once
;		hdread, hdwrite and
;		ide_wait_not_busy	optimized
;
; 05.02.2008	read_lp			nop
; 25.05.2010    hdread, hdwrite         ohne ei/di
;

public	hdread,hdwrite,hdlogin,hdinit

extrn	@adrv,@rdrv,@dma,@trk,@sect
extrn	@dbnk,@cbnk
extrn	@ermde
extrn	?wboot,?pmsg,?bank
extrn   ?pderr

maclib	BIOSDEF

	dseg

;
; HD Login
;
hdlogin:				; nothing to do
	ret

;
; HD hard init, important when boot from FDD
;
hdinit:
	ld	a,0c9h			; only once
	ld	(hdinit),a
	call	ide_hard_reset		; Drive Reset
	call	ide_init		; Drive Init
	ret

;
; Initalize the drive
;
ide_init:
	ld	a,ide_head
	ld	c,11100000b	; select the device
				; x1x00000b LBA master
				; x1x10000b LBA slave
				; x0x00000b CHS master
				; x0x10000b CHS slave
	call	ide_wr_8
				; wait for READY
	ld	de,0
ide_rdy_bsy:
	dec	de
	ld	a,d
	or	e
	jr	z,ide_not_rdy	; timeout
	ld	a,ide_status
	call	ide_rd_8
	ld	a,c
	bit	6,a		; if on then ready
	jr	z, ide_rdy_bsy	; wait for READY bit to be set	
	bit	7,a		; if on then busy
	jr	nz, ide_rdy_bsy	; wait for BUSY bit to be clear
	ret
ide_not_rdy:			; timeout
	ld	hl,nomsg
	call	?pmsg
	ret

;
; HD hard reset
;
ide_hard_reset:
	ld	a, pio_rdw		; PIO Read/Write Mode
	out	(pio_cfg), a
	ld	a, ide_rst		; hard reset drive
	out	(pio_ctl), a
	push	bc
	ld	bc,3000			; ca. 10 ms delay
wloop:
	dec	bc
	ld	a,b
	or	c
	jp	nz,wloop
	pop	bc
	xor	a			; no ide control lines asserted
	out	(pio_ctl), a
	ret

;
; Wait for DRQ  
;
ide_wait_drq:
	ld	a,ide_status
	call	ide_rd_8
	ld	a,c
	bit	7,a		; wait for BUSY to be clear
	jr	nz, ide_wait_drq
	bit	3,a		; wait for DRQ to be set
	jr	z, ide_wait_drq
	ret

;
; Wait for BUSY to be clear
;	
ide_wait_not_busy:
	ld	a,ide_status
	call	ide_rd_8
	ld	a,c
	bit	7,a
	jr	nz,ide_wait_not_busy
	ret

;
; 8 bit read
;
ide_rd_8:
	out	(pio_ctl),a	; drive address onto control lines
	or	ide_rd		; set read pin on
	out	(pio_ctl),a
	nop			; delay	
	in	a,(pio_lsb)	; read lower byte
	ld	c,a
	xor	a		; set all control pins off
	out	(pio_ctl),a
	ret

;
; 8 bit write 
;
ide_wr_8:
	ld	d,a		; Address
	ld	a, pio_wr
	out	(pio_cfg),a	; PIO Write Mode
	ld	a,c
	out	(pio_lsb),a	; Drive lower lines
	ld	a,d		; Drive address onto control lines
	out	(pio_ctl),a
	or	ide_wr		; Drive address, write pin
	out	(pio_ctl),a
	nop			; delay
	ld	a,d		; deassert write pin
	out	(pio_ctl),a
	ld	a,pio_rdw	; PIO Read/Write Mode	
	out	(pio_cfg),a
	ret		

;
; 16 bit read
;
hdread:
	call	ide_wait_not_busy
	call	wr_lba			; set sector
	ld	a,ide_command		; command register
	ld	c,ide_cmd_read
	call	ide_wr_8
	call	ide_wait_drq
	call	read_data
	call	ide_wait_not_busy
	and	10001001b		; busy, DRQ or error
	ret	z			; no
	ld	hl,readmsg
	ld	(opname),hl
	jr	get_err	

;
; 16 bit write
;
hdwrite:
	call	ide_wait_not_busy
	call	wr_lba			; set sector
	ld	a,ide_command		; command register
	ld	c,ide_cmd_write
	call	ide_wr_8
	call	ide_wait_drq
	call	write_data
	call	ide_wait_not_busy
	and	10001001b		; busy, DRQ or error
	ret	z			; no
	ld	hl,writemsg
	ld	(opname),hl
;	jr	get_err	

;
; read error register
;
get_err:
	ld	a,ide_err
	call	ide_rd_8
	ld	a,c
	ld	(errcde),a		; save for message
	jp	hderror

;
; Sektor=8bit, Track=16bit = 24bit = 8,388608GB max.
; 1110 Master, 1111 Slave LBA
; 1010 Master, 1011 Slave CHS
;
wr_lba:
;	ld	a,(lba+3)		; head
;	and	0fh			; 0000 0-15
;	or	11100000b		; 0e0h / 1110 Master LBA
;	ld	c,a

	ld	c,11100000b		; 0e0h / 1110 Master LBA, Head 0
	ld	a,ide_head
	call	ide_wr_8

	ld	hl,(@trk)		; track
	ld	c,h			; cyl msb
	ld	a,ide_cyl_msb
	call	ide_wr_8

	ld	c,l			; cyl lsb
	ld	a,ide_cyl_lsb
	call	ide_wr_8

	ld	a,(@sect)		; sector 0,1,2,3,4....
	ld	c,a
	ld	a,ide_sector
	call	ide_wr_8		; set sector

	ld	c,1			; transfer one sector
	ld	a,ide_sec_cnt
	call	ide_wr_8
	xor	a
	ret

	cseg
;
; read
;
read_data:
	ld	b,0		; 256 words, 512 bytes per sector
	ld	hl,(@dma)	; target
	ld	a,(@dbnk)	; bank
	call	?bank		; set
read_lp:
	ld	a,ide_data
	out	(pio_ctl),a	; drive address onto control lines
				; and reset read pin (loop)  
	or	ide_rd
	out	(pio_ctl),a	; set read pin
	nop			; delay
	in	a,(pio_lsb)	; read the lower byte
	ld	(hl),a
	inc	hl
	in	a,(pio_msb)	; read the upper byte	
	ld	(hl),a
	inc	hl
	djnz	read_lp
	xor	a		; set all control pins of
	out	(pio_ctl),a
	ld	a,(@cbnk)
	call	?bank
	ret

;
; write
;
write_data:
	ld	b,0		; 256 words, 512 bytes per sector
	ld	hl,(@dma)	; source
	ld	a,(@dbnk)	; bank
	call	?bank		; set
	ld	a, pio_wr
	out	(pio_cfg),a	; PIO Write Mode
write_lp:
	ld	a,(hl)
	out	(pio_lsb),a	; Drive lower lines with lsb
	inc	hl
	ld	a,(hl)
	out	(pio_msb),a	; Drive upper lines with msb
	inc	hl
	ld	a,ide_data	
	out	(pio_ctl),a	; Drive address onto control lines
	or	ide_wr		; 
	out	(pio_ctl),a	; set write pin
	nop			; delay
	ld	a,d		; reset write pin
	out	(pio_ctl),a
	djnz	write_lp
	ld	a,pio_rdw	; PIO Read/Write Mode	
	out	(pio_cfg),a
	ld	a,(@cbnk)
	call	?bank
	ret		

	dseg
;
; r/w error
;
hderror:
	ld	a,(@ermde)
	cp	0ffh
	jp	z,harderror
	call	?pderr
	ld	hl,(opname)
	call	?pmsg
	ld	a,(errcde)
	ld	hl,errtbl
errm1:
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	add	a,a
	push	af
	push	hl
	ex	de,hl
	call	c,?pmsg
	ex	de,hl
	pop	hl
	pop	af
	jp	nz,errm1
harderror:
	ld	a,1
hard1error:
	ret

	cseg
;
; Buffer
;
errcde:	defb	0

	dseg

readmsg:
	db	', read',0
writemsg:
	db	', write',0
opname:
	dw	readmsg

errtbl:
	defw	b7msg
	defw	b6msg
	defw	b5msg
	defw	b4msg
	defw	b3msg
	defw	b2msg
	defw	b1msg
	defw	b0msg

;
; hd error msg
;
b7msg:	defm	' ',0
b6msg:	defm	', Uncorrectable Data Error',0
b5msg:	defm	', Media Changed',0
b4msg:	defm	', ID Not Found',0
b3msg:	defm	', Media Change Requested',0
b2msg:	defm	', Aborted Command',0
b1msg:	defm	', Track 0 Not Found',0
b0msg:	defm	', Address Mark Not Found',0

nomsg:	defm	', !! HDD NOT FOUND !!',0
;
	end
;
; ende 



