diff options
author | Björn Stenberg <bjorn@haxx.se> | 2002-04-21 22:06:12 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2002-04-21 22:06:12 +0000 |
commit | 1acfd6b39d30a52c670263db50468590b8661f58 (patch) | |
tree | f5fd00e8bc5edc5b2934d8cfbfc48233d55ead85 /firmware/ata.c | |
parent | 78e6bb8ee25ed3215b010f402a0af849b7f7d25c (diff) | |
download | rockbox-1acfd6b39d30a52c670263db50468590b8661f58.tar.gz rockbox-1acfd6b39d30a52c670263db50468590b8661f58.zip |
Alan's ATA code, or what's left of it after I have laid my grubby little hands
on it. :-) It compiles, but it probably doesn't work...
Also, a stub for future kernel code. A sleep() and a dummy yield(), just so we
can start to use them in other code.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@163 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/ata.c')
-rw-r--r-- | firmware/ata.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/firmware/ata.c b/firmware/ata.c new file mode 100644 index 0000000000..460808a217 --- /dev/null +++ b/firmware/ata.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
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 | #include "ata.h" | ||
20 | #include "kernel.h" | ||
21 | #include "led.h" | ||
22 | |||
23 | #define ATA_DATA (*((volatile unsigned short*)0x06104100)) | ||
24 | #define ATA_ERROR (*((volatile unsigned char*)0x06100101)) | ||
25 | #define ATA_FEATURE ATA_ERROR | ||
26 | #define ATA_NSECTOR (*((volatile unsigned char*)0x06100102)) | ||
27 | #define ATA_SECTOR (*((volatile unsigned char*)0x06100103)) | ||
28 | #define ATA_LCYL (*((volatile unsigned char*)0x06100104)) | ||
29 | #define ATA_HCYL (*((volatile unsigned char*)0x06100105)) | ||
30 | #define ATA_SELECT (*((volatile unsigned char*)0x06100106)) | ||
31 | #define ATA_COMMAND (*((volatile unsigned char*)0x06100107)) | ||
32 | #define ATA_STATUS ATA_COMMAND | ||
33 | #define ATA_CONTROL (*((volatile unsigned char*)0x06100306)) | ||
34 | |||
35 | #define SELECT_LBA 0x40 | ||
36 | |||
37 | #define STATUS_BSY 0x80 | ||
38 | #define STATUS_RDY 0x40 | ||
39 | #define STATUS_DRQ 0x08 | ||
40 | #define STATUS_ERR 0x01 | ||
41 | |||
42 | #define CONTROL_nIEN 0x02 | ||
43 | #define CONTROL_SRST 0x04 | ||
44 | |||
45 | #define CMD_READ_SECTORS 0x20 | ||
46 | #define CMD_WRITE_SECTORS 0x30 | ||
47 | #define CMD_STANDBY_IMMEDIATE 0xE0 | ||
48 | #define CMD_STANDBY 0xE2 | ||
49 | #define CMD_SLEEP 0xE6 | ||
50 | #define CMD_SECURITY_FREEZE_LOCK 0xF5 | ||
51 | |||
52 | static int wait_for_bsy(void) | ||
53 | { | ||
54 | char timeout = current_tick + HZ; | ||
55 | while (TIME_BEFORE(current_tick, timeout) && (ATA_STATUS & STATUS_BSY)) | ||
56 | yield(); | ||
57 | |||
58 | if (TIME_BEFORE(current_tick, timeout)) | ||
59 | return 1; | ||
60 | else | ||
61 | return 0; /* timeout */ | ||
62 | } | ||
63 | |||
64 | static int wait_for_rdy(void) | ||
65 | { | ||
66 | if (!wait_for_bsy()) | ||
67 | return 0; | ||
68 | return ATA_STATUS & STATUS_RDY; | ||
69 | } | ||
70 | |||
71 | static int wait_for_start_of_transfer(void) | ||
72 | { | ||
73 | if (!wait_for_bsy()) | ||
74 | return 0; | ||
75 | return (ATA_STATUS & (STATUS_RDY|STATUS_DRQ)) == (STATUS_RDY|STATUS_DRQ); | ||
76 | } | ||
77 | |||
78 | static int wait_for_end_of_transfer(void) | ||
79 | { | ||
80 | if (!wait_for_bsy()) | ||
81 | return 0; | ||
82 | return (ATA_STATUS & (STATUS_RDY|STATUS_DRQ)) == STATUS_RDY; | ||
83 | } | ||
84 | |||
85 | int ata_read_sectors(unsigned long start, | ||
86 | unsigned char count, | ||
87 | unsigned short* buf) | ||
88 | { | ||
89 | int i; | ||
90 | |||
91 | if (!wait_for_rdy()) | ||
92 | return 0; | ||
93 | |||
94 | led_turn_on(); | ||
95 | |||
96 | ATA_NSECTOR = count; | ||
97 | ATA_SECTOR = start & 0xff; | ||
98 | ATA_LCYL = (start >> 8) & 0xff; | ||
99 | ATA_HCYL = (start >> 16) & 0xff; | ||
100 | ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA; | ||
101 | ATA_COMMAND = CMD_READ_SECTORS; | ||
102 | |||
103 | for (i=0; i<count; i++) { | ||
104 | int j; | ||
105 | if (!wait_for_start_of_transfer()) | ||
106 | return 0; | ||
107 | |||
108 | for (j=0; j<256; j++) | ||
109 | buf[j] = SWAB16(ATA_DATA); | ||
110 | } | ||
111 | |||
112 | led_turn_off(); | ||
113 | |||
114 | return wait_for_end_of_transfer(); | ||
115 | } | ||
116 | |||
117 | int ata_write_sectors(unsigned long start, | ||
118 | unsigned char count, | ||
119 | unsigned short* buf) | ||
120 | { | ||
121 | int i; | ||
122 | |||
123 | if (!wait_for_rdy()) | ||
124 | return 0; | ||
125 | |||
126 | led_turn_on (); | ||
127 | |||
128 | ATA_NSECTOR = count; | ||
129 | ATA_SECTOR = start & 0xff; | ||
130 | ATA_LCYL = (start >> 8) & 0xff; | ||
131 | ATA_HCYL = (start >> 16) & 0xff; | ||
132 | ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA; | ||
133 | ATA_COMMAND = CMD_WRITE_SECTORS; | ||
134 | |||
135 | for (i=0; i<count; i++) { | ||
136 | int j; | ||
137 | if (!wait_for_start_of_transfer()) | ||
138 | return 0; | ||
139 | |||
140 | for (j=0; j<256; j++) | ||
141 | ATA_DATA = SWAB16(buf[j]); | ||
142 | } | ||
143 | |||
144 | led_turn_off (); | ||
145 | |||
146 | return wait_for_end_of_transfer(); | ||
147 | } | ||
148 | |||
149 | static int check_registers(void) | ||
150 | { | ||
151 | if ( ATA_STATUS & STATUS_BSY ) | ||
152 | return 0; | ||
153 | |||
154 | ATA_NSECTOR = 0xa5; | ||
155 | ATA_SECTOR = 0x5a; | ||
156 | ATA_LCYL = 0xaa; | ||
157 | ATA_HCYL = 0x55; | ||
158 | |||
159 | if ((ATA_NSECTOR == 0xa5) && | ||
160 | (ATA_SECTOR == 0x5a) && | ||
161 | (ATA_LCYL == 0xaa) && | ||
162 | (ATA_HCYL == 0x55)) | ||
163 | return 1; | ||
164 | else | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static int check_harddisk(void) | ||
169 | { | ||
170 | if (!wait_for_rdy()) | ||
171 | return 0; | ||
172 | |||
173 | if ((ATA_NSECTOR == 1) && | ||
174 | (ATA_SECTOR == 1) && | ||
175 | (ATA_LCYL == 0) && | ||
176 | (ATA_HCYL == 0) && | ||
177 | (ATA_SELECT == 0)) | ||
178 | return 1; | ||
179 | else | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int freeze_lock(void) | ||
184 | { | ||
185 | if (!wait_for_rdy()) | ||
186 | return -1; | ||
187 | |||
188 | ATA_COMMAND = CMD_SECURITY_FREEZE_LOCK; | ||
189 | |||
190 | if (!wait_for_rdy()) | ||
191 | return -1; | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | int ata_hard_reset(void) | ||
197 | { | ||
198 | clear_bit(1,PADR); | ||
199 | sleep(HZ/500); | ||
200 | |||
201 | set_bit(1,PADR); | ||
202 | sleep(HZ/500); | ||
203 | |||
204 | return wait_for_rdy(); | ||
205 | } | ||
206 | |||
207 | int ata_soft_reset(void) | ||
208 | { | ||
209 | ATA_SELECT = SELECT_LBA; | ||
210 | ATA_CONTROL = CONTROL_nIEN|CONTROL_SRST; | ||
211 | sleep(HZ/20000); /* >= 5us */ | ||
212 | |||
213 | ATA_CONTROL = CONTROL_nIEN; | ||
214 | sleep(HZ/400); /* >2ms */ | ||
215 | |||
216 | return wait_for_rdy(); | ||
217 | } | ||
218 | |||
219 | int ata_init(void) | ||
220 | { | ||
221 | led_turn_off(); | ||
222 | |||
223 | /* activate ATA */ | ||
224 | PADR |= 0x80; | ||
225 | |||
226 | if (!ata_hard_reset()) | ||
227 | return -1; | ||
228 | |||
229 | if (!check_registers()) | ||
230 | return -2; | ||
231 | |||
232 | if (!check_harddisk()) | ||
233 | return -3; | ||
234 | |||
235 | if (!freeze_lock()) | ||
236 | return -4; | ||
237 | |||
238 | ATA_SELECT = SELECT_LBA; | ||
239 | ATA_CONTROL = CONTROL_nIEN; | ||
240 | |||
241 | return 0; | ||
242 | } | ||