summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/ata.c63
-rw-r--r--firmware/drivers/ata_mmc.c2
2 files changed, 37 insertions, 28 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 549a7bf920..db8bdf92a0 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -89,6 +89,7 @@ static bool initialized = false;
89static long last_user_activity = -1; 89static long last_user_activity = -1;
90long last_disk_activity = -1; 90long last_disk_activity = -1;
91 91
92static unsigned long total_sectors;
92static int multisectors; /* number of supported multisectors */ 93static int multisectors; /* number of supported multisectors */
93static unsigned short identify_info[SECTOR_SIZE/2]; 94static unsigned short identify_info[SECTOR_SIZE/2];
94 95
@@ -284,6 +285,11 @@ int ata_read_sectors(IF_MV2(int drive,)
284 mutex_lock(&ata_mtx); 285 mutex_lock(&ata_mtx);
285#endif 286#endif
286 287
288 if (start + incount > total_sectors) {
289 ret = -1;
290 goto error;
291 }
292
287 last_disk_activity = current_tick; 293 last_disk_activity = current_tick;
288 spinup_start = current_tick; 294 spinup_start = current_tick;
289 295
@@ -293,16 +299,14 @@ int ata_read_sectors(IF_MV2(int drive,)
293 spinup = true; 299 spinup = true;
294 if (poweroff) { 300 if (poweroff) {
295 if (ata_power_on()) { 301 if (ata_power_on()) {
296 mutex_unlock(&ata_mtx); 302 ret = -2;
297 ata_led(false); 303 goto error;
298 return -1;
299 } 304 }
300 } 305 }
301 else { 306 else {
302 if (perform_soft_reset()) { 307 if (perform_soft_reset()) {
303 mutex_unlock(&ata_mtx); 308 ret = -2;
304 ata_led(false); 309 goto error;
305 return -1;
306 } 310 }
307 } 311 }
308 } 312 }
@@ -312,9 +316,8 @@ int ata_read_sectors(IF_MV2(int drive,)
312 SET_REG(ATA_SELECT, ata_device); 316 SET_REG(ATA_SELECT, ata_device);
313 if (!wait_for_rdy()) 317 if (!wait_for_rdy())
314 { 318 {
315 mutex_unlock(&ata_mtx); 319 ret = -3;
316 ata_led(false); 320 goto error;
317 return -2;
318 } 321 }
319 322
320 retry: 323 retry:
@@ -371,7 +374,7 @@ int ata_read_sectors(IF_MV2(int drive,)
371 We choose alternative 2. 374 We choose alternative 2.
372 */ 375 */
373 perform_soft_reset(); 376 perform_soft_reset();
374 ret = -4; 377 ret = -5;
375 goto retry; 378 goto retry;
376 } 379 }
377 380
@@ -403,7 +406,7 @@ int ata_read_sectors(IF_MV2(int drive,)
403 */ 406 */
404 if ( status & (STATUS_BSY | STATUS_ERR | STATUS_DF) ) { 407 if ( status & (STATUS_BSY | STATUS_ERR | STATUS_DF) ) {
405 perform_soft_reset(); 408 perform_soft_reset();
406 ret = -5; 409 ret = -6;
407 goto retry; 410 goto retry;
408 } 411 }
409 412
@@ -415,13 +418,14 @@ int ata_read_sectors(IF_MV2(int drive,)
415 418
416 if(!ret && !wait_for_end_of_transfer()) { 419 if(!ret && !wait_for_end_of_transfer()) {
417 perform_soft_reset(); 420 perform_soft_reset();
418 ret = -3; 421 ret = -4;
419 goto retry; 422 goto retry;
420 } 423 }
421 break; 424 break;
422 } 425 }
423 ata_led(false);
424 426
427 error:
428 ata_led(false);
425#ifndef MAX_PHYS_SECTOR_SIZE 429#ifndef MAX_PHYS_SECTOR_SIZE
426 mutex_unlock(&ata_mtx); 430 mutex_unlock(&ata_mtx);
427#endif 431#endif
@@ -489,6 +493,9 @@ int ata_write_sectors(IF_MV2(int drive,)
489 mutex_lock(&ata_mtx); 493 mutex_lock(&ata_mtx);
490#endif 494#endif
491 495
496 if (start + count > total_sectors)
497 panicf("Writing past end of disk");
498
492 last_disk_activity = current_tick; 499 last_disk_activity = current_tick;
493 spinup_start = current_tick; 500 spinup_start = current_tick;
494 501
@@ -498,16 +505,14 @@ int ata_write_sectors(IF_MV2(int drive,)
498 spinup = true; 505 spinup = true;
499 if (poweroff) { 506 if (poweroff) {
500 if (ata_power_on()) { 507 if (ata_power_on()) {
501 mutex_unlock(&ata_mtx); 508 ret = -1;
502 ata_led(false); 509 goto error;
503 return -1;
504 } 510 }
505 } 511 }
506 else { 512 else {
507 if (perform_soft_reset()) { 513 if (perform_soft_reset()) {
508 mutex_unlock(&ata_mtx); 514 ret = -1;
509 ata_led(false); 515 goto error;
510 return -1;
511 } 516 }
512 } 517 }
513 } 518 }
@@ -515,9 +520,8 @@ int ata_write_sectors(IF_MV2(int drive,)
515 SET_REG(ATA_SELECT, ata_device); 520 SET_REG(ATA_SELECT, ata_device);
516 if (!wait_for_rdy()) 521 if (!wait_for_rdy())
517 { 522 {
518 mutex_unlock(&ata_mtx); 523 ret = -2;
519 ata_led(false); 524 goto error;
520 return -2;
521 } 525 }
522 526
523#ifdef HAVE_LBA48 527#ifdef HAVE_LBA48
@@ -575,8 +579,8 @@ int ata_write_sectors(IF_MV2(int drive,)
575 ret = -4; 579 ret = -4;
576 } 580 }
577 581
582 error:
578 ata_led(false); 583 ata_led(false);
579
580#ifndef MAX_PHYS_SECTOR_SIZE 584#ifndef MAX_PHYS_SECTOR_SIZE
581 mutex_unlock(&ata_mtx); 585 mutex_unlock(&ata_mtx);
582#endif 586#endif
@@ -1240,11 +1244,16 @@ int ata_init(void)
1240 phys_sector_mult * SECTOR_SIZE); 1244 phys_sector_mult * SECTOR_SIZE);
1241#endif 1245#endif
1242 1246
1247 total_sectors = identify_info[60] | (identify_info[60] << 16);
1248
1243#ifdef HAVE_LBA48 1249#ifdef HAVE_LBA48
1244 if (identify_info[83] & 0x0400 /* 48 bit address support */ 1250 if (identify_info[83] & 0x0400 /* 48 bit address support */
1245 && identify_info[60] == 0xFFFF /* and disk size >= 128 GiB */ 1251 && total_sectors == 0x0FFFFFFF) /* and disk size >= 128 GiB */
1246 && identify_info[61] == 0x0FFF) /* (needs BigLBA addressing) */ 1252 { /* (needs BigLBA addressing) */
1247 { 1253 if (identify_info[102] || identify_info[103])
1254 panicf("Unsupported disk size, >= 2^32 sectors");
1255
1256 total_sectors = identify_info[100] | (identify_info[101] << 16);
1248 lba48 = true; /* use BigLBA */ 1257 lba48 = true; /* use BigLBA */
1249 } 1258 }
1250#endif 1259#endif
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c
index fdd091248f..e0a2b17500 100644
--- a/firmware/drivers/ata_mmc.c
+++ b/firmware/drivers/ata_mmc.c
@@ -814,7 +814,7 @@ int ata_write_sectors(IF_MV2(int drive,)
814 } 814 }
815 815
816 if (c_end_addr > card->size) 816 if (c_end_addr > card->size)
817 panicf("Writing past end of card\n"); 817 panicf("Writing past end of card");
818 818
819 blocksize = card->blocksize; 819 blocksize = card->blocksize;
820 offset = c_addr & (blocksize - 1); 820 offset = c_addr & (blocksize - 1);