]> cloudbase.mooo.com Git - z180-stamp.git/blob - z180/cfboot.180
Merge branch 'chan-fatfs' into fatfs-integration
[z180-stamp.git] / z180 / cfboot.180
1 TITLE 'CF cold boot loader'
2
3 ; Port Address Equates
4
5 include config.inc
6 include z180reg.inc
7
8 ; IDE Task File Register Definitions
9
10 IDEDat equ IDEBASE+0 ; Data Register
11 IDEErr equ IDEBASE+1 ; Error Register
12 IDEFeat equ IDEBASE+1 ; Feature Register
13 IDESCnt equ IDEBASE+2 ; Sector Count
14 IDESNum equ IDEBASE+3 ; Sector Number
15 IDECLo equ IDEBASE+4 ; Cylinder Low
16 IDECHi equ IDEBASE+5 ; Cylinder High
17 IDESDH equ IDEBASE+6 ; Drive and Head
18 IDECmd equ IDEBASE+7 ; Command / Status
19
20 ; IDE Hard disk commands:
21
22 CmdNOP equ 00h ; NOP Command
23 CmdHome equ 10h ; Recalibrate
24 CmdRd equ 20h ; Read Sector
25 CmdWr equ 30h ; Write Sector
26 CmdId equ 0ECh ; Read ID
27 CmdSF equ 0EFh ; Set Feature
28
29 ; Partition Table Structures
30
31 PTYPE equ 4
32 PSTART equ 8
33 PSIZE equ 12
34
35 ; Partition table id
36 ; (see http://www.win.tue.nl/~aeb/partitions/partition_types-1.html)
37
38 PARTID1_FAT16 equ 00EH
39 PARTID2_FAT16 equ 006H
40 PARTID_CPM equ 052H
41
42
43 DEBUG equ false ; not used
44 DO_WAIT_NBSY equ false
45 RUN_TPA equ false
46
47 if RUN_TPA
48 base equ 0100h
49 else
50 base equ 0
51 endif
52
53 ;-------------------------------------------------------------------------------
54
55 aseg
56
57 org base
58
59 jr start
60
61 para: equ $
62 loadaddr: dw base+100h
63 sec_start: db 0
64 sec_cnt: db 7
65 part_id: db PARTID_CPM
66 timeout: dw 10000
67 stages: db number_of_stages
68 done: db 0
69 result: db 0
70 ide_result: db 0,0
71
72 o_part_id equ part_id - para
73 o_stages equ stages - para
74 o_done equ done - para
75 o_result equ result - para
76
77 ;-------------------------------------------------------------------------------
78
79 start:
80 ld sp,stack
81 pop ix
82 pop de
83 loop:
84 dec (ix+o_stages)
85 jp m,stop
86
87 pop hl
88 push de
89 push hl
90 exx
91 ld hl,(loadaddr)
92 ret
93 continue:
94 exx
95 ld (ix+o_result),a
96 or a
97 jr z,loop
98 stop:
99 in a,(Idecmd) ;2
100 ld l,a ;1
101 in a,(IdeErr) ;2
102 ld h,a ;1
103 ld (ide_result),hl ;3 9
104 dec (ix+o_done)
105 halt
106
107 ;-------------------------------------------------------------------------------
108
109 chk_to:
110 xor a ;
111 to_l:
112 dec a
113 ex (sp),hl
114 ex (sp),hl
115 jr nz,to_l ;
116 dec hl ; 4
117 ld a,h ; 4
118 or l ; 4
119 ret nz ; 10/5
120 ccf ; 3
121 ret ; 9
122
123 if base = 0
124 if 044h-$ > 0
125 rept 044h-$
126 db 0
127 endm
128 endif
129 endif
130
131 part_start:
132 ; dw 0
133 ; dw 0 ; part_start is 4 byte long, but stack gets free
134 stack:
135 dw para
136 dw continue
137 stage_table:
138 if DO_WAIT_NBSY
139 dw s_wait_not_bsy
140 endif
141 dw s_wait_rdy
142 dw s_check_io
143 dw s_set_xfermode8
144 dw s_read_parttbl
145 dw s_check_signature
146 dw s_find_partition
147 dw s_read_sectors
148 dw s_go
149 number_of_stages equ ($-stage_table)/2
150
151 if DO_WAIT_NBSY
152 ;-------------------------------------------------------------------------------
153 ; Wait while device is busy with time out
154 ; return:
155 ; a = 0 if ok
156 ; a = ff in timeout
157 ; destroys hl
158
159 s_wait_not_bsy:
160 ld hl,(timeout)
161 wnb_l:
162 in a,(IdeCmd)
163 rla
164 jr nc,wnb_e
165 call chk_to
166 jr nc,wnb_l
167 wnb_e:
168 sbc a,a
169 ret
170 endif
171
172 ;-------------------------------------------------------------------------------
173 ; Wait for ready signal with time out
174 ; return:
175 ; a = 0 if ok
176 ; a = ff in timeout
177 ; destroys hl
178
179 s_wait_rdy:
180 wait_rdy_to:
181 ld hl,(timeout)
182 wrdy_l:
183 in a,(IdeCmd)
184 xor 01000000b
185 and 11000000b ; clears carry
186 jr z,wrdy_e
187 call chk_to
188 jr nc,wrdy_l
189 wrdy_e:
190 sbc a,a
191 ret
192
193 ;-------------------------------------------------------------------------------
194
195 s_check_io:
196 ld a,0E0h ; unit 0, lba mode
197 out (IdeSDH),a ;
198
199 xor a ; execute NOP command
200 call do_ide_cmd ; should return error
201 ret c
202 xor 1
203 ret nz
204 ld a,CmdHome ; execute RECALIBRATE command
205 jr do_ide_cmd
206
207 ;-------------------------------------------------------------------------------
208
209 s_set_xfermode8:
210 ld a,1 ; Enable 8-bit data transfer.
211 out (IDEFeat),a
212 ld a,CmdSF ; Set feature command
213
214 ; fall thru
215 ; jr do_ide_cmd
216
217 ;-------------------------------------------------------------------------------
218
219 do_ide_cmd:
220 out (IdeCmd),a ;
221 call wait_rdy_to
222 ret c
223 in a,(IdeCmd)
224 and 10001001b ;
225 ret
226
227 ;-------------------------------------------------------------------------------
228
229 s_check_signature:
230 ; ld hl,(loadaddr)
231 inc h ; Point to last byte of MBR
232 inc h
233 dec hl
234 ld a,0aah
235 cp (hl) ; Test, if it has a valid MBR
236 ret nz
237 dec hl
238 cpl ; a=055h
239 sub (hl) ;
240 ret ; should be 0
241
242 ;-------------------------------------------------------------------------------
243 ; Read partition table (lbr)
244
245 s_read_parttbl:
246 ; ld hl,(loadaddr)
247 ld bc,1*256 + 0 ; sector 0 (lba)
248 ld e,c
249 ld d,c
250 jr read_sectors
251
252 ;-------------------------------------------------------------------------------
253 ; Find CP/M paartition
254 ; Look for first CP/M partition
255 ; and save partition offset
256
257 s_find_partition:
258 ; ld hl,(loadaddr)
259 ld de,512-2-64+PTYPE ; Point to partition type of first first partition table entry
260 add hl,de
261 ld de,16
262 ld b,4 ; Max # of partition table entries
263 ploop:
264 ld a,(ix+o_part_id)
265 sub (HL) ; Test for CP/M Partition
266 jr nz,pnext
267 ld bc,4
268 add hl,bc ; Point to partition start (lba)
269 ld de,part_start
270 ldir
271 ret ;a=0
272 pnext:
273 add hl,de
274 djnz ploop
275 ret
276
277
278 ;-------------------------------------------------------------------------------
279 ; Read sec_count sectors, beginning at part_start+sec_start
280
281 s_read_sectors:
282 ; ld hl,(loadaddr)
283 push hl
284 ld bc,(sec_start) ;b=sec_count, c=sec_start
285 ld e,c
286 ld d,0
287 ld hl,(part_start) ;add partition offset to sector number
288 add hl,de
289 ld a,(part_start+2)
290 adc a,d ;d=0
291 ld c,a
292 ex de,hl
293 pop hl
294
295 ; fall thru
296
297 ;-------------------------------------------------------------------------------
298 ; Read a number of sectors
299 ; hl: memory address
300 ; cde: sector number (24 bit)
301 ; b: sector count
302
303 read_sectors:
304 ld a,e ; lba 0..7
305 out (IdeSNum),a
306 ld a,d ; lba 0..7
307 out (IdeClo),a
308 ld a,c ; lba 0..7
309 out (IdeCHi),a
310 ld a,b ; number of sectors to read
311 out (IdeSCnt),a ; set sector count
312
313 ld a,CmdRd
314 out (IdeCmd),a ; command: read sector data
315 ld d,b
316 ld bc,IdeDat ; I/O address
317 wdrq:
318 in a,(IdeCmd) ; wait for DRQ to become active
319 bit 3,a
320 jr z,wdrq
321 inir ; read 512 data bytes (2 x 256)
322 inir
323 wnb: ; wait while busy
324 in a,(IdeCmd) ;
325 rlca
326 jr c,wnb
327 rrca ; restore status
328 bit 0,a
329 jr nz,err_out
330 dec d
331 jr nz,wdrq
332 err_out:
333 and 10001001b ; Busy, DRQ, or Error?
334 ret ; return 0, if everything is ok
335
336 ;-------------------------------------------------------------------------------
337
338 s_go:
339 ; ld hl,(loadaddr)
340 dec (ix+o_done)
341 jp (hl)
342
343
344 ;-------------------------------------------------------------------------------
345 if base = 0
346 if $ > 100h
347 .printx Error: Program to large to fit in page 0!
348 db "Stop
349 endif
350 endif
351
352 end