diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/ata.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 716af74ae2..95711c60ea 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #define ATA_CONTROL (*((volatile unsigned char*)0x06200306)) | 37 | #define ATA_CONTROL (*((volatile unsigned char*)0x06200306)) |
38 | #define ATA_ALT_STATUS ATA_CONTROL | 38 | #define ATA_ALT_STATUS ATA_CONTROL |
39 | 39 | ||
40 | #define SELECT_DEVICE1 0x10 | ||
40 | #define SELECT_LBA 0x40 | 41 | #define SELECT_LBA 0x40 |
41 | 42 | ||
42 | #define STATUS_BSY 0x80 | 43 | #define STATUS_BSY 0x80 |
@@ -54,7 +55,8 @@ | |||
54 | #define CMD_SLEEP 0xE6 | 55 | #define CMD_SLEEP 0xE6 |
55 | #define CMD_SECURITY_FREEZE_LOCK 0xF5 | 56 | #define CMD_SECURITY_FREEZE_LOCK 0xF5 |
56 | 57 | ||
57 | struct mutex ata_mtx; | 58 | static struct mutex ata_mtx; |
59 | static char device; /* device 0 (master) or 1 (slave) */ | ||
58 | 60 | ||
59 | static int wait_for_bsy(void) | 61 | static int wait_for_bsy(void) |
60 | { | 62 | { |
@@ -114,7 +116,7 @@ int ata_read_sectors(unsigned long start, | |||
114 | ATA_SECTOR = start & 0xff; | 116 | ATA_SECTOR = start & 0xff; |
115 | ATA_LCYL = (start >> 8) & 0xff; | 117 | ATA_LCYL = (start >> 8) & 0xff; |
116 | ATA_HCYL = (start >> 16) & 0xff; | 118 | ATA_HCYL = (start >> 16) & 0xff; |
117 | ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA; | 119 | ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA | device; |
118 | ATA_COMMAND = CMD_READ_SECTORS; | 120 | ATA_COMMAND = CMD_READ_SECTORS; |
119 | 121 | ||
120 | for (i=0; i<count; i++) { | 122 | for (i=0; i<count; i++) { |
@@ -164,7 +166,7 @@ int ata_write_sectors(unsigned long start, | |||
164 | ATA_SECTOR = start & 0xff; | 166 | ATA_SECTOR = start & 0xff; |
165 | ATA_LCYL = (start >> 8) & 0xff; | 167 | ATA_LCYL = (start >> 8) & 0xff; |
166 | ATA_HCYL = (start >> 16) & 0xff; | 168 | ATA_HCYL = (start >> 16) & 0xff; |
167 | ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA; | 169 | ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA | device; |
168 | ATA_COMMAND = CMD_WRITE_SECTORS; | 170 | ATA_COMMAND = CMD_WRITE_SECTORS; |
169 | 171 | ||
170 | for (i=0; i<count; i++) { | 172 | for (i=0; i<count; i++) { |
@@ -289,7 +291,7 @@ int ata_soft_reset(void) | |||
289 | 291 | ||
290 | mutex_lock(&ata_mtx); | 292 | mutex_lock(&ata_mtx); |
291 | 293 | ||
292 | ATA_SELECT = SELECT_LBA; | 294 | ATA_SELECT = SELECT_LBA | device; |
293 | ATA_CONTROL = CONTROL_nIEN|CONTROL_SRST; | 295 | ATA_CONTROL = CONTROL_nIEN|CONTROL_SRST; |
294 | sleep(HZ/20000); /* >= 5us */ | 296 | sleep(HZ/20000); /* >= 5us */ |
295 | 297 | ||
@@ -302,6 +304,27 @@ int ata_soft_reset(void) | |||
302 | return ret; | 304 | return ret; |
303 | } | 305 | } |
304 | 306 | ||
307 | static int master_slave(void) | ||
308 | { | ||
309 | /* master? */ | ||
310 | ATA_SELECT = 0; | ||
311 | if ( ATA_STATUS & STATUS_RDY ) { | ||
312 | device = 0; | ||
313 | DEBUGF("Found master harddisk\n"); | ||
314 | } | ||
315 | else { | ||
316 | /* slave? */ | ||
317 | ATA_SELECT = SELECT_DEVICE1; | ||
318 | if ( ATA_STATUS & STATUS_RDY ) { | ||
319 | device = SELECT_DEVICE1; | ||
320 | DEBUGF("Found slave harddisk\n"); | ||
321 | } | ||
322 | else | ||
323 | return -1; | ||
324 | } | ||
325 | return 0; | ||
326 | } | ||
327 | |||
305 | int ata_init(void) | 328 | int ata_init(void) |
306 | { | 329 | { |
307 | mutex_init(&ata_mtx); | 330 | mutex_init(&ata_mtx); |
@@ -311,15 +334,21 @@ int ata_init(void) | |||
311 | /* activate ATA */ | 334 | /* activate ATA */ |
312 | PADR &= ~0x80; | 335 | PADR &= ~0x80; |
313 | 336 | ||
314 | if (!ata_hard_reset()) | 337 | if (master_slave()) |
315 | return -1; | 338 | return -1; |
339 | |||
340 | if (!ata_hard_reset()) | ||
341 | return -2; | ||
316 | 342 | ||
317 | if (!check_registers()) | 343 | if (!check_registers()) |
318 | return -2; | 344 | return -3; |
319 | 345 | ||
320 | if (freeze_lock() < 0) | 346 | if (freeze_lock() < 0) |
321 | return -4; | 347 | return -4; |
322 | 348 | ||
349 | if (ata_spindown(1) < 0) | ||
350 | return -5; | ||
351 | |||
323 | ATA_SELECT = SELECT_LBA; | 352 | ATA_SELECT = SELECT_LBA; |
324 | ATA_CONTROL = CONTROL_nIEN; | 353 | ATA_CONTROL = CONTROL_nIEN; |
325 | 354 | ||