summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2002-09-05 15:25:08 +0000
committerBjörn Stenberg <bjorn@haxx.se>2002-09-05 15:25:08 +0000
commit8ccbc766a451f875289559a0cf530bbbb1223ec1 (patch)
tree130f85cf6e1848c9da3cd0b42c2e6f19b00319bd
parente4d35f617096d0cb0beb89457a44048097380fd8 (diff)
downloadrockbox-8ccbc766a451f875289559a0cf530bbbb1223ec1.tar.gz
rockbox-8ccbc766a451f875289559a0cf530bbbb1223ec1.zip
Now uses READ MULTIPLE command. Also corrected some return values.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2186 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/ata.c85
1 files changed, 62 insertions, 23 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 2f867d20b1..8d892788a9 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -70,8 +70,12 @@
70 70
71#define CMD_READ_SECTORS 0x20 71#define CMD_READ_SECTORS 0x20
72#define CMD_WRITE_SECTORS 0x30 72#define CMD_WRITE_SECTORS 0x30
73#define CMD_READ_MULTIPLE 0xC4
74#define CMD_WRITE_MULTIPLE 0xC5
75#define CMD_SET_MULTIPLE_MODE 0xC6
73#define CMD_STANDBY_IMMEDIATE 0xE0 76#define CMD_STANDBY_IMMEDIATE 0xE0
74#define CMD_STANDBY 0xE2 77#define CMD_STANDBY 0xE2
78#define CMD_IDENTIFY 0xEC
75#define CMD_SLEEP 0xE6 79#define CMD_SLEEP 0xE6
76#define CMD_SECURITY_FREEZE_LOCK 0xF5 80#define CMD_SECURITY_FREEZE_LOCK 0xF5
77 81
@@ -96,6 +100,9 @@ static int delayed_sector_num;
96static long last_user_activity = -1; 100static long last_user_activity = -1;
97static long last_disk_activity = -1; 101static long last_disk_activity = -1;
98 102
103static int multisectors; /* number of supported multisectors */
104static unsigned short identify_info[SECTOR_SIZE];
105
99#ifdef USE_POWEROFF 106#ifdef USE_POWEROFF
100static int ata_power_on(void); 107static int ata_power_on(void);
101#endif 108#endif
@@ -110,13 +117,9 @@ static int wait_for_bsy(void)
110 yield(); 117 yield();
111 118
112 if (TIME_BEFORE(current_tick, timeout)) 119 if (TIME_BEFORE(current_tick, timeout))
113 {
114 return 1; 120 return 1;
115 }
116 else 121 else
117 {
118 return 0; /* timeout */ 122 return 0; /* timeout */
119 }
120} 123}
121 124
122static int wait_for_rdy(void) __attribute__ ((section (".icode"))); 125static int wait_for_rdy(void) __attribute__ ((section (".icode")));
@@ -134,13 +137,9 @@ static int wait_for_rdy(void)
134 yield(); 137 yield();
135 138
136 if (TIME_BEFORE(current_tick, timeout)) 139 if (TIME_BEFORE(current_tick, timeout))
137 {
138 return STATUS_RDY; 140 return STATUS_RDY;
139 }
140 else 141 else
141 {
142 return 0; /* timeout */ 142 return 0; /* timeout */
143 }
144} 143}
145 144
146static int wait_for_start_of_transfer(void) __attribute__ ((section (".icode"))); 145static int wait_for_start_of_transfer(void) __attribute__ ((section (".icode")));
@@ -166,7 +165,6 @@ int ata_read_sectors(unsigned long start,
166 int count, 165 int count,
167 void* buf) 166 void* buf)
168{ 167{
169 int i;
170 int ret = 0; 168 int ret = 0;
171 169
172 last_disk_activity = current_tick; 170 last_disk_activity = current_tick;
@@ -193,7 +191,7 @@ int ata_read_sectors(unsigned long start,
193 if (!wait_for_rdy()) 191 if (!wait_for_rdy())
194 { 192 {
195 mutex_unlock(&ata_mtx); 193 mutex_unlock(&ata_mtx);
196 return -1; 194 return -2;
197 } 195 }
198 196
199 led(true); 197 led(true);
@@ -207,27 +205,36 @@ int ata_read_sectors(unsigned long start,
207 ATA_LCYL = (start >> 8) & 0xff; 205 ATA_LCYL = (start >> 8) & 0xff;
208 ATA_HCYL = (start >> 16) & 0xff; 206 ATA_HCYL = (start >> 16) & 0xff;
209 ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA | ata_device; 207 ATA_SELECT = ((start >> 24) & 0xf) | SELECT_LBA | ata_device;
210 ATA_COMMAND = CMD_READ_SECTORS; 208 ATA_COMMAND = CMD_READ_MULTIPLE;
211 209
212 for (i=0; i<count; i++) { 210 while (count) {
213 int j; 211 int j;
212 int sectors;
213
214 if (!wait_for_start_of_transfer()) 214 if (!wait_for_start_of_transfer())
215 { 215 {
216 led(false);
216 mutex_unlock(&ata_mtx); 217 mutex_unlock(&ata_mtx);
217 return -1; 218 return -1;
218 } 219 }
219 220
220 /* if destination address is odd, use byte copying, 221 /* if destination address is odd, use byte copying,
221 otherwise use word copying */ 222 otherwise use word copying */
223
224 if (count >= multisectors )
225 sectors = multisectors;
226 else
227 sectors = count;
228
222 if ( (unsigned int)buf & 1 ) { 229 if ( (unsigned int)buf & 1 ) {
223 for (j=0; j<SECTOR_SIZE/2; j++) { 230 for (j=0; j < sectors * SECTOR_SIZE / 2; j++) {
224 unsigned short tmp = SWAB16(ATA_DATA); 231 unsigned short tmp = SWAB16(ATA_DATA);
225 ((unsigned char*)buf)[j*2] = tmp >> 8; 232 ((unsigned char*)buf)[j*2] = tmp >> 8;
226 ((unsigned char*)buf)[j*2+1] = tmp & 0xff; 233 ((unsigned char*)buf)[j*2+1] = tmp & 0xff;
227 } 234 }
228 } 235 }
229 else { 236 else {
230 for (j=0; j<SECTOR_SIZE/2; j++) 237 for (j=0; j < sectors * SECTOR_SIZE / 2; j++)
231 ((unsigned short*)buf)[j] = SWAB16(ATA_DATA); 238 ((unsigned short*)buf)[j] = SWAB16(ATA_DATA);
232 } 239 }
233 240
@@ -235,13 +242,14 @@ int ata_read_sectors(unsigned long start,
235 /* reading the status register clears the interrupt */ 242 /* reading the status register clears the interrupt */
236 j = ATA_STATUS; 243 j = ATA_STATUS;
237#endif 244#endif
238 buf += SECTOR_SIZE; /* Advance one sector */ 245 buf += sectors * SECTOR_SIZE; /* Advance one sector */
246 count -= sectors;
239 } 247 }
240 248
241 led(false);
242
243 if(!wait_for_end_of_transfer()) 249 if(!wait_for_end_of_transfer())
244 ret = -1; 250 ret = -3;
251
252 led(false);
245 253
246 mutex_unlock(&ata_mtx); 254 mutex_unlock(&ata_mtx);
247 255
@@ -283,7 +291,7 @@ int ata_write_sectors(unsigned long start,
283 if (!wait_for_rdy()) 291 if (!wait_for_rdy())
284 { 292 {
285 mutex_unlock(&ata_mtx); 293 mutex_unlock(&ata_mtx);
286 return 0; 294 return -2;
287 } 295 }
288 296
289 led(true); 297 led(true);
@@ -318,7 +326,8 @@ int ata_write_sectors(unsigned long start,
318 326
319 led(false); 327 led(false);
320 328
321 i = wait_for_end_of_transfer(); 329 if(!wait_for_end_of_transfer())
330 i = -3;
322 331
323 mutex_unlock(&ata_mtx); 332 mutex_unlock(&ata_mtx);
324 333
@@ -375,7 +384,7 @@ static int freeze_lock(void)
375 ATA_COMMAND = CMD_SECURITY_FREEZE_LOCK; 384 ATA_COMMAND = CMD_SECURITY_FREEZE_LOCK;
376 385
377 if (!wait_for_rdy()) 386 if (!wait_for_rdy())
378 return -1; 387 return -2;
379 388
380 return 0; 389 return 0;
381} 390}
@@ -415,7 +424,7 @@ static int ata_perform_sleep(void)
415 if (!wait_for_rdy()) 424 if (!wait_for_rdy())
416 { 425 {
417 DEBUGF("ata_perform_sleep() - CMD failed\n"); 426 DEBUGF("ata_perform_sleep() - CMD failed\n");
418 ret = -1; 427 ret = -2;
419 } 428 }
420#endif 429#endif
421 sleeping = true; 430 sleeping = true;
@@ -479,7 +488,7 @@ int ata_hard_reset(void)
479 488
480 PADR |= 0x0200; 489 PADR |= 0x0200;
481 490
482 ret = wait_for_rdy(); 491 ret = wait_for_rdy();
483 492
484 /* Massage the return code so it is 0 on success and -1 on failure */ 493 /* Massage the return code so it is 0 on success and -1 on failure */
485 ret = ret?0:-1; 494 ret = ret?0:-1;
@@ -624,6 +633,31 @@ void ata_enable(bool on)
624 PAIOR |= 0x80; 633 PAIOR |= 0x80;
625} 634}
626 635
636static int identify(void)
637{
638 int i;
639
640 if(!wait_for_rdy()) {
641 DEBUGF("identify() - not RDY\n");
642 return -1;
643 }
644
645 ATA_SELECT = ata_device;
646 ATA_COMMAND = CMD_IDENTIFY;
647
648 if (!wait_for_start_of_transfer())
649 {
650 DEBUGF("identify() - CMD failed\n");
651 return -2;
652 }
653
654 for (i=0; i<SECTOR_SIZE/2; i++)
655 /* the IDENTIFY words are already swapped */
656 identify_info[i] = ATA_DATA;
657
658 return 0;
659}
660
627int ata_init(void) 661int ata_init(void)
628{ 662{
629 mutex_init(&ata_mtx); 663 mutex_init(&ata_mtx);
@@ -644,6 +678,11 @@ int ata_init(void)
644 678
645 if (freeze_lock()) 679 if (freeze_lock())
646 return -4; 680 return -4;
681
682 if (identify())
683 return -5;
684 multisectors = identify_info[47] & 0xff;
685 DEBUGF("ata: %d sectors per ata request\n",multisectors);
647 686
648 queue_init(&ata_queue); 687 queue_init(&ata_queue);
649 create_thread(ata_thread, ata_stack, 688 create_thread(ata_thread, ata_stack,