diff options
Diffstat (limited to 'firmware/drivers/ata.c')
-rw-r--r-- | firmware/drivers/ata.c | 80 |
1 files changed, 69 insertions, 11 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 0e0c48833c..716af74ae2 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -54,6 +54,8 @@ | |||
54 | #define CMD_SLEEP 0xE6 | 54 | #define CMD_SLEEP 0xE6 |
55 | #define CMD_SECURITY_FREEZE_LOCK 0xF5 | 55 | #define CMD_SECURITY_FREEZE_LOCK 0xF5 |
56 | 56 | ||
57 | struct mutex ata_mtx; | ||
58 | |||
57 | static int wait_for_bsy(void) | 59 | static int wait_for_bsy(void) |
58 | { | 60 | { |
59 | int timeout = current_tick + HZ*4; | 61 | int timeout = current_tick + HZ*4; |
@@ -96,9 +98,15 @@ int ata_read_sectors(unsigned long start, | |||
96 | void* buf) | 98 | void* buf) |
97 | { | 99 | { |
98 | int i; | 100 | int i; |
101 | int ret = 0; | ||
99 | 102 | ||
103 | mutex_lock(&ata_mtx); | ||
104 | |||
100 | if (!wait_for_rdy()) | 105 | if (!wait_for_rdy()) |
106 | { | ||
107 | mutex_unlock(&ata_mtx); | ||
101 | return -1; | 108 | return -1; |
109 | } | ||
102 | 110 | ||
103 | led(true); | 111 | led(true); |
104 | 112 | ||
@@ -112,7 +120,10 @@ int ata_read_sectors(unsigned long start, | |||
112 | for (i=0; i<count; i++) { | 120 | for (i=0; i<count; i++) { |
113 | int j; | 121 | int j; |
114 | if (!wait_for_start_of_transfer()) | 122 | if (!wait_for_start_of_transfer()) |
123 | { | ||
124 | mutex_unlock(&ata_mtx); | ||
115 | return -1; | 125 | return -1; |
126 | } | ||
116 | 127 | ||
117 | for (j=0; j<256; j++) | 128 | for (j=0; j<256; j++) |
118 | ((unsigned short*)buf)[j] = SWAB16(ATA_DATA); | 129 | ((unsigned short*)buf)[j] = SWAB16(ATA_DATA); |
@@ -126,9 +137,10 @@ int ata_read_sectors(unsigned long start, | |||
126 | led(false); | 137 | led(false); |
127 | 138 | ||
128 | if(!wait_for_end_of_transfer()) | 139 | if(!wait_for_end_of_transfer()) |
129 | return -1; | 140 | ret = -1; |
130 | else | 141 | |
131 | return 0; | 142 | mutex_unlock(&ata_mtx); |
143 | return ret; | ||
132 | } | 144 | } |
133 | 145 | ||
134 | #ifdef DISK_WRITE | 146 | #ifdef DISK_WRITE |
@@ -138,8 +150,13 @@ int ata_write_sectors(unsigned long start, | |||
138 | { | 150 | { |
139 | int i; | 151 | int i; |
140 | 152 | ||
153 | mutex_lock(&ata_mtx); | ||
154 | |||
141 | if (!wait_for_rdy()) | 155 | if (!wait_for_rdy()) |
156 | { | ||
157 | mutex_unlock(&ata_mtx); | ||
142 | return 0; | 158 | return 0; |
159 | } | ||
143 | 160 | ||
144 | led(true); | 161 | led(true); |
145 | 162 | ||
@@ -153,7 +170,10 @@ int ata_write_sectors(unsigned long start, | |||
153 | for (i=0; i<count; i++) { | 170 | for (i=0; i<count; i++) { |
154 | int j; | 171 | int j; |
155 | if (!wait_for_start_of_transfer()) | 172 | if (!wait_for_start_of_transfer()) |
173 | { | ||
174 | mutex_unlock(&ata_mtx); | ||
156 | return 0; | 175 | return 0; |
176 | } | ||
157 | 177 | ||
158 | for (j=0; j<256; j++) | 178 | for (j=0; j<256; j++) |
159 | ATA_DATA = SWAB16(((unsigned short*)buf)[j]); | 179 | ATA_DATA = SWAB16(((unsigned short*)buf)[j]); |
@@ -166,14 +186,24 @@ int ata_write_sectors(unsigned long start, | |||
166 | 186 | ||
167 | led(false); | 187 | led(false); |
168 | 188 | ||
169 | return wait_for_end_of_transfer(); | 189 | i = wait_for_end_of_transfer(); |
190 | |||
191 | mutex_unlock(&ata_mtx); | ||
192 | return i; | ||
170 | } | 193 | } |
171 | #endif | 194 | #endif |
172 | 195 | ||
173 | static int check_registers(void) | 196 | static int check_registers(void) |
174 | { | 197 | { |
198 | int ret = 0; | ||
199 | |||
200 | mutex_lock(&ata_mtx); | ||
201 | |||
175 | if ( ATA_STATUS & STATUS_BSY ) | 202 | if ( ATA_STATUS & STATUS_BSY ) |
203 | { | ||
204 | mutex_unlock(&ata_mtx); | ||
176 | return 0; | 205 | return 0; |
206 | } | ||
177 | 207 | ||
178 | ATA_NSECTOR = 0xa5; | 208 | ATA_NSECTOR = 0xa5; |
179 | ATA_SECTOR = 0x5a; | 209 | ATA_SECTOR = 0x5a; |
@@ -184,9 +214,10 @@ static int check_registers(void) | |||
184 | (ATA_SECTOR == 0x5a) && | 214 | (ATA_SECTOR == 0x5a) && |
185 | (ATA_LCYL == 0xaa) && | 215 | (ATA_LCYL == 0xaa) && |
186 | (ATA_HCYL == 0x55)) | 216 | (ATA_HCYL == 0x55)) |
187 | return 1; | 217 | ret = 1; |
188 | else | 218 | |
189 | return 0; | 219 | mutex_unlock(&ata_mtx); |
220 | return ret; | ||
190 | } | 221 | } |
191 | 222 | ||
192 | static int freeze_lock(void) | 223 | static int freeze_lock(void) |
@@ -204,38 +235,60 @@ static int freeze_lock(void) | |||
204 | 235 | ||
205 | int ata_spindown(int time) | 236 | int ata_spindown(int time) |
206 | { | 237 | { |
238 | int ret = 0; | ||
239 | |||
240 | mutex_lock(&ata_mtx); | ||
241 | |||
207 | if(!wait_for_rdy()) | 242 | if(!wait_for_rdy()) |
243 | { | ||
244 | mutex_unlock(&ata_mtx); | ||
208 | return -1; | 245 | return -1; |
246 | } | ||
209 | 247 | ||
210 | if ( time == -1 ) { | 248 | if ( time == -1 ) { |
211 | ATA_COMMAND = CMD_STANDBY_IMMEDIATE; | 249 | ATA_COMMAND = CMD_STANDBY_IMMEDIATE; |
212 | } | 250 | } |
213 | else { | 251 | else { |
214 | if (time > 255) | 252 | if (time > 255) |
253 | { | ||
254 | mutex_unlock(&ata_mtx); | ||
215 | return -1; | 255 | return -1; |
256 | } | ||
216 | ATA_NSECTOR = time & 0xff; | 257 | ATA_NSECTOR = time & 0xff; |
217 | ATA_COMMAND = CMD_STANDBY; | 258 | ATA_COMMAND = CMD_STANDBY; |
218 | } | 259 | } |
219 | 260 | ||
220 | if (!wait_for_rdy()) | 261 | if (!wait_for_rdy()) |
221 | return -1; | 262 | ret = -1; |
222 | 263 | ||
223 | return 0; | 264 | mutex_unlock(&ata_mtx); |
265 | return ret; | ||
224 | } | 266 | } |
225 | 267 | ||
226 | int ata_hard_reset(void) | 268 | int ata_hard_reset(void) |
227 | { | 269 | { |
270 | int ret; | ||
271 | |||
272 | mutex_lock(&ata_mtx); | ||
273 | |||
228 | PADR &= ~0x0002; | 274 | PADR &= ~0x0002; |
229 | 275 | ||
230 | sleep(2); | 276 | sleep(2); |
231 | 277 | ||
232 | PADR |= 0x0002; | 278 | PADR |= 0x0002; |
233 | 279 | ||
234 | return wait_for_rdy(); | 280 | ret = wait_for_rdy(); |
281 | |||
282 | mutex_unlock(&ata_mtx); | ||
283 | return ret; | ||
235 | } | 284 | } |
236 | 285 | ||
237 | int ata_soft_reset(void) | 286 | int ata_soft_reset(void) |
238 | { | 287 | { |
288 | int ret; | ||
289 | |||
290 | mutex_lock(&ata_mtx); | ||
291 | |||
239 | ATA_SELECT = SELECT_LBA; | 292 | ATA_SELECT = SELECT_LBA; |
240 | ATA_CONTROL = CONTROL_nIEN|CONTROL_SRST; | 293 | ATA_CONTROL = CONTROL_nIEN|CONTROL_SRST; |
241 | sleep(HZ/20000); /* >= 5us */ | 294 | sleep(HZ/20000); /* >= 5us */ |
@@ -243,11 +296,16 @@ int ata_soft_reset(void) | |||
243 | ATA_CONTROL = CONTROL_nIEN; | 296 | ATA_CONTROL = CONTROL_nIEN; |
244 | sleep(HZ/400); /* >2ms */ | 297 | sleep(HZ/400); /* >2ms */ |
245 | 298 | ||
246 | return wait_for_rdy(); | 299 | ret = wait_for_rdy(); |
300 | |||
301 | mutex_unlock(&ata_mtx); | ||
302 | return ret; | ||
247 | } | 303 | } |
248 | 304 | ||
249 | int ata_init(void) | 305 | int ata_init(void) |
250 | { | 306 | { |
307 | mutex_init(&ata_mtx); | ||
308 | |||
251 | led(false); | 309 | led(false); |
252 | 310 | ||
253 | /* activate ATA */ | 311 | /* activate ATA */ |