diff options
Diffstat (limited to 'firmware/drivers/ata.c')
-rw-r--r-- | firmware/drivers/ata.c | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index cb4e1e6b90..24abecdb5c 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #define ATA_COMMAND (*((volatile unsigned char*)0x06100107)) | 31 | #define ATA_COMMAND (*((volatile unsigned char*)0x06100107)) |
32 | #define ATA_STATUS ATA_COMMAND | 32 | #define ATA_STATUS ATA_COMMAND |
33 | #define ATA_CONTROL (*((volatile unsigned char*)0x06100306)) | 33 | #define ATA_CONTROL (*((volatile unsigned char*)0x06100306)) |
34 | #define ATA_ALT_STATUS ATA_CONTROL | ||
34 | 35 | ||
35 | #define SELECT_LBA 0x40 | 36 | #define SELECT_LBA 0x40 |
36 | 37 | ||
@@ -52,7 +53,7 @@ | |||
52 | static int wait_for_bsy(void) | 53 | static int wait_for_bsy(void) |
53 | { | 54 | { |
54 | char timeout = current_tick + HZ; | 55 | char timeout = current_tick + HZ; |
55 | while (TIME_BEFORE(current_tick, timeout) && (ATA_STATUS & STATUS_BSY)) | 56 | while (TIME_BEFORE(current_tick, timeout) && (ATA_ALT_STATUS & STATUS_BSY)) |
56 | yield(); | 57 | yield(); |
57 | 58 | ||
58 | if (TIME_BEFORE(current_tick, timeout)) | 59 | if (TIME_BEFORE(current_tick, timeout)) |
@@ -65,21 +66,21 @@ static int wait_for_rdy(void) | |||
65 | { | 66 | { |
66 | if (!wait_for_bsy()) | 67 | if (!wait_for_bsy()) |
67 | return 0; | 68 | return 0; |
68 | return ATA_STATUS & STATUS_RDY; | 69 | return ATA_ALT_STATUS & STATUS_RDY; |
69 | } | 70 | } |
70 | 71 | ||
71 | static int wait_for_start_of_transfer(void) | 72 | static int wait_for_start_of_transfer(void) |
72 | { | 73 | { |
73 | if (!wait_for_bsy()) | 74 | if (!wait_for_bsy()) |
74 | return 0; | 75 | return 0; |
75 | return (ATA_STATUS & (STATUS_RDY|STATUS_DRQ)) == (STATUS_RDY|STATUS_DRQ); | 76 | return (ATA_ALT_STATUS & (STATUS_BSY|STATUS_DRQ)) == STATUS_DRQ; |
76 | } | 77 | } |
77 | 78 | ||
78 | static int wait_for_end_of_transfer(void) | 79 | static int wait_for_end_of_transfer(void) |
79 | { | 80 | { |
80 | if (!wait_for_bsy()) | 81 | if (!wait_for_bsy()) |
81 | return 0; | 82 | return 0; |
82 | return (ATA_STATUS & (STATUS_RDY|STATUS_DRQ)) == STATUS_RDY; | 83 | return (ATA_ALT_STATUS & (STATUS_RDY|STATUS_DRQ)) == STATUS_RDY; |
83 | } | 84 | } |
84 | 85 | ||
85 | int ata_read_sectors(unsigned long start, | 86 | int ata_read_sectors(unsigned long start, |
@@ -107,6 +108,11 @@ int ata_read_sectors(unsigned long start, | |||
107 | 108 | ||
108 | for (j=0; j<256; j++) | 109 | for (j=0; j<256; j++) |
109 | ((unsigned short*)buf)[j] = SWAB16(ATA_DATA); | 110 | ((unsigned short*)buf)[j] = SWAB16(ATA_DATA); |
111 | |||
112 | #ifdef USE_INTERRUPT | ||
113 | /* reading the status register clears the interrupt */ | ||
114 | j = ATA_STATUS; | ||
115 | #endif | ||
110 | } | 116 | } |
111 | 117 | ||
112 | led_turn_off(); | 118 | led_turn_off(); |
@@ -139,6 +145,11 @@ int ata_write_sectors(unsigned long start, | |||
139 | 145 | ||
140 | for (j=0; j<256; j++) | 146 | for (j=0; j<256; j++) |
141 | ATA_DATA = SWAB16(((unsigned short*)buf)[j]); | 147 | ATA_DATA = SWAB16(((unsigned short*)buf)[j]); |
148 | |||
149 | #ifdef USE_INTERRUPT | ||
150 | /* reading the status register clears the interrupt */ | ||
151 | j = ATA_STATUS; | ||
152 | #endif | ||
142 | } | 153 | } |
143 | 154 | ||
144 | led_turn_off (); | 155 | led_turn_off (); |
@@ -193,6 +204,27 @@ static int freeze_lock(void) | |||
193 | return 0; | 204 | return 0; |
194 | } | 205 | } |
195 | 206 | ||
207 | int ata_spindown(int time) | ||
208 | { | ||
209 | if (!wait_for_rdy()) | ||
210 | return -1; | ||
211 | |||
212 | if ( time == -1 ) { | ||
213 | ATA_COMMAND = CMD_STANDBY_IMMEDIATE; | ||
214 | } | ||
215 | else { | ||
216 | if (time > 255) | ||
217 | return -1; | ||
218 | ATA_NSECTOR = time & 0xff; | ||
219 | ATA_COMMAND = CMD_STANDBY; | ||
220 | } | ||
221 | |||
222 | if (!wait_for_rdy()) | ||
223 | return -1; | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
196 | int ata_hard_reset(void) | 228 | int ata_hard_reset(void) |
197 | { | 229 | { |
198 | clear_bit(1,PADR); | 230 | clear_bit(1,PADR); |