]>
Commit | Line | Data |
---|---|---|
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 | stages: 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_stages equ stages - 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 | dec (ix+o_stages)\r | |
85 | jp m,stop\r | |
86 | \r | |
87 | pop hl\r | |
88 | push de\r | |
89 | push hl\r | |
90 | exx\r | |
91 | ld hl,(loadaddr)\r | |
92 | ret\r | |
93 | continue:\r | |
94 | exx\r | |
95 | ld (ix+o_result),a\r | |
96 | or a\r | |
97 | jr z,loop\r | |
98 | stop:\r | |
99 | in a,(Idecmd) ;2\r | |
100 | ld l,a ;1\r | |
101 | in a,(IdeErr) ;2\r | |
102 | ld h,a ;1\r | |
103 | ld (ide_result),hl ;3 9\r | |
104 | dec (ix+o_done)\r | |
105 | halt\r | |
106 | \r | |
107 | ;-------------------------------------------------------------------------------\r | |
108 | \r | |
109 | chk_to:\r | |
110 | xor a ;\r | |
111 | to_l:\r | |
112 | dec a\r | |
113 | ex (sp),hl\r | |
114 | ex (sp),hl\r | |
115 | jr nz,to_l ;\r | |
116 | dec hl ; 4\r | |
117 | ld a,h ; 4\r | |
118 | or l ; 4\r | |
119 | ret nz ; 10/5\r | |
120 | ccf ; 3\r | |
121 | ret ; 9\r | |
122 | \r | |
123 | if base = 0\r | |
124 | if 044h-$ > 0\r | |
125 | rept 044h-$\r | |
126 | db 0\r | |
127 | endm\r | |
128 | endif\r | |
129 | endif\r | |
130 | \r | |
131 | part_start:\r | |
132 | ; dw 0\r | |
133 | ; dw 0 ; part_start is 4 byte long, but stack gets free\r | |
134 | stack:\r | |
135 | dw para\r | |
136 | dw continue\r | |
137 | stage_table:\r | |
138 | if DO_WAIT_NBSY\r | |
139 | dw s_wait_not_bsy\r | |
140 | endif\r | |
141 | dw s_wait_rdy\r | |
142 | dw s_check_io\r | |
143 | dw s_set_xfermode8\r | |
144 | dw s_read_parttbl\r | |
145 | dw s_check_signature\r | |
146 | dw s_find_partition\r | |
147 | dw s_read_sectors\r | |
148 | dw s_go\r | |
149 | number_of_stages equ ($-stage_table)/2\r | |
150 | \r | |
151 | if DO_WAIT_NBSY\r | |
152 | ;-------------------------------------------------------------------------------\r | |
153 | ; Wait while device is busy with time out\r | |
154 | ; return:\r | |
155 | ; a = 0 if ok\r | |
156 | ; a = ff in timeout\r | |
157 | ; destroys hl\r | |
158 | \r | |
159 | s_wait_not_bsy:\r | |
160 | ld hl,(timeout)\r | |
161 | wnb_l:\r | |
162 | in a,(IdeCmd)\r | |
163 | rla\r | |
164 | jr nc,wnb_e\r | |
165 | call chk_to\r | |
166 | jr nc,wnb_l\r | |
167 | wnb_e:\r | |
168 | sbc a,a\r | |
169 | ret\r | |
170 | endif\r | |
171 | \r | |
172 | ;-------------------------------------------------------------------------------\r | |
173 | ; Wait for ready signal with time out\r | |
174 | ; return:\r | |
175 | ; a = 0 if ok\r | |
176 | ; a = ff in timeout\r | |
177 | ; destroys hl\r | |
178 | \r | |
179 | s_wait_rdy:\r | |
180 | wait_rdy_to:\r | |
181 | ld hl,(timeout)\r | |
182 | wrdy_l:\r | |
183 | in a,(IdeCmd)\r | |
184 | xor 01000000b\r | |
185 | and 11000000b ; clears carry\r | |
186 | jr z,wrdy_e\r | |
187 | call chk_to\r | |
188 | jr nc,wrdy_l\r | |
189 | wrdy_e:\r | |
190 | sbc a,a\r | |
191 | ret\r | |
192 | \r | |
193 | ;-------------------------------------------------------------------------------\r | |
194 | \r | |
195 | s_check_io:\r | |
196 | ld a,0E0h ; unit 0, lba mode\r | |
197 | out (IdeSDH),a ;\r | |
198 | \r | |
199 | xor a ; execute NOP command\r | |
200 | call do_ide_cmd ; should return error\r | |
201 | ret c\r | |
202 | xor 1\r | |
203 | ret nz\r | |
204 | ld a,CmdHome ; execute RECALIBRATE command\r | |
205 | jr do_ide_cmd\r | |
206 | \r | |
207 | ;-------------------------------------------------------------------------------\r | |
208 | \r | |
209 | s_set_xfermode8:\r | |
210 | ld a,1 ; Enable 8-bit data transfer.\r | |
211 | out (IDEFeat),a\r | |
212 | ld a,CmdSF ; Set feature command\r | |
213 | \r | |
214 | ; fall thru\r | |
215 | ; jr do_ide_cmd\r | |
216 | \r | |
217 | ;-------------------------------------------------------------------------------\r | |
218 | \r | |
219 | do_ide_cmd:\r | |
220 | out (IdeCmd),a ;\r | |
221 | call wait_rdy_to\r | |
222 | ret c\r | |
223 | in a,(IdeCmd)\r | |
224 | and 10001001b ;\r | |
225 | ret\r | |
226 | \r | |
227 | ;-------------------------------------------------------------------------------\r | |
228 | \r | |
229 | s_check_signature:\r | |
230 | ; ld hl,(loadaddr)\r | |
231 | inc h ; Point to last byte of MBR\r | |
232 | inc h\r | |
233 | dec hl\r | |
234 | ld a,0aah\r | |
235 | cp (hl) ; Test, if it has a valid MBR\r | |
236 | ret nz\r | |
237 | dec hl\r | |
238 | cpl ; a=055h\r | |
239 | sub (hl) ;\r | |
240 | ret ; should be 0\r | |
241 | \r | |
242 | ;-------------------------------------------------------------------------------\r | |
243 | ; Read partition table (lbr)\r | |
244 | \r | |
245 | s_read_parttbl:\r | |
246 | ; ld hl,(loadaddr)\r | |
247 | ld bc,1*256 + 0 ; sector 0 (lba)\r | |
248 | ld e,c\r | |
249 | ld d,c\r | |
250 | jr read_sectors\r | |
251 | \r | |
252 | ;-------------------------------------------------------------------------------\r | |
253 | ; Find CP/M paartition\r | |
254 | ; Look for first CP/M partition\r | |
255 | ; and save partition offset\r | |
256 | \r | |
257 | s_find_partition:\r | |
258 | ; ld hl,(loadaddr)\r | |
259 | ld de,512-2-64+PTYPE ; Point to partition type of first first partition table entry\r | |
260 | add hl,de\r | |
261 | ld de,16\r | |
262 | ld b,4 ; Max # of partition table entries\r | |
263 | ploop:\r | |
264 | ld a,(ix+o_part_id)\r | |
265 | sub (HL) ; Test for CP/M Partition\r | |
266 | jr nz,pnext\r | |
267 | ld bc,4\r | |
268 | add hl,bc ; Point to partition start (lba)\r | |
269 | ld de,part_start\r | |
270 | ldir\r | |
271 | ret ;a=0\r | |
272 | pnext:\r | |
273 | add hl,de\r | |
274 | djnz ploop\r | |
275 | ret\r | |
276 | \r | |
277 | \r | |
278 | ;-------------------------------------------------------------------------------\r | |
279 | ; Read sec_count sectors, beginning at part_start+sec_start\r | |
280 | \r | |
281 | s_read_sectors:\r | |
282 | ; ld hl,(loadaddr)\r | |
283 | push hl\r | |
284 | ld bc,(sec_start) ;b=sec_count, c=sec_start\r | |
285 | ld e,c\r | |
286 | ld d,0\r | |
287 | ld hl,(part_start) ;add partition offset to sector number\r | |
288 | add hl,de\r | |
289 | ld a,(part_start+2)\r | |
290 | adc a,d ;d=0\r | |
291 | ld c,a\r | |
292 | ex de,hl\r | |
293 | pop hl\r | |
294 | \r | |
295 | ; fall thru\r | |
296 | \r | |
297 | ;-------------------------------------------------------------------------------\r | |
298 | ; Read a number of sectors\r | |
299 | ; hl: memory address\r | |
300 | ; cde: sector number (24 bit)\r | |
301 | ; b: sector count\r | |
302 | \r | |
303 | read_sectors:\r | |
304 | ld a,e ; lba 0..7\r | |
305 | out (IdeSNum),a\r | |
306 | ld a,d ; lba 0..7\r | |
307 | out (IdeClo),a\r | |
308 | ld a,c ; lba 0..7\r | |
309 | out (IdeCHi),a\r | |
310 | ld a,b ; number of sectors to read\r | |
311 | out (IdeSCnt),a ; set sector count\r | |
312 | \r | |
313 | ld a,CmdRd\r | |
314 | out (IdeCmd),a ; command: read sector data\r | |
315 | ld d,b\r | |
316 | ld bc,IdeDat ; I/O address\r | |
317 | wdrq:\r | |
318 | in a,(IdeCmd) ; wait for DRQ to become active\r | |
319 | bit 3,a\r | |
320 | jr z,wdrq\r | |
321 | inir ; read 512 data bytes (2 x 256)\r | |
322 | inir\r | |
323 | wnb: ; wait while busy\r | |
324 | in a,(IdeCmd) ;\r | |
325 | rlca\r | |
326 | jr c,wnb\r | |
327 | rrca ; restore status\r | |
328 | bit 0,a\r | |
329 | jr nz,err_out\r | |
330 | dec d\r | |
331 | jr nz,wdrq\r | |
332 | err_out:\r | |
333 | and 10001001b ; Busy, DRQ, or Error?\r | |
334 | ret ; return 0, if everything is ok\r | |
335 | \r | |
336 | ;-------------------------------------------------------------------------------\r | |
337 | \r | |
338 | s_go:\r | |
339 | ; ld hl,(loadaddr)\r | |
340 | dec (ix+o_done)\r | |
341 | jp (hl)\r | |
342 | \r | |
343 | \r | |
344 | ;-------------------------------------------------------------------------------\r | |
345 | if base = 0\r | |
346 | if $ > 100h\r | |
347 | .printx Error: Program to large to fit in page 0!\r | |
348 | db "Stop\r | |
349 | endif\r | |
350 | endif\r | |
351 | \r | |
352 | end\r |