summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2009-03-12 02:01:25 +0000
committerMichael Sevakis <jethead71@rockbox.org>2009-03-12 02:01:25 +0000
commitbc8cab4c24a0891182ac9711c67165a9e3373b1c (patch)
treef164876bee0344f051d50c36195404d28b50907f
parent01c390d5c5fce784883054a650b6c8ebaba8b186 (diff)
downloadrockbox-bc8cab4c24a0891182ac9711c67165a9e3373b1c.tar.gz
rockbox-bc8cab4c24a0891182ac9711c67165a9e3373b1c.zip
Commit the common portion of FS#9708: ATA (IDE) DMA by Boris Gjenero with a couple cosmetic tweaks and without the inclusion of 'FS#9721: No error check after writes in ata.c'changes (which can be done separately). No code is changed for targets without HAVE_ATA_DMA defined other than to not display DMA modes in the View Disk Info debug screen if not using DMA (Gigabeat F/X/S were). No target uses the code yet but Gigabeat S use will follow shortly.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20298 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/debug_menu.c27
-rw-r--r--firmware/drivers/ata.c245
-rw-r--r--firmware/export/ata.h14
3 files changed, 228 insertions, 58 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 561be7c947..2912129a1a 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -2029,7 +2029,7 @@ static int disk_callback(int btn, struct gui_synclist *lists)
2029 simplelist_addline(SIMPLELIST_ADD_LINE, 2029 simplelist_addline(SIMPLELIST_ADD_LINE,
2030 "No timing info"); 2030 "No timing info");
2031 } 2031 }
2032#if defined (TOSHIBA_GIGABEAT_F) || defined (TOSHIBA_GIGABEAT_S) 2032#ifdef HAVE_ATA_DMA
2033 if (identify_info[63] & (1<<0)) { 2033 if (identify_info[63] & (1<<0)) {
2034 char mdma0[2], mdma1[2], mdma2[2]; 2034 char mdma0[2], mdma1[2], mdma2[2];
2035 mdma0[1] = mdma1[1] = mdma2[1] = 0; 2035 mdma0[1] = mdma1[1] = mdma2[1] = 0;
@@ -2047,24 +2047,25 @@ static int disk_callback(int btn, struct gui_synclist *lists)
2047 simplelist_addline(SIMPLELIST_ADD_LINE, 2047 simplelist_addline(SIMPLELIST_ADD_LINE,
2048 "No MDMA mode info"); 2048 "No MDMA mode info");
2049 } 2049 }
2050 if (identify_info[88] & (1<<0)) { 2050 if (identify_info[53] & (1<<2)) {
2051 char udma0[2], udma1[2], udma2[2], udma3[2], udma4[2], udma5[2]; 2051 char udma0[2], udma1[2], udma2[2], udma3[2], udma4[2], udma5[2], udma6[2];
2052 udma0[1] = udma1[1] = udma2[1] = udma3[1] = udma4[1] = udma5[1] = 0; 2052 udma0[1] = udma1[1] = udma2[1] = udma3[1] = udma4[1] = udma5[1] = udma6[1] = 0;
2053 udma0[0] = (identify_info[88] & (1<<0)) ? '0' : 0; 2053 udma0[0] = (identify_info[88] & (1<<0)) ? '0' : 0;
2054 udma1[0] = (identify_info[88] & (1<<1)) ? '1' : 0; 2054 udma1[0] = (identify_info[88] & (1<<1)) ? '1' : 0;
2055 udma2[0] = (identify_info[88] & (1<<2)) ? '2' : 0; 2055 udma2[0] = (identify_info[88] & (1<<2)) ? '2' : 0;
2056 udma3[0] = (identify_info[88] & (1<<3)) ? '3' : 0; 2056 udma3[0] = (identify_info[88] & (1<<3)) ? '3' : 0;
2057 udma4[0] = (identify_info[88] & (1<<4)) ? '4' : 0; 2057 udma4[0] = (identify_info[88] & (1<<4)) ? '4' : 0;
2058 udma5[0] = (identify_info[88] & (1<<5)) ? '5' : 0; 2058 udma5[0] = (identify_info[88] & (1<<5)) ? '5' : 0;
2059 udma6[0] = (identify_info[88] & (1<<6)) ? '6' : 0;
2059 simplelist_addline(SIMPLELIST_ADD_LINE, 2060 simplelist_addline(SIMPLELIST_ADD_LINE,
2060 "UDMA modes: %s %s %s %s %s %s", udma0, udma1, udma2, 2061 "UDMA modes: %s %s %s %s %s %s %s", udma0, udma1, udma2,
2061 udma3, udma4, udma5); 2062 udma3, udma4, udma5, udma6);
2062 } 2063 }
2063 else { 2064 else {
2064 simplelist_addline(SIMPLELIST_ADD_LINE, 2065 simplelist_addline(SIMPLELIST_ADD_LINE,
2065 "No UDMA mode info"); 2066 "No UDMA mode info");
2066 } 2067 }
2067#endif /* defined (TOSHIBA_GIGABEAT_F) || defined (TOSHIBA_GIGABEAT_S) */ 2068#endif /* HAVE_ATA_DMA */
2068 timing_info_present = identify_info[53] & (1<<1); 2069 timing_info_present = identify_info[53] & (1<<1);
2069 if(timing_info_present) { 2070 if(timing_info_present) {
2070 i = identify_info[49] & (1<<11); 2071 i = identify_info[49] & (1<<11);
@@ -2079,6 +2080,18 @@ static int disk_callback(int btn, struct gui_synclist *lists)
2079 } 2080 }
2080 simplelist_addline(SIMPLELIST_ADD_LINE, 2081 simplelist_addline(SIMPLELIST_ADD_LINE,
2081 "Cluster size: %d bytes", fat_get_cluster_size(IF_MV(0))); 2082 "Cluster size: %d bytes", fat_get_cluster_size(IF_MV(0)));
2083#ifdef HAVE_ATA_DMA
2084 i = ata_get_dma_mode();
2085 if (i == 0) {
2086 simplelist_addline(SIMPLELIST_ADD_LINE,
2087 "DMA not enabled");
2088 } else {
2089 simplelist_addline(SIMPLELIST_ADD_LINE,
2090 "DMA mode: %s %c",
2091 (i & 0x40) ? "UDMA" : "MDMA",
2092 '0' + (i & 7));
2093 }
2094#endif /* HAVE_ATA_DMA */
2082 return btn; 2095 return btn;
2083} 2096}
2084#else /* No SD, MMC or ATA */ 2097#else /* No SD, MMC or ATA */
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 23f65b35c5..88633f0ec9 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -60,6 +60,12 @@
60#define CMD_SLEEP 0xE6 60#define CMD_SLEEP 0xE6
61#define CMD_SET_FEATURES 0xEF 61#define CMD_SET_FEATURES 0xEF
62#define CMD_SECURITY_FREEZE_LOCK 0xF5 62#define CMD_SECURITY_FREEZE_LOCK 0xF5
63#ifdef HAVE_ATA_DMA
64#define CMD_READ_DMA 0xC8
65#define CMD_READ_DMA_EXT 0x25
66#define CMD_WRITE_DMA 0xCA
67#define CMD_WRITE_DMA_EXT 0x35
68#endif
63 69
64/* Should all be < 0x100 (which are reserved for control messages) */ 70/* Should all be < 0x100 (which are reserved for control messages) */
65#define Q_SLEEP 0 71#define Q_SLEEP 0
@@ -188,6 +194,10 @@ static struct sector_cache_entry sector_cache;
188static int phys_sector_mult = 1; 194static int phys_sector_mult = 1;
189#endif 195#endif
190 196
197#ifdef HAVE_ATA_DMA
198static int dma_mode = 0;
199#endif
200
191static int ata_power_on(void); 201static int ata_power_on(void);
192static int perform_soft_reset(void); 202static int perform_soft_reset(void);
193static int set_multiple_mode(int sectors); 203static int set_multiple_mode(int sectors);
@@ -308,6 +318,9 @@ int ata_read_sectors(IF_MV2(int drive,)
308 int count; 318 int count;
309 void* buf; 319 void* buf;
310 long spinup_start; 320 long spinup_start;
321#ifdef HAVE_ATA_DMA
322 bool usedma = false;
323#endif
311 324
312#ifndef MAX_PHYS_SECTOR_SIZE 325#ifndef MAX_PHYS_SECTOR_SIZE
313#ifdef HAVE_MULTIVOLUME 326#ifdef HAVE_MULTIVOLUME
@@ -358,6 +371,12 @@ int ata_read_sectors(IF_MV2(int drive,)
358 ret = 0; 371 ret = 0;
359 last_disk_activity = current_tick; 372 last_disk_activity = current_tick;
360 373
374#ifdef HAVE_ATA_DMA
375 /* If DMA is supported and parameters are ok for DMA, use it */
376 if (dma_mode && ata_dma_setup(inbuf, incount * SECTOR_SIZE, false))
377 usedma = true;
378#endif
379
361#ifdef HAVE_LBA48 380#ifdef HAVE_LBA48
362 if (lba48) 381 if (lba48)
363 { 382 {
@@ -370,7 +389,11 @@ int ata_read_sectors(IF_MV2(int drive,)
370 SET_REG(ATA_HCYL, 0); /* 47:40 */ 389 SET_REG(ATA_HCYL, 0); /* 47:40 */
371 SET_REG(ATA_HCYL, (start >> 16) & 0xff); /* 23:16 */ 390 SET_REG(ATA_HCYL, (start >> 16) & 0xff); /* 23:16 */
372 SET_REG(ATA_SELECT, SELECT_LBA | ata_device); 391 SET_REG(ATA_SELECT, SELECT_LBA | ata_device);
392#ifdef HAVE_ATA_DMA
393 SET_REG(ATA_COMMAND, usedma ? CMD_READ_DMA_EXT : CMD_READ_MULTIPLE_EXT);
394#else
373 SET_REG(ATA_COMMAND, CMD_READ_MULTIPLE_EXT); 395 SET_REG(ATA_COMMAND, CMD_READ_MULTIPLE_EXT);
396#endif
374 } 397 }
375 else 398 else
376#endif 399#endif
@@ -380,7 +403,11 @@ int ata_read_sectors(IF_MV2(int drive,)
380 SET_REG(ATA_LCYL, (start >> 8) & 0xff); 403 SET_REG(ATA_LCYL, (start >> 8) & 0xff);
381 SET_REG(ATA_HCYL, (start >> 16) & 0xff); 404 SET_REG(ATA_HCYL, (start >> 16) & 0xff);
382 SET_REG(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device); 405 SET_REG(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device);
406#ifdef HAVE_ATA_DMA
407 SET_REG(ATA_COMMAND, usedma ? CMD_READ_DMA : CMD_READ_MULTIPLE);
408#else
383 SET_REG(ATA_COMMAND, CMD_READ_MULTIPLE); 409 SET_REG(ATA_COMMAND, CMD_READ_MULTIPLE);
410#endif
384 } 411 }
385 412
386 /* wait at least 400ns between writing command and reading status */ 413 /* wait at least 400ns between writing command and reading status */
@@ -390,22 +417,13 @@ int ata_read_sectors(IF_MV2(int drive,)
390 __asm__ volatile ("nop"); 417 __asm__ volatile ("nop");
391 __asm__ volatile ("nop"); 418 __asm__ volatile ("nop");
392 419
393 while (count) { 420#ifdef HAVE_ATA_DMA
394 int sectors; 421 if (usedma) {
395 int wordcount; 422 if (!ata_dma_finish())
396 int status; 423 ret = -7;
397 424
398 if (!wait_for_start_of_transfer()) { 425 if (ret != 0) {
399 /* We have timed out waiting for RDY and/or DRQ, possibly
400 because the hard drive is shaking and has problems reading
401 the data. We have two options:
402 1) Wait some more
403 2) Perform a soft reset and try again.
404
405 We choose alternative 2.
406 */
407 perform_soft_reset(); 426 perform_soft_reset();
408 ret = -5;
409 goto retry; 427 goto retry;
410 } 428 }
411 429
@@ -415,36 +433,67 @@ int ata_read_sectors(IF_MV2(int drive,)
415 sleeping = false; 433 sleeping = false;
416 poweroff = false; 434 poweroff = false;
417 } 435 }
436 }
437 else
438#endif /* HAVE_ATA_DMA */
439 {
440 while (count) {
441 int sectors;
442 int wordcount;
443 int status;
444
445 if (!wait_for_start_of_transfer()) {
446 /* We have timed out waiting for RDY and/or DRQ, possibly
447 because the hard drive is shaking and has problems
448 reading the data. We have two options:
449 1) Wait some more
450 2) Perform a soft reset and try again.
451
452 We choose alternative 2.
453 */
454 perform_soft_reset();
455 ret = -5;
456 goto retry;
457 }
418 458
419 /* read the status register exactly once per loop */ 459 if (spinup) {
420 status = ATA_STATUS; 460 spinup_time = current_tick - spinup_start;
461 spinup = false;
462 sleeping = false;
463 poweroff = false;
464 }
421 465
422 if (count >= multisectors ) 466 /* read the status register exactly once per loop */
423 sectors = multisectors; 467 status = ATA_STATUS;
424 else
425 sectors = count;
426 468
427 wordcount = sectors * SECTOR_SIZE / 2; 469 if (count >= multisectors )
470 sectors = multisectors;
471 else
472 sectors = count;
428 473
429 copy_read_sectors(buf, wordcount); 474 wordcount = sectors * SECTOR_SIZE / 2;
430 475
431 /* 476 copy_read_sectors(buf, wordcount);
432 "Device errors encountered during READ MULTIPLE commands are
433 posted at the beginning of the block or partial block transfer,
434 but the DRQ bit is still set to one and the data transfer shall
435 take place, including transfer of corrupted data, if any."
436 -- ATA specification
437 */
438 if ( status & (STATUS_BSY | STATUS_ERR | STATUS_DF) ) {
439 perform_soft_reset();
440 ret = -6;
441 goto retry;
442 }
443 477
444 buf += sectors * SECTOR_SIZE; /* Advance one chunk of sectors */ 478 /*
445 count -= sectors; 479 "Device errors encountered during READ MULTIPLE commands
480 are posted at the beginning of the block or partial block
481 transfer, but the DRQ bit is still set to one and the data
482 transfer shall take place, including transfer of corrupted
483 data, if any."
484 -- ATA specification
485 */
486 if ( status & (STATUS_BSY | STATUS_ERR | STATUS_DF) ) {
487 perform_soft_reset();
488 ret = -6;
489 goto retry;
490 }
446 491
447 last_disk_activity = current_tick; 492 buf += sectors * SECTOR_SIZE; /* Advance one chunk of sectors */
493 count -= sectors;
494
495 last_disk_activity = current_tick;
496 }
448 } 497 }
449 498
450 if(!ret && !wait_for_end_of_transfer()) { 499 if(!ret && !wait_for_end_of_transfer()) {
@@ -515,6 +564,9 @@ int ata_write_sectors(IF_MV2(int drive,)
515 int i; 564 int i;
516 int ret = 0; 565 int ret = 0;
517 long spinup_start; 566 long spinup_start;
567#ifdef HAVE_ATA_DMA
568 bool usedma = false;
569#endif
518 570
519#ifndef MAX_PHYS_SECTOR_SIZE 571#ifndef MAX_PHYS_SECTOR_SIZE
520#ifdef HAVE_MULTIVOLUME 572#ifdef HAVE_MULTIVOLUME
@@ -554,6 +606,12 @@ int ata_write_sectors(IF_MV2(int drive,)
554 goto error; 606 goto error;
555 } 607 }
556 608
609#ifdef HAVE_ATA_DMA
610 /* If DMA is supported and parameters are ok for DMA, use it */
611 if (dma_mode && ata_dma_setup((void *)buf, count * SECTOR_SIZE, true))
612 usedma = true;
613#endif
614
557#ifdef HAVE_LBA48 615#ifdef HAVE_LBA48
558 if (lba48) 616 if (lba48)
559 { 617 {
@@ -566,7 +624,11 @@ int ata_write_sectors(IF_MV2(int drive,)
566 SET_REG(ATA_HCYL, 0); /* 47:40 */ 624 SET_REG(ATA_HCYL, 0); /* 47:40 */
567 SET_REG(ATA_HCYL, (start >> 16) & 0xff); /* 23:16 */ 625 SET_REG(ATA_HCYL, (start >> 16) & 0xff); /* 23:16 */
568 SET_REG(ATA_SELECT, SELECT_LBA | ata_device); 626 SET_REG(ATA_SELECT, SELECT_LBA | ata_device);
627#ifdef HAVE_ATA_DMA
628 SET_REG(ATA_COMMAND, usedma ? CMD_WRITE_DMA_EXT : CMD_WRITE_SECTORS_EXT);
629#else
569 SET_REG(ATA_COMMAND, CMD_WRITE_SECTORS_EXT); 630 SET_REG(ATA_COMMAND, CMD_WRITE_SECTORS_EXT);
631#endif
570 } 632 }
571 else 633 else
572#endif 634#endif
@@ -576,32 +638,51 @@ int ata_write_sectors(IF_MV2(int drive,)
576 SET_REG(ATA_LCYL, (start >> 8) & 0xff); 638 SET_REG(ATA_LCYL, (start >> 8) & 0xff);
577 SET_REG(ATA_HCYL, (start >> 16) & 0xff); 639 SET_REG(ATA_HCYL, (start >> 16) & 0xff);
578 SET_REG(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device); 640 SET_REG(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device);
641#ifdef HAVE_ATA_DMA
642 SET_REG(ATA_COMMAND, usedma ? CMD_WRITE_DMA : CMD_WRITE_SECTORS);
643#else
579 SET_REG(ATA_COMMAND, CMD_WRITE_SECTORS); 644 SET_REG(ATA_COMMAND, CMD_WRITE_SECTORS);
645#endif
580 } 646 }
581 647
582 for (i=0; i<count; i++) { 648#ifdef HAVE_ATA_DMA
583 649 if (usedma) {
584 if (!wait_for_start_of_transfer()) { 650 if (!ata_dma_finish())
585 ret = -3; 651 ret = -7;
586 break; 652 else if (spinup) {
587 }
588
589 if (spinup) {
590 spinup_time = current_tick - spinup_start; 653 spinup_time = current_tick - spinup_start;
591 spinup = false; 654 spinup = false;
592 sleeping = false; 655 sleeping = false;
593 poweroff = false; 656 poweroff = false;
594 } 657 }
658 }
659 else
660#endif /* HAVE_ATA_DMA */
661 {
662 for (i=0; i<count; i++) {
663
664 if (!wait_for_start_of_transfer()) {
665 ret = -3;
666 break;
667 }
668
669 if (spinup) {
670 spinup_time = current_tick - spinup_start;
671 spinup = false;
672 sleeping = false;
673 poweroff = false;
674 }
595 675
596 copy_write_sectors(buf, SECTOR_SIZE/2); 676 copy_write_sectors(buf, SECTOR_SIZE/2);
597 677
598#ifdef USE_INTERRUPT 678#ifdef USE_INTERRUPT
599 /* reading the status register clears the interrupt */ 679 /* reading the status register clears the interrupt */
600 j = ATA_STATUS; 680 j = ATA_STATUS;
601#endif 681#endif
602 buf += SECTOR_SIZE; 682 buf += SECTOR_SIZE;
603 683
604 last_disk_activity = current_tick; 684 last_disk_activity = current_tick;
685 }
605 } 686 }
606 687
607 if(!ret && !wait_for_end_of_transfer()) { 688 if(!ret && !wait_for_end_of_transfer()) {
@@ -1039,7 +1120,12 @@ static int perform_soft_reset(void)
1039 SET_REG(ATA_CONTROL, CONTROL_nIEN|CONTROL_SRST ); 1120 SET_REG(ATA_CONTROL, CONTROL_nIEN|CONTROL_SRST );
1040 sleep(1); /* >= 5us */ 1121 sleep(1); /* >= 5us */
1041 1122
1123#ifdef HAVE_ATA_DMA
1124 /* DMA requires INTRQ be enabled */
1125 SET_REG(ATA_CONTROL, 0);
1126#else
1042 SET_REG(ATA_CONTROL, CONTROL_nIEN); 1127 SET_REG(ATA_CONTROL, CONTROL_nIEN);
1128#endif
1043 sleep(1); /* >2ms */ 1129 sleep(1); /* >2ms */
1044 1130
1045 /* This little sucker can take up to 30 seconds */ 1131 /* This little sucker can take up to 30 seconds */
@@ -1179,6 +1265,22 @@ static int set_multiple_mode(int sectors)
1179 return 0; 1265 return 0;
1180} 1266}
1181 1267
1268#ifdef HAVE_ATA_DMA
1269static int get_best_mode(unsigned short identword, int max, int modetype)
1270{
1271 unsigned short testbit = 1u << max;
1272
1273 while (1) {
1274 if (identword & testbit)
1275 return max | modetype;
1276 testbit >>= 1;
1277 if (!testbit)
1278 return 0;
1279 max--;
1280 }
1281}
1282#endif
1283
1182static int set_features(void) 1284static int set_features(void)
1183{ 1285{
1184 static struct { 1286 static struct {
@@ -1191,6 +1293,9 @@ static int set_features(void)
1191 { 83, 3, 0x05, 0x80 }, /* adv. power management: lowest w/o standby */ 1293 { 83, 3, 0x05, 0x80 }, /* adv. power management: lowest w/o standby */
1192 { 83, 9, 0x42, 0x80 }, /* acoustic management: lowest noise */ 1294 { 83, 9, 0x42, 0x80 }, /* acoustic management: lowest noise */
1193 { 82, 6, 0xaa, 0 }, /* enable read look-ahead */ 1295 { 82, 6, 0xaa, 0 }, /* enable read look-ahead */
1296#ifdef HAVE_ATA_DMA
1297 { 0, 0, 0x03, 0 }, /* DMA mode */
1298#endif
1194 }; 1299 };
1195 int i; 1300 int i;
1196 int pio_mode = 2; 1301 int pio_mode = 2;
@@ -1204,6 +1309,23 @@ static int set_features(void)
1204 1309
1205 /* Update the table: set highest supported pio mode that we also support */ 1310 /* Update the table: set highest supported pio mode that we also support */
1206 features[0].parameter = 8 + pio_mode; 1311 features[0].parameter = 8 + pio_mode;
1312
1313#ifdef HAVE_ATA_DMA
1314 if (identify_info[53] & (1<<2))
1315 /* Ultra DMA mode info present, find a mode */
1316 dma_mode = get_best_mode(identify_info[88], ATA_MAX_UDMA, 0x40);
1317
1318 if (!dma_mode) {
1319 /* No UDMA mode found, try to find a multi-word DMA mode */
1320 dma_mode = get_best_mode(identify_info[63], ATA_MAX_MWDMA, 0x20);
1321 features[4].id_word = 63;
1322 }
1323 else
1324 features[4].id_word = 88;
1325
1326 features[4].id_bit = dma_mode & 7;
1327 features[4].parameter = dma_mode;
1328#endif /* HAVE_ATA_DMA */
1207 1329
1208 SET_REG(ATA_SELECT, ata_device); 1330 SET_REG(ATA_SELECT, ata_device);
1209 1331
@@ -1237,6 +1359,10 @@ static int set_features(void)
1237 ata_set_pio_timings(pio_mode); 1359 ata_set_pio_timings(pio_mode);
1238#endif 1360#endif
1239 1361
1362#ifdef HAVE_ATA_DMA
1363 ata_dma_set_mode(dma_mode);
1364#endif
1365
1240 return 0; 1366 return 0;
1241} 1367}
1242 1368
@@ -1305,6 +1431,11 @@ int ata_init(void)
1305 sleep(HZ/4); /* allow voltage to build up */ 1431 sleep(HZ/4); /* allow voltage to build up */
1306 } 1432 }
1307 1433
1434#ifdef HAVE_ATA_DMA
1435 /* DMA requires INTRQ be enabled */
1436 SET_REG(ATA_CONTROL, 0);
1437#endif
1438
1308 /* first try, hard reset at cold start only */ 1439 /* first try, hard reset at cold start only */
1309 rc = init_and_check(coldstart); 1440 rc = init_and_check(coldstart);
1310 1441
@@ -1450,3 +1581,17 @@ void ata_get_info(struct storage_info *info)
1450 info->revision=revision; 1581 info->revision=revision;
1451} 1582}
1452#endif 1583#endif
1584
1585#ifdef HAVE_ATA_DMA
1586/* Returns last DMA mode as set by set_features() */
1587int ata_get_dma_mode(void)
1588{
1589 return dma_mode;
1590}
1591
1592/* Needed to allow updating while waiting for DMA to complete */
1593void ata_keep_active(void)
1594{
1595 last_disk_activity = current_tick;
1596}
1597#endif
diff --git a/firmware/export/ata.h b/firmware/export/ata.h
index f491e525e6..b5e39de3aa 100644
--- a/firmware/export/ata.h
+++ b/firmware/export/ata.h
@@ -60,5 +60,17 @@ bool ata_present(IF_MV_NONVOID(int drive));
60long ata_last_disk_activity(void); 60long ata_last_disk_activity(void);
61int ata_spinup_time(void); /* ticks */ 61int ata_spinup_time(void); /* ticks */
62 62
63#ifdef HAVE_ATA_DMA
64/* Needed to allow updating while waiting for DMA to complete */
65void ata_keep_active(void);
66/* Returns current DMA mode */
67int ata_get_dma_mode(void);
68/* Set DMA mode for ATA interface */
69void ata_dma_set_mode(unsigned char mode);
70/* Sets up DMA transfer */
71bool ata_dma_setup(void *addr, unsigned long bytes, bool write);
72/* Waits for DMA transfer completion */
73bool ata_dma_finish(void);
74#endif /* HAVE_ATA_DMA */
63 75
64#endif 76#endif /* __ATA_H__ */