diff options
Diffstat (limited to 'firmware/target/coldfire')
-rwxr-xr-x | firmware/target/coldfire/ata-as-coldfire.S | 459 | ||||
-rwxr-xr-x | firmware/target/coldfire/ata-target.h | 6 |
2 files changed, 463 insertions, 2 deletions
diff --git a/firmware/target/coldfire/ata-as-coldfire.S b/firmware/target/coldfire/ata-as-coldfire.S new file mode 100755 index 0000000000..3b0d67f8e4 --- /dev/null +++ b/firmware/target/coldfire/ata-as-coldfire.S | |||
@@ -0,0 +1,459 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 by Jens Arnold | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | .section .icode,"ax",@progbits | ||
21 | |||
22 | .equ .ata_port, 0x20000020 | ||
23 | |||
24 | .align 2 | ||
25 | .global copy_read_sectors | ||
26 | .type copy_read_sectors,@function | ||
27 | |||
28 | /* Read a number of words from the ATA data port | ||
29 | * | ||
30 | * Utilises line bursts, assumes there is at least one full line to copy. | ||
31 | * | ||
32 | * Arguments: | ||
33 | * (4,%sp) - buffer address | ||
34 | * (8,%sp) - word count | ||
35 | * | ||
36 | * Register usage: | ||
37 | * %a0 - current address | ||
38 | * %a1 - end address | ||
39 | * %a2 - ata port | ||
40 | * %d0 - scratch | ||
41 | * %d1 - shift count | ||
42 | * %d2-%d6 - read buffers | ||
43 | */ | ||
44 | |||
45 | copy_read_sectors: | ||
46 | lea.l (-24, %sp), %sp | ||
47 | movem.l %d2-%d6/%a2, (%sp) | ||
48 | movem.l (28, %sp), %a0-%a1 | ||
49 | add.l %a1, %a1 | ||
50 | add.l %a0, %a1 | ||
51 | lea.l .ata_port, %a2 | ||
52 | |||
53 | move.l %a0, %d0 | ||
54 | btst.l #0, %d0 /* 16-bit aligned? */ | ||
55 | jeq .r_aligned /* yes, do word copy */ | ||
56 | |||
57 | /* not 16-bit aligned */ | ||
58 | subq.l #1, %a1 /* last byte is done unconditionally */ | ||
59 | moveq.l #24, %d1 /* preload shift count */ | ||
60 | |||
61 | move.w (%a2), %d2 /* load initial word */ | ||
62 | move.l %d2, %d3 | ||
63 | lsr.l #8, %d3 | ||
64 | move.b %d3, (%a0)+ /* write high byte of it, aligns dest addr */ | ||
65 | |||
66 | btst.l #1, %d0 /* longword aligned? */ | ||
67 | beq.b .r_end_u_w1 /* yes, skip leading word handling */ | ||
68 | |||
69 | swap %d2 /* move initial word up */ | ||
70 | move.w (%a2), %d2 /* combine with second word */ | ||
71 | move.l %d2, %d3 | ||
72 | lsr.l #8, %d3 | ||
73 | move.w %d3, (%a0)+ /* write bytes 2 and 3 as word */ | ||
74 | |||
75 | .r_end_u_w1: | ||
76 | moveq.l #12, %d0 | ||
77 | add.l %a0, %d0 | ||
78 | and.l #0xFFFFFFF0,%d0 /* d0 == first line bound */ | ||
79 | cmp.l %a0, %d0 /* any leading longwords? */ | ||
80 | bls.b .r_end_u_l1 /* no: skip loop */ | ||
81 | |||
82 | .r_loop_u_l1: | ||
83 | move.w (%a2), %d3 /* load first word */ | ||
84 | swap %d3 /* move to upper 16 bit */ | ||
85 | move.w (%a2), %d3 /* load second word */ | ||
86 | move.l %d3, %d4 | ||
87 | lsl.l %d1, %d2 | ||
88 | lsr.l #8, %d3 | ||
89 | or.l %d3, %d2 /* combine old low byte with new top 3 bytes */ | ||
90 | move.l %d2, (%a0)+ /* store as long */ | ||
91 | move.l %d4, %d2 | ||
92 | cmp.l %a0, %d0 /* run up to first line bound */ | ||
93 | bhi.b .r_loop_u_l1 | ||
94 | |||
95 | .r_end_u_l1: | ||
96 | lea.l (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */ | ||
97 | |||
98 | .r_loop_u_line: | ||
99 | move.w (%a2), %d3 /* load 1st word */ | ||
100 | swap %d3 /* move to upper 16 bit */ | ||
101 | move.w (%a2), %d3 /* load 2nd word */ | ||
102 | move.l %d3, %d0 | ||
103 | lsl.l %d1, %d2 | ||
104 | lsr.l #8, %d0 | ||
105 | or.l %d0, %d2 /* combine old low byte with new top 3 bytes */ | ||
106 | move.w (%a2), %d4 /* load 3rd word */ | ||
107 | swap %d4 /* move to upper 16 bit */ | ||
108 | move.w (%a2), %d4 /* load 4th word */ | ||
109 | move.l %d4, %d0 | ||
110 | lsl.l %d1, %d3 | ||
111 | lsr.l #8, %d0 | ||
112 | or.l %d0, %d3 /* combine old low byte with new top 3 bytes */ | ||
113 | move.w (%a2), %d5 /* load 5th word */ | ||
114 | swap %d5 /* move to upper 16 bit */ | ||
115 | move.w (%a2), %d5 /* load 6th word */ | ||
116 | move.l %d5, %d0 | ||
117 | lsl.l %d1, %d4 | ||
118 | lsr.l #8, %d0 | ||
119 | or.l %d0, %d4 /* combine old low byte with new top 3 bytes */ | ||
120 | move.w (%a2), %d6 /* load 7th word */ | ||
121 | swap %d6 /* move to upper 16 bit */ | ||
122 | move.w (%a2), %d6 /* load 8th word */ | ||
123 | move.l %d6, %d0 | ||
124 | lsl.l %d1, %d5 | ||
125 | lsr.l #8, %d0 | ||
126 | or.l %d0, %d5 /* combine old low byte with new top 3 bytes */ | ||
127 | movem.l %d2-%d5, (%a0) /* store line */ | ||
128 | lea.l (16, %a0), %a0 | ||
129 | move.l %d6, %d2 | ||
130 | cmp.l %a0, %a1 /* run up to last line bound */ | ||
131 | bhi.b .r_loop_u_line | ||
132 | |||
133 | lea.l (12, %a1), %a1 /* readjust for longword loop */ | ||
134 | cmp.l %a0, %a1 /* any trailing longwords? */ | ||
135 | bls.b .r_end_u_l2 /* no: skip loop */ | ||
136 | |||
137 | .r_loop_u_l2: | ||
138 | move.w (%a2), %d3 /* load first word */ | ||
139 | swap %d3 /* move to upper 16 bit */ | ||
140 | move.w (%a2), %d3 /* load second word */ | ||
141 | move.l %d3, %d4 | ||
142 | lsl.l %d1, %d2 | ||
143 | lsr.l #8, %d3 | ||
144 | or.l %d3, %d2 /* combine old low byte with new top 3 bytes */ | ||
145 | move.l %d2, (%a0)+ /* store as long */ | ||
146 | move.l %d4, %d2 | ||
147 | cmp.l %a0, %a1 /* run up to last long bound */ | ||
148 | bhi.b .r_loop_u_l2 | ||
149 | |||
150 | .r_end_u_l2: | ||
151 | addq.l #2, %a1 /* back to final end address */ | ||
152 | cmp.l %a0, %a1 /* one word left? */ | ||
153 | bls.b .r_end_u_w2 | ||
154 | |||
155 | swap %d2 /* move old word to upper 16 bits */ | ||
156 | move.w (%a2), %d2 /* load final word */ | ||
157 | move.l %d2, %d3 | ||
158 | lsr.l #8, %d3 | ||
159 | move.w %d3, (%a0)+ /* write bytes 2 and 3 as word */ | ||
160 | |||
161 | .r_end_u_w2: | ||
162 | move.b %d2, (%a0)+ /* store final byte */ | ||
163 | bra.b .r_exit | ||
164 | |||
165 | /* 16-bit aligned */ | ||
166 | .r_aligned: | ||
167 | btst.l #1, %d0 /* longword aligned? */ | ||
168 | beq.b .r_end_a_w1 /* yes, skip leading word handling */ | ||
169 | |||
170 | move.w (%a2), (%a0)+ /* copy initial word */ | ||
171 | |||
172 | .r_end_a_w1: | ||
173 | moveq.l #12, %d0 | ||
174 | add.l %a0, %d0 | ||
175 | and.l #0xFFFFFFF0,%d0 /* d0 == first line bound */ | ||
176 | cmp.l %a0, %d0 /* any leading longwords? */ | ||
177 | bls.b .r_end_a_l1 /* no: skip loop */ | ||
178 | |||
179 | .r_loop_a_l1: | ||
180 | move.w (%a2), %d1 /* load first word */ | ||
181 | swap %d1 /* move it to upper 16 bits */ | ||
182 | move.w (%a2), %d1 /* load second word */ | ||
183 | move.l %d1, (%a0)+ /* store as long */ | ||
184 | cmp.l %a0, %d0 /* run up to first line bound */ | ||
185 | bhi.b .r_loop_a_l1 | ||
186 | |||
187 | .r_end_a_l1: | ||
188 | lea.l (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */ | ||
189 | |||
190 | .r_loop_a_line: | ||
191 | move.w (%a2), %d0 /* load 1st word */ | ||
192 | swap %d0 /* move it to upper 16 bits */ | ||
193 | move.w (%a2), %d0 /* load 2nd word */ | ||
194 | move.w (%a2), %d1 /* load 3rd word */ | ||
195 | swap %d1 /* move it to upper 16 bits */ | ||
196 | move.w (%a2), %d1 /* load 4th word */ | ||
197 | move.w (%a2), %d2 /* load 5th word */ | ||
198 | swap %d2 /* move it to upper 16 bits */ | ||
199 | move.w (%a2), %d2 /* load 6th word */ | ||
200 | move.w (%a2), %d3 /* load 7th word */ | ||
201 | swap %d3 /* move it to upper 16 bits */ | ||
202 | move.w (%a2), %d3 /* load 8th word */ | ||
203 | movem.l %d0-%d3, (%a0) /* store line */ | ||
204 | lea.l (16, %a0), %a0 | ||
205 | cmp.l %a0, %a1 /* run up to last line bound */ | ||
206 | bhi.b .r_loop_a_line | ||
207 | |||
208 | lea.l (12, %a1), %a1 /* readjust for longword loop */ | ||
209 | cmp.l %a0, %a1 /* any trailing longwords? */ | ||
210 | bls.b .r_end_a_l2 /* no: skip loop */ | ||
211 | |||
212 | .r_loop_a_l2: | ||
213 | move.w (%a2), %d1 /* read first word */ | ||
214 | swap %d1 /* move it to upper 16 bits */ | ||
215 | move.w (%a2), %d1 /* read second word */ | ||
216 | move.l %d1, (%a0)+ /* store as long */ | ||
217 | cmp.l %a0, %a1 /* run up to last long bound */ | ||
218 | bhi.b .r_loop_a_l2 | ||
219 | |||
220 | .r_end_a_l2: | ||
221 | addq.l #2, %a1 /* back to final end address */ | ||
222 | cmp.l %a0, %a1 /* one word left? */ | ||
223 | bls.b .r_end_a_w2 | ||
224 | |||
225 | move.w (%a2), (%a0)+ /* copy final word */ | ||
226 | |||
227 | .r_end_a_w2: | ||
228 | |||
229 | .r_exit: | ||
230 | movem.l (%sp), %d2-%d6/%a2 | ||
231 | lea.l (24, %sp), %sp | ||
232 | rts | ||
233 | |||
234 | .r_end: | ||
235 | .size copy_read_sectors,.r_end-copy_read_sectors | ||
236 | |||
237 | .align 2 | ||
238 | .global copy_write_sectors | ||
239 | .type copy_write_sectors,@function | ||
240 | |||
241 | /* Write a number of words to the ATA data port | ||
242 | * | ||
243 | * Utilises line bursts, assumes there is at least one full line to copy. | ||
244 | * | ||
245 | * Arguments: | ||
246 | * (4,%sp) - buffer address | ||
247 | * (8,%sp) - word count | ||
248 | * | ||
249 | * Register usage: | ||
250 | * %a0 - current address | ||
251 | * %a1 - end address | ||
252 | * %a2 - ata port | ||
253 | * %d0 - scratch | ||
254 | * %d1 - shift count | ||
255 | * %d2-%d6 - read buffers | ||
256 | */ | ||
257 | |||
258 | copy_write_sectors: | ||
259 | lea.l (-24, %sp), %sp | ||
260 | movem.l %d2-%d6/%a2, (%sp) | ||
261 | movem.l (28, %sp), %a0-%a1 | ||
262 | add.l %a1, %a1 | ||
263 | add.l %a0, %a1 | ||
264 | lea.l .ata_port, %a2 | ||
265 | |||
266 | move.l %a0, %d0 | ||
267 | btst.l #0, %d0 /* 16-bit aligned? */ | ||
268 | jeq .w_aligned /* yes, do word copy */ | ||
269 | |||
270 | /* not 16-bit aligned */ | ||
271 | subq.l #1, %a1 /* last byte is done unconditionally */ | ||
272 | moveq.l #24, %d1 /* preload shift count */ | ||
273 | |||
274 | move.b (%a0)+, %d2 | ||
275 | |||
276 | btst.l #1, %d0 /* longword aligned? */ | ||
277 | beq.b .w_end_u_w1 /* yes, skip leading word handling */ | ||
278 | |||
279 | swap %d2 | ||
280 | move.w (%a0)+, %d2 | ||
281 | move.l %d2, %d3 | ||
282 | lsr.l #8, %d3 | ||
283 | move.w %d3, (%a2) | ||
284 | |||
285 | .w_end_u_w1: | ||
286 | moveq.l #12, %d0 | ||
287 | add.l %a0, %d0 | ||
288 | and.l #0xFFFFFFF0,%d0 /* d0 == first line bound */ | ||
289 | cmp.l %a0, %d0 /* any leading longwords? */ | ||
290 | bls.b .w_end_u_l1 /* no: skip loop */ | ||
291 | |||
292 | .w_loop_u_l1: | ||
293 | move.l (%a0)+, %d3 | ||
294 | move.l %d3, %d4 | ||
295 | lsl.l %d1, %d2 | ||
296 | lsr.l #8, %d3 | ||
297 | or.l %d3, %d2 | ||
298 | swap %d2 | ||
299 | move.w %d2, (%a2) | ||
300 | swap %d2 | ||
301 | move.w %d2, (%a2) | ||
302 | move.l %d4, %d2 | ||
303 | cmp.l %a0, %d0 /* run up to first line bound */ | ||
304 | bhi.b .w_loop_u_l1 | ||
305 | |||
306 | .w_end_u_l1: | ||
307 | lea.l (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */ | ||
308 | |||
309 | .w_loop_u_line: | ||
310 | movem.l (%a0), %d3-%d6 | ||
311 | lea.l (16, %a0), %a0 | ||
312 | move.l %d3, %d0 | ||
313 | lsl.l %d1, %d2 | ||
314 | lsr.l #8, %d0 | ||
315 | or.l %d0, %d2 | ||
316 | swap %d2 | ||
317 | move.w %d2, (%a2) | ||
318 | swap %d2 | ||
319 | move.w %d2, (%a2) | ||
320 | move.l %d4, %d0 | ||
321 | lsl.l %d1, %d3 | ||
322 | lsr.l #8, %d0 | ||
323 | or.l %d0, %d3 | ||
324 | swap %d3 | ||
325 | move.w %d3, (%a2) | ||
326 | swap %d3 | ||
327 | move.w %d3, (%a2) | ||
328 | move.l %d5, %d0 | ||
329 | lsl.l %d1, %d4 | ||
330 | lsr.l #8, %d0 | ||
331 | or.l %d0, %d4 | ||
332 | swap %d4 | ||
333 | move.w %d4, (%a2) | ||
334 | swap %d4 | ||
335 | move.w %d4, (%a2) | ||
336 | move.l %d6, %d0 | ||
337 | lsl.l %d1, %d5 | ||
338 | lsr.l #8, %d0 | ||
339 | or.l %d0, %d5 | ||
340 | swap %d5 | ||
341 | move.w %d5, (%a2) | ||
342 | swap %d5 | ||
343 | move.w %d5, (%a2) | ||
344 | move.l %d6, %d2 | ||
345 | cmp.l %a0, %a1 /* run up to last line bound */ | ||
346 | bhi.b .w_loop_u_line | ||
347 | |||
348 | lea.l (12, %a1), %a1 /* readjust for longword loop */ | ||
349 | cmp.l %a0, %a1 /* any trailing longwords? */ | ||
350 | bls.b .w_end_u_l2 /* no: skip loop */ | ||
351 | |||
352 | .w_loop_u_l2: | ||
353 | move.l (%a0)+, %d3 | ||
354 | move.l %d3, %d4 | ||
355 | lsl.l %d1, %d2 | ||
356 | lsr.l #8, %d3 | ||
357 | or.l %d3, %d2 | ||
358 | swap %d2 | ||
359 | move.w %d2, (%a2) | ||
360 | swap %d2 | ||
361 | move.w %d2, (%a2) | ||
362 | move.l %d4, %d2 | ||
363 | cmp.l %a0, %a1 /* run up to first line bound */ | ||
364 | bhi.b .w_loop_u_l2 | ||
365 | |||
366 | .w_end_u_l2: | ||
367 | addq.l #2, %a1 /* back to final end address */ | ||
368 | cmp.l %a0, %a1 /* one word left? */ | ||
369 | bls.b .w_end_u_w2 | ||
370 | |||
371 | swap %d2 | ||
372 | move.w (%a0)+, %d2 | ||
373 | move.l %d2, %d3 | ||
374 | lsr.l #8, %d3 | ||
375 | move.w %d3, (%a2) | ||
376 | |||
377 | .w_end_u_w2: | ||
378 | lsl.l #8, %d2 | ||
379 | move.b (%a0)+, %d2 | ||
380 | move.w %d2, (%a2) | ||
381 | bra.b .w_exit | ||
382 | |||
383 | /* 16-bit aligned */ | ||
384 | .w_aligned: | ||
385 | btst.l #1, %d0 | ||
386 | beq.b .w_end_a_w1 | ||
387 | |||
388 | move.w (%a0)+, (%a2) /* copy initial word */ | ||
389 | |||
390 | .w_end_a_w1: | ||
391 | moveq.l #12, %d0 | ||
392 | add.l %a0, %d0 | ||
393 | and.l #0xFFFFFFF0,%d0 /* d0 == first line bound */ | ||
394 | cmp.l %a0, %d0 /* any leading longwords? */ | ||
395 | bls.b .w_end_a_l1 /* no: skip loop */ | ||
396 | |||
397 | .w_loop_a_l1: | ||
398 | move.l (%a0)+, %d1 | ||
399 | swap %d1 | ||
400 | move.w %d1, (%a2) | ||
401 | swap %d1 | ||
402 | move.w %d1, (%a2) | ||
403 | cmp.l %a0, %d0 /* run up to first line bound */ | ||
404 | bhi.b .w_loop_a_l1 | ||
405 | |||
406 | .w_end_a_l1: | ||
407 | lea.l (-14, %a1), %a1 /* adjust end addr. to 16 bytes/pass */ | ||
408 | |||
409 | .w_loop_a_line: | ||
410 | movem.l (%a0), %d0-%d3 | ||
411 | lea.l (16, %a0), %a0 | ||
412 | swap %d0 | ||
413 | move.w %d0, (%a2) | ||
414 | swap %d0 | ||
415 | move.w %d0, (%a2) | ||
416 | swap %d1 | ||
417 | move.w %d1, (%a2) | ||
418 | swap %d1 | ||
419 | move.w %d1, (%a2) | ||
420 | swap %d2 | ||
421 | move.w %d2, (%a2) | ||
422 | swap %d2 | ||
423 | move.w %d2, (%a2) | ||
424 | swap %d3 | ||
425 | move.w %d3, (%a2) | ||
426 | swap %d3 | ||
427 | move.w %d3, (%a2) | ||
428 | cmp.l %a0, %a1 /* run up to last line bound */ | ||
429 | bhi.b .w_loop_a_line | ||
430 | |||
431 | lea.l (12, %a1), %a1 /* readjust for longword loop */ | ||
432 | cmp.l %a0, %a1 /* any trailing longwords? */ | ||
433 | bls.b .w_end_a_l2 /* no: skip loop */ | ||
434 | |||
435 | .w_loop_a_l2: | ||
436 | move.l (%a0)+, %d1 | ||
437 | swap %d1 | ||
438 | move.w %d1, (%a2) | ||
439 | swap %d1 | ||
440 | move.w %d1, (%a2) | ||
441 | cmp.l %a0, %a1 /* run up to first line bound */ | ||
442 | bhi.b .w_loop_a_l2 | ||
443 | |||
444 | .w_end_a_l2: | ||
445 | addq.l #2, %a1 /* back to final end address */ | ||
446 | cmp.l %a0, %a1 /* one word left? */ | ||
447 | bls.b .w_end_a_w2 | ||
448 | |||
449 | move.w (%a0)+, (%a2) /* copy final word */ | ||
450 | |||
451 | .w_end_a_w2: | ||
452 | |||
453 | .w_exit: | ||
454 | movem.l (%sp), %d2-%d6/%a2 | ||
455 | lea.l (24, %sp), %sp | ||
456 | rts | ||
457 | |||
458 | .w_end: | ||
459 | .size copy_write_sectors,.w_end-copy_write_sectors | ||
diff --git a/firmware/target/coldfire/ata-target.h b/firmware/target/coldfire/ata-target.h index 4a28c3ae3f..e246dc7af1 100755 --- a/firmware/target/coldfire/ata-target.h +++ b/firmware/target/coldfire/ata-target.h | |||
@@ -20,8 +20,8 @@ | |||
20 | #define ATA_TARGET_H | 20 | #define ATA_TARGET_H |
21 | 21 | ||
22 | /* asm optimised read & write loops */ | 22 | /* asm optimised read & write loops */ |
23 | 23 | #define ATA_OPTIMIZED_READING | |
24 | #define NOINLINE_ATTR __attribute__((noinline)) /* don't inline the loops */ | 24 | #define ATA_OPTIMIZED_WRITING |
25 | 25 | ||
26 | #define ATA_IOBASE 0x20000000 | 26 | #define ATA_IOBASE 0x20000000 |
27 | #define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE + 0x20))) | 27 | #define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE + 0x20))) |
@@ -65,4 +65,6 @@ void ata_reset(void); | |||
65 | void ata_device_init(void); | 65 | void ata_device_init(void); |
66 | bool ata_is_coldstart(void); | 66 | bool ata_is_coldstart(void); |
67 | 67 | ||
68 | void copy_read_sectors(unsigned char* buf, int wordcount); | ||
69 | void copy_write_sectors(const unsigned char* buf, int wordcount); | ||
68 | #endif | 70 | #endif |