]>
Commit | Line | Data |
---|---|---|
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 | |
10 | IDEDat equ IDEBASE+0 ; Data Register\r | |
11 | IDEErr equ IDEBASE+1 ; Error Register\r | |
12 | IDEFeat equ IDEBASE+1 ; Feature Register\r | |
13 | IDESCnt equ IDEBASE+2 ; Sector Count\r | |
14 | IDESNum equ IDEBASE+3 ; Sector Number\r | |
15 | IDECLo equ IDEBASE+4 ; Cylinder Low\r | |
16 | IDECHi equ IDEBASE+5 ; Cylinder High\r | |
17 | IDESDH equ IDEBASE+6 ; Drive and Head\r | |
18 | IDECmd equ IDEBASE+7 ; Command / Status\r | |
19 | \r | |
20 | ; IDE Hard disk commands:\r | |
21 | \r | |
22 | CmdNOP equ 00h ; NOP Command\r | |
23 | CmdHome equ 10h ; Recalibrate\r | |
24 | CmdRd equ 20h ; Read Sector\r | |
25 | CmdWr equ 30h ; Write Sector\r | |
26 | CmdId equ 0ECh ; Read ID\r | |
27 | CmdSF equ 0EFh ; Set Feature\r | |
28 | \r | |
29 | ; Partition Table Structures\r | |
30 | \r | |
31 | PTYPE equ 4\r | |
32 | PSTART equ 8\r | |
33 | PSIZE 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 | |
38 | PARTID1_FAT16 equ 00EH\r | |
39 | PARTID2_FAT16 equ 006H\r | |
40 | PARTID_CPM equ 052H\r | |
41 | \r | |
42 | \r | |
43 | DEBUG equ false ; not used\r | |
44 | DO_WAIT_NBSY equ false\r | |
45 | RUN_TPA equ false\r | |
46 | \r | |
47 | if RUN_TPA\r | |
48 | base equ 0100h\r | |
49 | else\r | |
50 | base 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 | |
61 | para: equ $\r | |
62 | loadaddr: dw base+100h\r | |
63 | sec_start: db 0\r | |
64 | sec_cnt: db 7\r | |
65 | part_id: db PARTID_CPM\r | |
66 | timeout: dw 10000\r | |
67 | stop_stage: db number_of_stages\r | |
68 | done: db 0\r | |
69 | result: db 0\r | |
70 | ide_result: db 0,0\r | |
71 | \r | |
72 | o_part_id equ part_id - para\r | |
73 | o_stop_stage equ stop_stage - para\r | |
74 | o_done equ done - para\r | |
75 | o_result equ result - para\r | |
76 | \r | |
77 | ;-------------------------------------------------------------------------------\r | |
78 | \r | |
79 | start:\r | |
80 | ld sp,stack\r | |
81 | pop ix\r | |
82 | pop de\r | |
83 | loop:\r | |
84 | pop hl\r | |
85 | push de\r | |
86 | push hl\r | |
87 | exx\r | |
88 | ld hl,(loadaddr)\r | |
89 | ret\r | |
90 | continue:\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 | |
97 | stop:\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 | |
108 | chk_to:\r | |
109 | xor a ;\r | |
110 | to_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 | |
130 | part_start:\r | |
131 | ; dw 0\r | |
132 | ; dw 0 ; part_start is 4 byte long, but stack gets free\r | |
133 | stack:\r | |
134 | dw para\r | |
135 | dw continue\r | |
136 | stages:\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 | |
148 | number_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 | |
158 | s_wait_not_bsy:\r | |
159 | ld hl,(timeout)\r | |
160 | wnb_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 | |
166 | wnb_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 | |
178 | s_wait_rdy:\r | |
179 | wait_rdy_to:\r | |
180 | ld hl,(timeout)\r | |
181 | wrdy_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 | |
188 | wrdy_e:\r | |
189 | sbc a,a\r | |
190 | ret\r | |
191 | \r | |
192 | ;-------------------------------------------------------------------------------\r | |
193 | \r | |
194 | s_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 | |
208 | s_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 | |
218 | do_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 | |
228 | s_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 | |
244 | s_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 | |
256 | s_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 | |
262 | ploop:\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 | |
271 | pnext:\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 | |
280 | s_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 | |
302 | read_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 | |
316 | wdrq:\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 | |
322 | wnb: ; 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 | |
331 | err_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 | |
337 | s_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 |