diff options
author | Björn Stenberg <bjorn@haxx.se> | 2002-09-05 15:25:08 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2002-09-05 15:25:08 +0000 |
commit | 8ccbc766a451f875289559a0cf530bbbb1223ec1 (patch) | |
tree | 130f85cf6e1848c9da3cd0b42c2e6f19b00319bd /firmware/drivers | |
parent | e4d35f617096d0cb0beb89457a44048097380fd8 (diff) | |
download | rockbox-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
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/ata.c | 85 |
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; | |||
96 | static long last_user_activity = -1; | 100 | static long last_user_activity = -1; |
97 | static long last_disk_activity = -1; | 101 | static long last_disk_activity = -1; |
98 | 102 | ||
103 | static int multisectors; /* number of supported multisectors */ | ||
104 | static unsigned short identify_info[SECTOR_SIZE]; | ||
105 | |||
99 | #ifdef USE_POWEROFF | 106 | #ifdef USE_POWEROFF |
100 | static int ata_power_on(void); | 107 | static 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 | ||
122 | static int wait_for_rdy(void) __attribute__ ((section (".icode"))); | 125 | static 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 | ||
146 | static int wait_for_start_of_transfer(void) __attribute__ ((section (".icode"))); | 145 | static 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 | ||
636 | static 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 | |||
627 | int ata_init(void) | 661 | int 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, |