summaryrefslogtreecommitdiff
path: root/firmware/drivers/ata.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/ata.c')
-rw-r--r--firmware/drivers/ata.c42
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 @@
52static int wait_for_bsy(void) 53static 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
71static int wait_for_start_of_transfer(void) 72static 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
78static int wait_for_end_of_transfer(void) 79static 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
85int ata_read_sectors(unsigned long start, 86int 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
207int 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
196int ata_hard_reset(void) 228int ata_hard_reset(void)
197{ 229{
198 clear_bit(1,PADR); 230 clear_bit(1,PADR);