summaryrefslogtreecommitdiff
path: root/z180/cfboot.180
blob: 083aa4c7789a86e57ca473d3499ab58b221f21b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
	TITLE 'CF cold boot loader'

    ; Port Address Equates

	include config.inc
	include z180reg.inc

    ; IDE Task File Register Definitions

IDEDat	equ	IDEBASE+0	; Data Register
IDEErr	equ	IDEBASE+1	; Error Register
IDEFeat	equ	IDEBASE+1	; Feature Register
IDESCnt	equ	IDEBASE+2	; Sector Count
IDESNum	equ	IDEBASE+3	; Sector Number
IDECLo	equ	IDEBASE+4	; Cylinder Low
IDECHi	equ	IDEBASE+5	; Cylinder High
IDESDH	equ	IDEBASE+6	; Drive and Head
IDECmd	equ	IDEBASE+7	; Command / Status

    ; IDE Hard disk commands:

CmdNOP	equ	00h		; NOP Command
CmdHome	equ	10h		; Recalibrate
CmdRd	equ	20h		; Read Sector
CmdWr	equ	30h		; Write Sector
CmdId	equ	0ECh		; Read ID
CmdSF	equ	0EFh		; Set Feature

    ; Partition Table Structures

PTYPE	equ	4
PSTART	equ	8
PSIZE	equ	12

    ; Partition table id
    ; (see http://www.win.tue.nl/~aeb/partitions/partition_types-1.html)

PARTID1_FAT16	equ	00EH
PARTID2_FAT16	equ	006H
PARTID_CPM	equ	052H


DEBUG		equ	false		; not used
DO_WAIT_NBSY	equ	false
RUN_TPA		equ	false

   if RUN_TPA
base		equ	0100h
   else
base		equ	0
   endif

;-------------------------------------------------------------------------------

	aseg

	org	base

	jr	start

para:		equ	$
loadaddr:	dw	base+100h
sec_start:	db	0
sec_cnt:	db	7
part_id:	db	PARTID_CPM
timeout:	dw	10000
stages:		db	number_of_stages
done:		db	0
result:		db	0
ide_result:	db	0,0

o_part_id	equ	part_id - para
o_stages	equ	stages - para
o_done		equ	done    - para
o_result	equ	result  - para

;-------------------------------------------------------------------------------

start:
	ld	sp,stack
	pop	ix
	pop	de
loop:
	dec	(ix+o_stages)
	jp	m,stop

	pop	hl
	push	de
	push	hl
	exx
	ld	hl,(loadaddr)
	ret
continue:
	exx
	ld	(ix+o_result),a
	or	a
	jr	z,loop
stop:
	in	a,(Idecmd) 	;2
	ld	l,a     	;1
	in	a,(IdeErr) 	;2
	ld	h,a     	;1
	ld	(ide_result),hl	;3 	9
	dec	(ix+o_done)
	halt

;-------------------------------------------------------------------------------

chk_to:
	xor	a	;
to_l:
	dec	a
	ex	(sp),hl
	ex	(sp),hl
	jr	nz,to_l	;
	dec	hl	; 4
	ld	a,h	; 4
	or	l	; 4
	ret	nz	; 10/5
	ccf		; 3
	ret		; 9

   if base = 0
     if 044h-$ > 0
	rept	044h-$
	db	0
	endm
     endif
   endif

part_start:
;	dw	0
;	dw	0	; part_start is 4 byte long, but stack gets free
stack:
	dw	para
	dw	continue
stage_table:
   if	DO_WAIT_NBSY
	dw	s_wait_not_bsy
   endif
	dw	s_wait_rdy
	dw	s_check_io
	dw	s_set_xfermode8
	dw	s_read_parttbl
	dw	s_check_signature
	dw	s_find_partition
	dw	s_read_sectors
	dw	s_go
number_of_stages equ ($-stage_table)/2

   if	DO_WAIT_NBSY
;-------------------------------------------------------------------------------
; Wait while device is busy with time out
;     return:
;	 a = 0 if ok
;	 a = ff in timeout
;     destroys hl

s_wait_not_bsy:
	ld	hl,(timeout)
wnb_l:
	in	a,(IdeCmd)
	rla
	jr	nc,wnb_e
	call	chk_to
	jr	nc,wnb_l
wnb_e:
	sbc	a,a
	ret
   endif

;-------------------------------------------------------------------------------
; Wait for ready signal with time out
;     return:
;	 a = 0 if ok
;	 a = ff in timeout
;     destroys hl

s_wait_rdy:
wait_rdy_to:
	ld	hl,(timeout)
wrdy_l:
	in	a,(IdeCmd)
	xor	01000000b
	and	11000000b	; clears carry
	jr	z,wrdy_e
	call	chk_to
	jr	nc,wrdy_l
wrdy_e:
	sbc	a,a
	ret

;-------------------------------------------------------------------------------

s_check_io:
	ld	a,0E0h		; unit 0, lba mode
	out	(IdeSDH),a	;

	xor	a		; execute NOP command
	call	do_ide_cmd	; should return error
	ret	c
	xor	1
	ret	nz
	ld	a,CmdHome	; execute RECALIBRATE command
	jr	do_ide_cmd

;-------------------------------------------------------------------------------

s_set_xfermode8:
	ld	a,1		; Enable 8-bit data transfer.
	out	(IDEFeat),a
	ld	a,CmdSF		; Set feature command

;	fall thru
;	jr	do_ide_cmd

;-------------------------------------------------------------------------------

do_ide_cmd:
	out	(IdeCmd),a	;
	call	wait_rdy_to
	ret	c
	in	a,(IdeCmd)
	and	10001001b	;
	ret

;-------------------------------------------------------------------------------

s_check_signature:
;	ld	hl,(loadaddr)
	inc	h		; Point to last byte of MBR
	inc	h
	dec	hl
	ld	a,0aah
	cp	(hl)			; Test, if it has a valid MBR
	ret	nz
	dec	hl
	cpl				; a=055h
	sub	(hl)			;
	ret				; should be 0

;-------------------------------------------------------------------------------
; Read partition table (lbr)

s_read_parttbl:
;	ld	hl,(loadaddr)
	ld	bc,1*256 + 0	; sector 0 (lba)
	ld	e,c
	ld	d,c
	jr	read_sectors

;-------------------------------------------------------------------------------
; Find CP/M paartition
; 	Look for first CP/M partition
;	and save partition offset

s_find_partition:
;	ld	hl,(loadaddr)
	ld	de,512-2-64+PTYPE	; Point to  partition type of first first partition table entry
	add	hl,de
	ld	de,16
	ld	b,4			; Max # of partition table entries
ploop:
	ld	a,(ix+o_part_id)
	sub	(HL)			; Test for CP/M Partition
	jr	nz,pnext
	ld	bc,4
	add	hl,bc			; Point to partition start (lba)
	ld	de,part_start
	ldir
	ret				;a=0
pnext:
	add	hl,de
	djnz	ploop
	ret


;-------------------------------------------------------------------------------
; Read sec_count sectors, beginning at part_start+sec_start

s_read_sectors:
;	ld	hl,(loadaddr)
	push	hl
	ld	bc,(sec_start)		;b=sec_count, c=sec_start
	ld	e,c
	ld	d,0
	ld	hl,(part_start)		;add partition offset to sector number
	add	hl,de
	ld	a,(part_start+2)
	adc	a,d			;d=0
	ld	c,a
	ex	de,hl
	pop	hl

;	fall thru

;-------------------------------------------------------------------------------
; Read a number of sectors
;	hl:  memory address
; 	cde: sector number (24 bit)
;	b:   sector count

read_sectors:
	ld	a,e		; lba 0..7
	out	(IdeSNum),a
	ld	a,d		; lba 0..7
	out	(IdeClo),a
	ld	a,c		; lba 0..7
	out	(IdeCHi),a
	ld	a,b		; number of sectors to read
	out	(IdeSCnt),a	; set sector count

	ld	a,CmdRd
	out	(IdeCmd),a	; command: read sector data
	ld	d,b
	ld	bc,IdeDat	; I/O address
wdrq:
	in	a,(IdeCmd)	; wait for DRQ to become active
	bit	3,a
	jr	z,wdrq
	inir			; read 512 data bytes (2 x 256)
	inir
wnb:				; wait while busy
	in	a,(IdeCmd)	;
	rlca
	jr	c,wnb
	rrca			; restore status
	bit	0,a
	jr	nz,err_out
	dec	d
	jr	nz,wdrq
err_out:
	and	10001001b	; Busy, DRQ, or Error?
	ret			; return 0, if everything is ok

;-------------------------------------------------------------------------------

s_go:
;	ld	hl,(loadaddr)
	dec	(ix+o_done)
	jp	(hl)


;-------------------------------------------------------------------------------
   if base = 0
     if $ > 100h
	.printx Error: Program to large to fit in page 0!
	db "Stop
     endif
   endif

	end