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.c81
1 files changed, 65 insertions, 16 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 8c591253f9..f5b8810d28 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -47,7 +47,9 @@
47 47
48#define CMD_READ_SECTORS 0x20 48#define CMD_READ_SECTORS 0x20
49#define CMD_WRITE_SECTORS 0x30 49#define CMD_WRITE_SECTORS 0x30
50#define CMD_WRITE_SECTORS_EXT 0x34
50#define CMD_READ_MULTIPLE 0xC4 51#define CMD_READ_MULTIPLE 0xC4
52#define CMD_READ_MULTIPLE_EXT 0x29
51#define CMD_WRITE_MULTIPLE 0xC5 53#define CMD_WRITE_MULTIPLE 0xC5
52#define CMD_SET_MULTIPLE_MODE 0xC6 54#define CMD_SET_MULTIPLE_MODE 0xC6
53#define CMD_STANDBY_IMMEDIATE 0xE0 55#define CMD_STANDBY_IMMEDIATE 0xE0
@@ -76,6 +78,9 @@ static long sleep_timeout = 5*HZ;
76#ifdef HAVE_ATA_POWER_OFF 78#ifdef HAVE_ATA_POWER_OFF
77static int poweroff_timeout = 2*HZ; 79static int poweroff_timeout = 2*HZ;
78#endif 80#endif
81#ifdef HAVE_BIGLBA
82static bool biglba = false; /* set for 48 bit addressing */
83#endif
79static long ata_stack[DEFAULT_STACK_SIZE/sizeof(long)]; 84static long ata_stack[DEFAULT_STACK_SIZE/sizeof(long)];
80static const char ata_thread_name[] = "ata"; 85static const char ata_thread_name[] = "ata";
81static struct event_queue ata_queue; 86static struct event_queue ata_queue;
@@ -252,16 +257,34 @@ int ata_read_sectors(IF_MV2(int drive,)
252 ret = 0; 257 ret = 0;
253 last_disk_activity = current_tick; 258 last_disk_activity = current_tick;
254 259
255 if ( count == 256 ) 260#ifdef HAVE_BIGLBA
256 SET_REG(ATA_NSECTOR, 0); /* 0 means 256 sectors */ 261 if (biglba)
262 {
263 SET_REG(ATA_NSECTOR, count >> 8);
264 SET_REG(ATA_NSECTOR, count & 0xff);
265 SET_REG(ATA_SECTOR, (start >> 24) & 0xff); /* 31:24 */
266 SET_REG(ATA_SECTOR, start & 0xff); /* 7:0 */
267 SET_REG(ATA_LCYL, 0); /* 39:32 */
268 SET_REG(ATA_LCYL, (start >> 8) & 0xff); /* 15:8 */
269 SET_REG(ATA_HCYL, 0); /* 47:40 */
270 SET_REG(ATA_HCYL, (start >> 16) & 0xff); /* 23:16 */
271 SET_REG(ATA_SELECT, SELECT_LBA | ata_device);
272 SET_REG(ATA_COMMAND, CMD_READ_MULTIPLE_EXT);
273 }
257 else 274 else
258 SET_REG(ATA_NSECTOR, (unsigned char)count); 275#endif
276 {
277 if ( count == 256 )
278 SET_REG(ATA_NSECTOR, 0); /* 0 means 256 sectors */
279 else
280 SET_REG(ATA_NSECTOR, (unsigned char)count);
259 281
260 SET_REG(ATA_SECTOR, start & 0xff); 282 SET_REG(ATA_SECTOR, start & 0xff);
261 SET_REG(ATA_LCYL, (start >> 8) & 0xff); 283 SET_REG(ATA_LCYL, (start >> 8) & 0xff);
262 SET_REG(ATA_HCYL, (start >> 16) & 0xff); 284 SET_REG(ATA_HCYL, (start >> 16) & 0xff);
263 SET_REG(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device); 285 SET_REG(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device);
264 SET_REG(ATA_COMMAND, CMD_READ_MULTIPLE); 286 SET_REG(ATA_COMMAND, CMD_READ_MULTIPLE);
287 }
265 288
266 /* wait at least 400ns between writing command and reading status */ 289 /* wait at least 400ns between writing command and reading status */
267 __asm__ volatile ("nop"); 290 __asm__ volatile ("nop");
@@ -429,15 +452,33 @@ int ata_write_sectors(IF_MV2(int drive,)
429 return -2; 452 return -2;
430 } 453 }
431 454
432 if ( count == 256 ) 455#ifdef HAVE_BIGLBA
433 SET_REG(ATA_NSECTOR, 0); /* 0 means 256 sectors */ 456 if (biglba)
457 {
458 SET_REG(ATA_NSECTOR, count >> 8);
459 SET_REG(ATA_NSECTOR, count & 0xff);
460 SET_REG(ATA_SECTOR, (start >> 24) & 0xff); /* 31:24 */
461 SET_REG(ATA_SECTOR, start & 0xff); /* 7:0 */
462 SET_REG(ATA_LCYL, 0); /* 39:32 */
463 SET_REG(ATA_LCYL, (start >> 8) & 0xff); /* 15:8 */
464 SET_REG(ATA_HCYL, 0); /* 47:40 */
465 SET_REG(ATA_HCYL, (start >> 16) & 0xff); /* 23:16 */
466 SET_REG(ATA_SELECT, SELECT_LBA | ata_device);
467 SET_REG(ATA_COMMAND, CMD_WRITE_SECTORS_EXT);
468 }
434 else 469 else
435 SET_REG(ATA_NSECTOR, (unsigned char)count); 470#endif
436 SET_REG(ATA_SECTOR, start & 0xff); 471 {
437 SET_REG(ATA_LCYL, (start >> 8) & 0xff); 472 if ( count == 256 )
438 SET_REG(ATA_HCYL, (start >> 16) & 0xff); 473 SET_REG(ATA_NSECTOR, 0); /* 0 means 256 sectors */
439 SET_REG(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device); 474 else
440 SET_REG(ATA_COMMAND, CMD_WRITE_SECTORS); 475 SET_REG(ATA_NSECTOR, (unsigned char)count);
476 SET_REG(ATA_SECTOR, start & 0xff);
477 SET_REG(ATA_LCYL, (start >> 8) & 0xff);
478 SET_REG(ATA_HCYL, (start >> 16) & 0xff);
479 SET_REG(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device);
480 SET_REG(ATA_COMMAND, CMD_WRITE_SECTORS);
481 }
441 482
442 for (i=0; i<count; i++) { 483 for (i=0; i<count; i++) {
443 484
@@ -944,6 +985,14 @@ int ata_init(void)
944 multisectors = identify_info[47] & 0xff; 985 multisectors = identify_info[47] & 0xff;
945 DEBUGF("ata: %d sectors per ata request\n",multisectors); 986 DEBUGF("ata: %d sectors per ata request\n",multisectors);
946 987
988#ifdef HAVE_BIGLBA
989 if (identify_info[83] & 0x0400 /* 48 bit address support */
990 && identify_info[60] == 0xFFFF /* and disk size >= 128 GiB */
991 && identify_info[61] == 0x0FFF) /* (needs BigLBA addressing) */
992 {
993 biglba = true; /* use BigLBA */
994 }
995#endif
947 rc = freeze_lock(); 996 rc = freeze_lock();
948 997
949 if (rc) 998 if (rc)