summaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 7def9a093b..f9cf2d1436 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -224,13 +224,19 @@ static int ahci_rw(struct ata_port *ata, void *rbuf, const void *wbuf,
struct ahci_port *ahci = container_of(ata, struct ahci_port, ata);
u8 fis[20];
int ret;
+ int lba48 = ata_id_has_lba48(ata->id);
memset(fis, 0, sizeof(fis));
/* Construct the FIS */
fis[0] = 0x27; /* Host to device FIS. */
fis[1] = 1 << 7; /* Command FIS. */
- fis[2] = wbuf ? ATA_CMD_WRITE_EXT : ATA_CMD_READ_EXT; /* Command byte. */
+
+ /* Command byte. */
+ if (lba48)
+ fis[2] = wbuf ? ATA_CMD_WRITE_EXT : ATA_CMD_READ_EXT;
+ else
+ fis[2] = wbuf ? ATA_CMD_WRITE : ATA_CMD_READ;
while (num_blocks) {
int now;
@@ -240,9 +246,14 @@ static int ahci_rw(struct ata_port *ata, void *rbuf, const void *wbuf,
fis[4] = (block >> 0) & 0xff;
fis[5] = (block >> 8) & 0xff;
fis[6] = (block >> 16) & 0xff;
- fis[7] = 1 << 6; /* device reg: set LBA mode */
- fis[8] = ((block >> 24) & 0xff);
- fis[3] = 0xe0; /* features */
+
+ if (lba48) {
+ fis[7] = 1 << 6; /* device reg: set LBA mode */
+ fis[8] = ((block >> 24) & 0xff);
+ fis[3] = 0xe0; /* features */
+ } else {
+ fis[7] = ((block >> 24) & 0xf) | 0xe0;
+ }
/* Block (sector) count */
fis[12] = (now >> 0) & 0xff;
@@ -558,6 +569,20 @@ void ahci_info(struct device_d *dev)
ahci_print_info(ahci);
}
+static int ahci_detect(struct device_d *dev)
+{
+ struct ahci_device *ahci = dev->priv;
+ int i;
+
+ for (i = 0; i < ahci->n_ports; i++) {
+ struct ahci_port *ahci_port = &ahci->ports[i];
+
+ ata_port_detect(&ahci_port->ata);
+ }
+
+ return 0;
+}
+
int ahci_add_host(struct ahci_device *ahci)
{
u8 *mmio = (u8 *)ahci->mmio_base;
@@ -619,6 +644,8 @@ int ahci_add_host(struct ahci_device *ahci)
ahci_iowrite(ahci, HOST_CTL, tmp | HOST_IRQ_EN);
tmp = ahci_ioread(ahci, HOST_CTL);
+ ahci->dev->detect = ahci_detect;
+
return 0;
}