summaryrefslogtreecommitdiff
path: root/firmware/target/coldfire
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/coldfire')
-rwxr-xr-xfirmware/target/coldfire/ata-as-coldfire.S459
-rwxr-xr-xfirmware/target/coldfire/ata-target.h6
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
45copy_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
258copy_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);
65void ata_device_init(void); 65void ata_device_init(void);
66bool ata_is_coldstart(void); 66bool ata_is_coldstart(void);
67 67
68void copy_read_sectors(unsigned char* buf, int wordcount);
69void copy_write_sectors(const unsigned char* buf, int wordcount);
68#endif 70#endif