FS#11335 by me: make ARM assembly functions thumb-friendly
[kugel-rb.git] / firmware / target / arm / ata-as-arm.S
blob101bc4dcc1d8502f370927ba15387397878b6cb9
1 /***************************************************************************
2  *             __________               __   ___.
3  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7  *                     \/            \/     \/    \/            \/
8  * $Id$
9  *
10  * Copyright (C) 2007 by Jens Arnold
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18  * KIND, either express or implied.
19  *
20  ****************************************************************************/
22 #include "config.h"
25 #if CONFIG_CPU == PP5002
26     /* Causes ATA retries on iPod G3 probably related to improper controller
27      * setup. Needs investigation. */
28     .section    .icode,"ax",%progbits
29     .equ    .ata_port, 0xc00031e0
30 #elif defined CPU_PP502x
31     /* Verified working on (PP5020, PP5022) targets */
32     .section    .icode,"ax",%progbits
33     .equ    .ata_port, 0xc30001e0
34 #elif CONFIG_CPU == S3C2440
35     /* Untested */
36     .text
37     .equ    .ata_port, 0x18000000
38 #elif defined(CREATIVE_ZVx) /* Zen Vision could have an other address */
39     .text
40     .equ    .ata_port, 0x50FEE000
41 #elif defined(MROBE_500)
42     .text
43     .equ    .ata_port, 0x50400000
44 #else
45     /* This isn't vaild, but it does it's job, not sure what this should be */
46     #error ata_port undefined!
47 #endif
49     .align  2
50     .global copy_read_sectors
51     .type   copy_read_sectors,%function
52     
53 /* Read a number of words from the ATA data port
54  *
55  * Optimised for speed; assumes wordcount >= 10
56  *
57  * Arguments:
58  *   r0 - buffer address
59  *   r1 - word count
60  *
61  * Register usage:
62  *   r0 - current address
63  *   r1 - word count
64  *   r2 - ata port
65  *   r3..r5, r12, lr - read buffers
66  */
68 copy_read_sectors:
69     stmfd   sp!, {r4, r5, lr}
70     ldr     r2, =.ata_port
71     tst     r0, #1              /* 16 bit aligned? */
72     beq     .r_aligned
74     /* not 16-bit aligned */
75     sub     r1, r1, #1          /* one halfword is handled unconditionally */
76     ldrh    r3, [r2]            /* read first halfword */
77     strb    r3, [r0], #1        /* store low byte */
78     mov     r3, r3, lsr #8
80     tst     r0, #2              /* 32 bit aligned? */
81     beq     .r_noword_u
82     ldrh    r4, [r2]            /* read second halfword */
83     orr     r3, r3, r4, lsl #8  /* combine with old byte */
84     strh    r3, [r0], #2        /* store */
85     mov     r3, r4, lsr #8
86     sub     r1, r1, #1          /* another halfword taken */
87 .r_noword_u:
89     sub     r1, r1, #8          /* adjust for zero-check and doing 8 halfwords/loop */
90 .r_loop_u:
91     ldrh    r4, [r2]            /* Read 8 halfwords and combine them into */
92     orr     r3, r3, r4, lsl #8  /*  4 words so that they're properly aligned */
93     ldrh    r4, [r2]            /*  in memory. Bottom byte of first word is */
94     orr     r3, r3, r4, lsl #24 /*  the top byte from the last round. Write */
95     mov     r4, r4, lsr #8      /*  all 4 words at once. */
96     ldrh    r5, [r2]
97     orr     r4, r4, r5, lsl #8
98     ldrh    r5, [r2]
99     orr     r4, r4, r5, lsl #24
100     mov     r5, r5, lsr #8
101     ldrh    r12, [r2]
102     orr     r5, r5, r12, lsl #8
103     ldrh    r12, [r2]
104     orr     r5, r5, r12, lsl #24
105     mov     r12, r12, lsr #8
106     ldrh    lr, [r2]
107     orr     r12, r12, lr, lsl #8
108     ldrh    lr, [r2]
109     orr     r12, r12, lr, lsl #24
110     stmia   r0!, {r3, r4, r5, r12}
111     mov     r3, lr, lsr #8
112     subs    r1, r1, #8          /* 8 or more halfwords left? */
113     bge     .r_loop_u
115     /* No need to adjust the count, only checking bits from now on. */
116     tst     r1, #4              /* 4 or more halfwords left? */
117     beq     .r_end4_u
118     ldrh    r4, [r2]
119     orr     r3, r3, r4, lsl #8
120     ldrh    r4, [r2]
121     orr     r3, r3, r4, lsl #24
122     mov     r4, r4, lsr #8
123     ldrh    r5, [r2]
124     orr     r4, r4, r5, lsl #8
125     ldrh    r5, [r2]
126     orr     r4, r4, r5, lsl #24
127     stmia   r0!, {r3, r4}
128     mov     r3, r5, lsr #8
129 .r_end4_u:
131     tst     r1, #2              /* 2 or more halfwords left? */
132     beq     .r_end2_u
133     ldrh    r4, [r2]
134     orr     r3, r3, r4, lsl #8
135     ldrh    r4, [r2]
136     orr     r3, r3, r4, lsl #24
137     str     r3, [r0], #4
138     mov     r3, r4, lsr #8
139 .r_end2_u:
141     tst     r1, #1              /* one halfword left? */
142     ldrneh  r4, [r2]
143     orrne   r3, r3, r4, lsl #8
144     strneh  r3, [r0], #2
145     movne   r3, r4, lsr #8
147     strb    r3, [r0], #1        /* store final byte */
149     ldmpc   regs=r4-r5
151     /* 16-bit aligned */
152 .r_aligned:
153     tst     r0, #2              /* 32 bit aligned? */
154     ldrneh  r3, [r2]            /* no: read first halfword */
155     strneh  r3, [r0], #2        /*     store */
156     subne   r1, r1, #1          /*     one halfword taken */
158     sub     r1, r1, #8          /* adjust for zero-check and doing 8 halfwords/loop */
159 .r_loop_a:
160     ldrh    r3, [r2]            /* Read 8 halfwords and combine each pair */
161     ldrh    r4, [r2]            /*  into a word, then store all at once. */
162     orr     r3, r3, r4, lsl #16
163     ldrh    r4, [r2]
164     ldrh    r5, [r2]
165     orr     r4, r4, r5, lsl #16
166     ldrh    r5, [r2]
167     ldrh    r12, [r2]
168     orr     r5, r5, r12, lsl #16
169     ldrh    r12, [r2]
170     ldrh    lr, [r2]
171     orr     r12, r12, lr, lsl #16
172     stmia   r0!, {r3, r4, r5, r12}
173     subs    r1, r1, #8          /* 8 or more halfwords left? */
174     bge     .r_loop_a
175     
176     /* No need to adjust the count, only checking bits from now on. */
177     tst     r1, #4              /* 4 or more halfwords left? */
178     beq     .r_end4_a
179     ldrh    r3, [r2]
180     ldrh    r4, [r2]
181     orr     r3, r3, r4, lsl #16
182     ldrh    r4, [r2]
183     ldrh    r5, [r2]
184     orr     r4, r4, r5, lsl #16
185     stmia   r0!, {r3, r4}
186 .r_end4_a:
188     tst     r1, #2              /* 2 or more halfwords left? */
189     ldrneh  r3, [r2]
190     ldrneh  r4, [r2]
191     orrne   r3, r3, r4, lsl #16
192     strne   r3, [r0], #4
194     tst     r1, #1              /* one halfword left? */
195     ldrneh  r3, [r2]
196     strneh  r3, [r0], #2
198     ldmpc   regs=r4-r5
200 .r_end:
201     .size   copy_read_sectors,.r_end-copy_read_sectors
203     .align  2
204     .global copy_write_sectors
205     .type   copy_write_sectors,%function
206     
207 /* Write a number of words to the ATA data port
209  * Optimised for speed; assumes wordcount >= 10
211  * Arguments:
212  *   r0 - buffer address
213  *   r1 - word count
215  * Register usage:
216  *   r0 - current address
217  *   r1 - word count
218  *   r2 - ata port
219  *   r3..r5, r12, lr - read buffers
220  */
222 copy_write_sectors:
223     stmfd   sp!, {r4, r5, lr}
224     ldr     r2, =.ata_port
225     tst     r0, #1              /* 16 bit aligned? */
226     beq     .w_aligned
227     
228     /* not 16-bit aligned */
229     sub     r1, r1, #1          /* one halfword is done unconditionally */
230     ldrb    r3, [r0], #1        /* load 1st byte, now halfword aligned. */
232     tst     r0, #2              /* 32 bit aligned? */
233     beq     .w_noword_u
234     ldrh    r4, [r0], #2        /* load a halfword */
235     orr     r3, r3, r4, lsl #8  /* combine with old byte */
236     strh    r3, [r2]            /* write halfword */
237     mov     r3, r4, lsr #8
238     sub     r1, r1, #1          /* another halfword taken */
239 .w_noword_u:
241     sub     r1, r1, #8          /* adjust for zero-check and doing 8 halfwords/loop */
242 .w_loop_u:
243     ldmia   r0!, {r4, r5, r12, lr}
244     orr     r3, r3, r4, lsl #8  /* Load 4 words at once and decompose them */
245     strh    r3, [r2]            /*  into 8 halfwords in a way that the words */
246     mov     r3, r3, lsr #16     /*  are shifted by 8 bits, putting the high */
247     strh    r3, [r2]            /*  byte of one word into the low byte of */
248     mov     r4, r4, lsr #24     /*  the next. High byte of last word becomes */
249     orr     r4, r4, r5, lsl #8  /*  low byte of next round. */
250     strh    r4, [r2]
251     mov     r4, r4, lsr #16
252     strh    r4, [r2]
253     mov     r5, r5, lsr #24
254     orr     r5, r5, r12, lsl #8
255     strh    r5, [r2]
256     mov     r5, r5, lsr #16
257     strh    r5, [r2]
258     mov     r12, r12, lsr #24
259     orr     r12, r12, lr, lsl #8
260     strh    r12, [r2]
261     mov     r12, r12, lsr #16
262     strh    r12, [r2]
263     mov     r3, lr, lsr #24
264     subs    r1, r1, #8          /* 8 or more halfwords left? */
265     bge     .w_loop_u
266     
267     /* No need to adjust the count, only checking bits from now on. */
268     tst     r1, #4              /* 4 or more halfwords left? */
269     beq     .w_end4_u
270     ldmia   r0!, {r4, r5}
271     orr     r3, r3, r4, lsl #8
272     strh    r3, [r2]
273     mov     r3, r3, lsr #16
274     strh    r3, [r2]
275     mov     r4, r4, lsr #24
276     orr     r4, r4, r5, lsl #8
277     strh    r4, [r2]
278     mov     r4, r4, lsr #16
279     strh    r4, [r2]
280     mov     r3, r5, lsr #24
281 .w_end4_u:
283     tst     r1, #2              /* 2 or more halfwords left? */
284     beq     .w_end2_u
285     ldr     r4, [r0], #4
286     orr     r3, r3, r4, lsl #8
287     strh    r3, [r2]
288     mov     r3, r3, lsr #16
289     strh    r3, [r2]
290     mov     r3, r4, lsr #24
291 .w_end2_u:
293     tst     r1, #1              /* one halfword left? */
294     ldrneh  r4, [r0], #2
295     orrne   r3, r3, r4, lsl #8
296     strneh  r3, [r2]
297     movne   r3, r3, lsr #16
298     
299     ldrb    r4, [r0], #1        /* load final byte */
300     orr     r3, r3, r4, lsl #8
301     strh    r3, [r2]            /* write final halfword */
303     ldmpc   regs=r4-r5
305     /* 16-bit aligned */
306 .w_aligned:
307     tst     r0, #2              /* 32 bit aligned? */
308     ldrneh  r3, [r0], #2        /* no: load first halfword */
309     strneh  r3, [r2]            /*     write */
310     subne   r1, r1, #1          /*     one halfword taken */
312     sub     r1, r1, #8          /* adjust for zero-check and doing 8 halfwords/loop */
313 .w_loop_a:
314     ldmia   r0!, {r3, r4, r5, r12}
315     strh    r3, [r2]            /* Load 4 words and decompose them into */
316     mov     r3, r3, lsr #16     /*  2 halfwords each, and write those. */
317     strh    r3, [r2]
318     strh    r4, [r2]
319     mov     r4, r4, lsr #16
320     strh    r4, [r2]
321     strh    r5, [r2]
322     mov     r5, r5, lsr #16
323     strh    r5, [r2]
324     strh    r12, [r2]
325     mov     r12, r12, lsr #16
326     strh    r12, [r2]
327     subs    r1, r1, #8          /* 8 or more halfwords left? */
328     bge     .w_loop_a
330     /* No need to adjust the count, only checking bits from now on. */
331     tst     r1, #4              /* 4 or more halfwords left? */
332     beq     .w_end4_a
333     ldmia   r0!, {r3, r4}
334     strh    r3, [r2]
335     mov     r3, r3, lsr #16
336     strh    r3, [r2]
337     strh    r4, [r2]
338     mov     r4, r4, lsr #16
339     strh    r4, [r2]
340 .w_end4_a:
342     tst     r1, #2              /* 2 or more halfwords left? */
343     ldrne   r3, [r0], #4
344     strneh  r3, [r2]
345     movne   r3, r3, lsr #16
346     strneh  r3, [r2]
348     tst     r1, #1              /* one halfword left? */
349     ldrneh  r3, [r0], #2
350     strneh  r3, [r2]
352     ldmpc   regs=r4-r5
354 .w_end:
355     .size   copy_write_sectors,.w_end-copy_write_sectors