diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 35 |
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; } |