diff options
author | mav <mav@FreeBSD.org> | 2009-02-20 23:17:52 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2009-02-20 23:17:52 +0000 |
commit | 1348b6bf738e7990a24a05eab5a61e17345549eb (patch) | |
tree | cb80049d47d553241be761a98116510b58b2954e /sys/dev/ata | |
parent | 6b0a7363d7b12ba8ed8a5555063e5d62b0b8365c (diff) | |
download | FreeBSD-src-1348b6bf738e7990a24a05eab5a61e17345549eb.zip FreeBSD-src-1348b6bf738e7990a24a05eab5a61e17345549eb.tar.gz |
Disable port hardware on detach. First switch it to slumber mode to
power-down peer transmitter, then disable completely.
Side effect of this is saving about 0.5W of power per detached device.
Diffstat (limited to 'sys/dev/ata')
-rw-r--r-- | sys/dev/ata/chipsets/ata-ahci.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/sys/dev/ata/chipsets/ata-ahci.c b/sys/dev/ata/chipsets/ata-ahci.c index a950793..9dd2488 100644 --- a/sys/dev/ata/chipsets/ata-ahci.c +++ b/sys/dev/ata/chipsets/ata-ahci.c @@ -230,6 +230,22 @@ ata_ahci_ch_attach(device_t dev) int ata_ahci_ch_detach(device_t dev) { + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + int offset = ch->unit << 7; + + /* Disable port interrupts. */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0); + /* Reset command register. */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 0); + + /* Allow everything including partial and slumber modes. */ + ATA_IDX_OUTL(ch, ATA_SCONTROL, 0); + /* Request slumber mode transition and give some time to get there. */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, ATA_AHCI_P_CMD_SLUMBER); + DELAY(100); + /* Disable PHY. */ + ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_DISABLE); ata_dmafini(dev); return (0); |