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