1183724Ssos/*- 2230132Suqs * Copyright (c) 1998 - 2008 S��ren Schmidt <sos@FreeBSD.org> 3183724Ssos * All rights reserved. 4183724Ssos * 5183724Ssos * Redistribution and use in source and binary forms, with or without 6183724Ssos * modification, are permitted provided that the following conditions 7183724Ssos * are met: 8183724Ssos * 1. Redistributions of source code must retain the above copyright 9183724Ssos * notice, this list of conditions and the following disclaimer, 10183724Ssos * without modification, immediately at the beginning of the file. 11183724Ssos * 2. Redistributions in binary form must reproduce the above copyright 12183724Ssos * notice, this list of conditions and the following disclaimer in the 13183724Ssos * documentation and/or other materials provided with the distribution. 14183724Ssos * 15183724Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16183724Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17183724Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18183724Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19183724Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20183724Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21183724Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22183724Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23183724Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24183724Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25183724Ssos */ 26183724Ssos 27183724Ssos#include <sys/cdefs.h> 28183724Ssos__FBSDID("$FreeBSD$"); 29183724Ssos 30183724Ssos#include <sys/param.h> 31183724Ssos#include <sys/module.h> 32183724Ssos#include <sys/systm.h> 33183724Ssos#include <sys/kernel.h> 34183724Ssos#include <sys/ata.h> 35183724Ssos#include <sys/bus.h> 36183724Ssos#include <sys/endian.h> 37183724Ssos#include <sys/malloc.h> 38183724Ssos#include <sys/lock.h> 39183724Ssos#include <sys/mutex.h> 40183724Ssos#include <sys/sema.h> 41183724Ssos#include <sys/taskqueue.h> 42183724Ssos#include <vm/uma.h> 43183724Ssos#include <machine/stdarg.h> 44183724Ssos#include <machine/resource.h> 45183724Ssos#include <machine/bus.h> 46183724Ssos#include <sys/rman.h> 47183724Ssos#include <dev/pci/pcivar.h> 48183724Ssos#include <dev/pci/pcireg.h> 49183724Ssos#include <dev/ata/ata-all.h> 50183724Ssos#include <dev/ata/ata-pci.h> 51183724Ssos#include <ata_if.h> 52183724Ssos 53183724Ssos/* local prototypes */ 54199322Smavstatic int ata_ahci_ch_attach(device_t dev); 55199322Smavstatic int ata_ahci_ch_detach(device_t dev); 56199322Smavstatic int ata_ahci_ch_suspend(device_t dev); 57199322Smavstatic int ata_ahci_ch_resume(device_t dev); 58199322Smavstatic int ata_ahci_ctlr_reset(device_t dev); 59199322Smavstatic void ata_ahci_reset(device_t dev); 60183724Ssosstatic int ata_ahci_suspend(device_t dev); 61183724Ssosstatic int ata_ahci_status(device_t dev); 62183724Ssosstatic int ata_ahci_begin_transaction(struct ata_request *request); 63183724Ssosstatic int ata_ahci_end_transaction(struct ata_request *request); 64183724Ssosstatic int ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result); 65183724Ssosstatic int ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t result); 66190581Smavstatic int ata_ahci_hardreset(device_t dev, int port, uint32_t *signature); 67183724Ssosstatic u_int32_t ata_ahci_softreset(device_t dev, int port); 68183724Ssosstatic void ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); 69183724Ssosstatic int ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *equest); 70188769Smavstatic void ata_ahci_dmainit(device_t dev); 71190581Smavstatic void ata_ahci_start(device_t dev); 72190581Smavstatic void ata_ahci_stop(device_t dev); 73190581Smavstatic void ata_ahci_clo(device_t dev); 74190581Smavstatic void ata_ahci_start_fr(device_t dev); 75190581Smavstatic void ata_ahci_stop_fr(device_t dev); 76183724Ssos 77183724Ssos/* 78183724Ssos * AHCI v1.x compliant SATA chipset support functions 79183724Ssos */ 80183724Ssosstatic int 81183724Ssosata_ahci_probe(device_t dev) 82183724Ssos{ 83183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 84183724Ssos char buffer[64]; 85183724Ssos 86183724Ssos /* is this a possible AHCI candidate ? */ 87186296Smav if (pci_get_class(dev) != PCIC_STORAGE || 88186296Smav pci_get_subclass(dev) != PCIS_STORAGE_SATA) 89186296Smav return (ENXIO); 90183724Ssos 91183724Ssos /* is this PCI device flagged as an AHCI compliant chip ? */ 92191601Sjkim if (pci_get_progif(dev) != PCIP_STORAGE_SATA_AHCI_1_0) 93191600Sjkim return (ENXIO); 94183724Ssos 95183724Ssos if (bootverbose) 96183724Ssos sprintf(buffer, "%s (ID=%08x) AHCI controller", 97183724Ssos ata_pcivendor2str(dev), pci_get_devid(dev)); 98183724Ssos else 99183724Ssos sprintf(buffer, "%s AHCI controller", ata_pcivendor2str(dev)); 100183724Ssos device_set_desc_copy(dev, buffer); 101183724Ssos ctlr->chipinit = ata_ahci_chipinit; 102191600Sjkim return (BUS_PROBE_GENERIC); 103183724Ssos} 104183724Ssos 105199322Smavstatic int 106199322Smavata_ahci_ata_probe(device_t dev) 107199322Smav{ 108199322Smav struct ata_pci_controller *ctlr = device_get_softc(dev); 109199322Smav 110199322Smav if ((intptr_t)device_get_ivars(dev) >= 0) 111199322Smav return (ENXIO); 112199322Smav device_set_desc_copy(dev, "AHCI SATA controller"); 113199322Smav ctlr->chipinit = ata_ahci_chipinit; 114199322Smav return (BUS_PROBE_GENERIC); 115199322Smav} 116199322Smav 117199322Smavstatic int 118199322Smavata_ahci_ata_attach(device_t dev) 119199322Smav{ 120199322Smav struct ata_pci_controller *ctlr = device_get_softc(dev); 121199322Smav device_t child; 122199322Smav int unit; 123199322Smav 124199322Smav /* do chipset specific setups only needed once */ 125199322Smav ctlr->legacy = 0; 126199322Smav ctlr->ichannels = -1; 127199322Smav ctlr->ch_attach = ata_pci_ch_attach; 128199322Smav ctlr->ch_detach = ata_pci_ch_detach; 129199322Smav ctlr->dev = dev; 130199322Smav if (ctlr->chipinit(dev)) 131199322Smav return ENXIO; 132199322Smav /* attach all channels on this controller */ 133199322Smav for (unit = 0; unit < ctlr->channels; unit++) { 134199322Smav if ((ctlr->ichannels & (1 << unit)) == 0) 135199322Smav continue; 136199322Smav child = device_add_child(dev, "ata", 137199322Smav ((unit == 0 || unit == 1) && ctlr->legacy) ? 138199322Smav unit : devclass_find_free_unit(ata_devclass, 2)); 139199322Smav if (child == NULL) 140199322Smav device_printf(dev, "failed to add ata child device\n"); 141199322Smav else 142199322Smav device_set_ivars(child, (void *)(intptr_t)unit); 143199322Smav } 144199322Smav bus_generic_attach(dev); 145199322Smav return 0; 146199322Smav} 147199322Smav 148183724Ssosint 149183724Ssosata_ahci_chipinit(device_t dev) 150183724Ssos{ 151183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 152193277Smav int error, speed; 153193277Smav u_int32_t caps, version; 154183724Ssos 155183724Ssos /* if we have a memory BAR(5) we are likely on an AHCI part */ 156183724Ssos ctlr->r_type2 = SYS_RES_MEMORY; 157183724Ssos ctlr->r_rid2 = PCIR_BAR(5); 158183724Ssos if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, 159183724Ssos &ctlr->r_rid2, RF_ACTIVE))) 160183724Ssos return ENXIO; 161183724Ssos 162183724Ssos /* setup interrupt delivery if not done allready by a vendor driver */ 163183724Ssos if (!ctlr->r_irq) { 164186250Smav if (ata_setup_interrupt(dev, ata_generic_intr)) { 165186250Smav bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2); 166183724Ssos return ENXIO; 167186250Smav } 168183724Ssos } 169183724Ssos else 170183724Ssos device_printf(dev, "AHCI called from vendor specific driver\n"); 171183724Ssos 172183724Ssos /* reset controller */ 173186250Smav if ((error = ata_ahci_ctlr_reset(dev)) != 0) { 174186250Smav bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2); 175186250Smav return (error); 176186250Smav }; 177183724Ssos 178183724Ssos /* get the number of HW channels */ 179188694Smav ctlr->ichannels = ATA_INL(ctlr->r_res2, ATA_AHCI_PI); 180199322Smav ctlr->channels = MAX(flsl(ctlr->ichannels), 181191674Smav (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_NPMASK) + 1); 182232380Smav if (pci_get_devid(dev) == ATA_M88SE6111) 183199322Smav ctlr->channels = 1; 184232380Smav else if (pci_get_devid(dev) == ATA_M88SE6121) 185199322Smav ctlr->channels = 2; 186232380Smav else if (pci_get_devid(dev) == ATA_M88SE6141 || 187232380Smav pci_get_devid(dev) == ATA_M88SE6145) 188199322Smav ctlr->channels = 4; 189183724Ssos 190183724Ssos ctlr->reset = ata_ahci_reset; 191188765Smav ctlr->ch_attach = ata_ahci_ch_attach; 192188769Smav ctlr->ch_detach = ata_ahci_ch_detach; 193190581Smav ctlr->ch_suspend = ata_ahci_ch_suspend; 194190581Smav ctlr->ch_resume = ata_ahci_ch_resume; 195183724Ssos ctlr->setmode = ata_sata_setmode; 196200171Smav ctlr->getrev = ata_sata_getrev; 197183724Ssos ctlr->suspend = ata_ahci_suspend; 198183724Ssos ctlr->resume = ata_ahci_ctlr_reset; 199183724Ssos 200193277Smav /* announce we support the HW */ 201193277Smav version = ATA_INL(ctlr->r_res2, ATA_AHCI_VS); 202193277Smav caps = ATA_INL(ctlr->r_res2, ATA_AHCI_CAP); 203193277Smav speed = (caps & ATA_AHCI_CAP_ISS) >> ATA_AHCI_CAP_ISS_SHIFT; 204193277Smav device_printf(dev, 205193277Smav "AHCI v%x.%02x controller with %d %sGbps ports, PM %s\n", 206193277Smav ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f), 207193277Smav ((version >> 4) & 0xf0) + (version & 0x0f), 208193277Smav (caps & ATA_AHCI_CAP_NPMASK) + 1, 209193277Smav ((speed == 1) ? "1.5":((speed == 2) ? "3": 210193277Smav ((speed == 3) ? "6":"?"))), 211193277Smav (caps & ATA_AHCI_CAP_SPM) ? 212193277Smav "supported" : "not supported"); 213193277Smav if (bootverbose) { 214193277Smav device_printf(dev, "Caps:%s%s%s%s%s%s%s%s %sGbps", 215193277Smav (caps & ATA_AHCI_CAP_64BIT) ? " 64bit":"", 216193277Smav (caps & ATA_AHCI_CAP_SNCQ) ? " NCQ":"", 217193277Smav (caps & ATA_AHCI_CAP_SSNTF) ? " SNTF":"", 218193277Smav (caps & ATA_AHCI_CAP_SMPS) ? " MPS":"", 219193277Smav (caps & ATA_AHCI_CAP_SSS) ? " SS":"", 220193277Smav (caps & ATA_AHCI_CAP_SALP) ? " ALP":"", 221193277Smav (caps & ATA_AHCI_CAP_SAL) ? " AL":"", 222193277Smav (caps & ATA_AHCI_CAP_SCLO) ? " CLO":"", 223193277Smav ((speed == 1) ? "1.5":((speed == 2) ? "3": 224193277Smav ((speed == 3) ? "6":"?")))); 225193277Smav printf("%s%s%s%s%s%s %dcmd%s%s%s %dports\n", 226193277Smav (caps & ATA_AHCI_CAP_SAM) ? " AM":"", 227193277Smav (caps & ATA_AHCI_CAP_SPM) ? " PM":"", 228193277Smav (caps & ATA_AHCI_CAP_FBSS) ? " FBS":"", 229193277Smav (caps & ATA_AHCI_CAP_PMD) ? " PMD":"", 230193277Smav (caps & ATA_AHCI_CAP_SSC) ? " SSC":"", 231193277Smav (caps & ATA_AHCI_CAP_PSC) ? " PSC":"", 232193277Smav ((caps & ATA_AHCI_CAP_NCS) >> ATA_AHCI_CAP_NCS_SHIFT) + 1, 233193277Smav (caps & ATA_AHCI_CAP_CCCS) ? " CCC":"", 234193277Smav (caps & ATA_AHCI_CAP_EMS) ? " EM":"", 235193277Smav (caps & ATA_AHCI_CAP_SXS) ? " eSATA":"", 236193277Smav (caps & ATA_AHCI_CAP_NPMASK) + 1); 237193277Smav } 238193277Smav return 0; 239183724Ssos} 240183724Ssos 241199322Smavstatic int 242183724Ssosata_ahci_ctlr_reset(device_t dev) 243183724Ssos{ 244183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 245188621Smav int timeout; 246183724Ssos 247183724Ssos /* enable AHCI mode */ 248183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE); 249183724Ssos 250183724Ssos /* reset AHCI controller */ 251188621Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE|ATA_AHCI_GHC_HR); 252188621Smav for (timeout = 1000; timeout > 0; timeout--) { 253188621Smav DELAY(1000); 254188621Smav if ((ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & ATA_AHCI_GHC_HR) == 0) 255188621Smav break; 256188621Smav } 257188621Smav if (timeout == 0) { 258183724Ssos device_printf(dev, "AHCI controller reset failure\n"); 259183724Ssos return ENXIO; 260183724Ssos } 261183724Ssos 262183724Ssos /* reenable AHCI mode */ 263183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE); 264183724Ssos 265183724Ssos /* clear interrupts */ 266183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, ATA_INL(ctlr->r_res2, ATA_AHCI_IS)); 267183724Ssos 268183724Ssos /* enable AHCI interrupts */ 269183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, 270183724Ssos ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_IE); 271183724Ssos 272183724Ssos return 0; 273183724Ssos} 274183724Ssos 275183724Ssosstatic int 276183724Ssosata_ahci_suspend(device_t dev) 277183724Ssos{ 278183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 279183724Ssos 280183724Ssos /* disable interupts so the state change(s) doesn't trigger */ 281183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, 282183724Ssos ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & (~ATA_AHCI_GHC_IE)); 283183724Ssos return 0; 284183724Ssos} 285183724Ssos 286199322Smavstatic int 287188765Smavata_ahci_ch_attach(device_t dev) 288183724Ssos{ 289183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 290183724Ssos struct ata_channel *ch = device_get_softc(dev); 291183724Ssos int offset = ch->unit << 7; 292183724Ssos 293188765Smav ata_ahci_dmainit(dev); 294188765Smav 295183724Ssos /* set the SATA resources */ 296183724Ssos ch->r_io[ATA_SSTATUS].res = ctlr->r_res2; 297183724Ssos ch->r_io[ATA_SSTATUS].offset = ATA_AHCI_P_SSTS + offset; 298183724Ssos ch->r_io[ATA_SERROR].res = ctlr->r_res2; 299183724Ssos ch->r_io[ATA_SERROR].offset = ATA_AHCI_P_SERR + offset; 300183724Ssos ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; 301183724Ssos ch->r_io[ATA_SCONTROL].offset = ATA_AHCI_P_SCTL + offset; 302183724Ssos ch->r_io[ATA_SACTIVE].res = ctlr->r_res2; 303183724Ssos ch->r_io[ATA_SACTIVE].offset = ATA_AHCI_P_SACT + offset; 304183724Ssos 305183724Ssos ch->hw.status = ata_ahci_status; 306183724Ssos ch->hw.begin_transaction = ata_ahci_begin_transaction; 307183724Ssos ch->hw.end_transaction = ata_ahci_end_transaction; 308183724Ssos ch->hw.command = NULL; /* not used here */ 309183724Ssos ch->hw.softreset = ata_ahci_softreset; 310183724Ssos ch->hw.pm_read = ata_ahci_pm_read; 311183724Ssos ch->hw.pm_write = ata_ahci_pm_write; 312200171Smav ch->flags |= ATA_NO_SLAVE; 313200171Smav ch->flags |= ATA_SATA; 314183724Ssos 315190581Smav ata_ahci_ch_resume(dev); 316183724Ssos return 0; 317183724Ssos} 318183724Ssos 319199322Smavstatic int 320188769Smavata_ahci_ch_detach(device_t dev) 321188769Smav{ 322219337Smarius struct ata_channel *ch = device_get_softc(dev); 323219337Smarius 324219337Smarius if (ch->dma.work_tag && ch->dma.work_map) 325219337Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 326219337Smarius BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 327190581Smav ata_ahci_ch_suspend(dev); 328190581Smav ata_dmafini(dev); 329190581Smav return (0); 330190581Smav} 331190581Smav 332199322Smavstatic int 333190581Smavata_ahci_ch_suspend(device_t dev) 334190581Smav{ 335188877Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 336188877Smav struct ata_channel *ch = device_get_softc(dev); 337188877Smav int offset = ch->unit << 7; 338188769Smav 339188877Smav /* Disable port interrupts. */ 340188877Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0); 341188877Smav /* Reset command register. */ 342190581Smav ata_ahci_stop(dev); 343190581Smav ata_ahci_stop_fr(dev); 344188877Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 0); 345188877Smav 346188877Smav /* Allow everything including partial and slumber modes. */ 347188877Smav ATA_IDX_OUTL(ch, ATA_SCONTROL, 0); 348188877Smav /* Request slumber mode transition and give some time to get there. */ 349188877Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, ATA_AHCI_P_CMD_SLUMBER); 350188877Smav DELAY(100); 351188877Smav /* Disable PHY. */ 352188877Smav ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_DISABLE); 353188877Smav 354188769Smav return (0); 355188769Smav} 356188769Smav 357199322Smavstatic int 358190581Smavata_ahci_ch_resume(device_t dev) 359190581Smav{ 360190581Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 361190581Smav struct ata_channel *ch = device_get_softc(dev); 362190581Smav uint64_t work; 363190581Smav int offset = ch->unit << 7; 364190581Smav 365190581Smav /* Disable port interrupts */ 366190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0); 367190581Smav 368190581Smav /* setup work areas */ 369190581Smav work = ch->dma.work_bus + ATA_AHCI_CL_OFFSET; 370190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff); 371190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32); 372190581Smav 373190581Smav work = ch->dma.work_bus + ATA_AHCI_FB_OFFSET; 374190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff); 375190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32); 376190581Smav 377190581Smav /* activate the channel and power/spin up device */ 378190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 379191674Smav (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | 380191674Smav ((ch->pm_level > 1) ? ATA_AHCI_P_CMD_ALPE : 0) | 381191674Smav ((ch->pm_level > 2) ? ATA_AHCI_P_CMD_ASP : 0 ))); 382190581Smav ata_ahci_start_fr(dev); 383190581Smav ata_ahci_start(dev); 384190581Smav 385190581Smav return (0); 386190581Smav} 387190581Smav 388183724Ssosstatic int 389183724Ssosata_ahci_status(device_t dev) 390183724Ssos{ 391183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 392183724Ssos struct ata_channel *ch = device_get_softc(dev); 393183724Ssos u_int32_t action = ATA_INL(ctlr->r_res2, ATA_AHCI_IS); 394183724Ssos int offset = ch->unit << 7; 395183724Ssos 396183724Ssos#define ATA_AHCI_STATBITS \ 397183724Ssos (ATA_AHCI_P_IX_IF|ATA_AHCI_P_IX_HBD|ATA_AHCI_P_IX_HBF|ATA_AHCI_P_IX_TFE) 398183724Ssos 399183724Ssos if (action & (1 << ch->unit)) { 400183724Ssos u_int32_t istatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset); 401183724Ssos u_int32_t cstatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset); 402183724Ssos 403183724Ssos /* clear interrupt(s) */ 404183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, istatus); 405188658Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, 1 << ch->unit); 406183724Ssos 407183724Ssos /* do we have any PHY events ? */ 408183724Ssos if (istatus & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) 409214016Smav ata_sata_phy_check_events(dev, -1); 410183724Ssos 411183724Ssos /* do we have a potentially hanging engine to take care of? */ 412183724Ssos /* XXX SOS what todo on NCQ */ 413183724Ssos if ((istatus & ATA_AHCI_STATBITS) && (cstatus & 1)) { 414183724Ssos 415183724Ssos u_int32_t cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 416183724Ssos int timeout = 0; 417183724Ssos 418183724Ssos /* kill off all activity on this channel */ 419183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 420183724Ssos cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); 421183724Ssos 422183724Ssos /* XXX SOS this is not entirely wrong */ 423183724Ssos do { 424183724Ssos DELAY(1000); 425183724Ssos if (timeout++ > 1000) { 426183724Ssos device_printf(dev, "stopping AHCI engine failed\n"); 427183724Ssos break; 428183724Ssos } 429183724Ssos } while (ATA_INL(ctlr->r_res2, 430183724Ssos ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_CR); 431183724Ssos 432183724Ssos /* start operations on this channel */ 433183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 434183724Ssos cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); 435183724Ssos 436183724Ssos return 1; 437183724Ssos } 438183724Ssos else 439183724Ssos /* XXX SOS what todo on NCQ */ 440183724Ssos return (!(cstatus & 1)); 441183724Ssos } 442183724Ssos return 0; 443183724Ssos} 444183724Ssos 445183724Ssos/* must be called with ATA channel locked and state_mtx held */ 446183724Ssosstatic int 447183724Ssosata_ahci_begin_transaction(struct ata_request *request) 448183724Ssos{ 449198717Smav struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); 450183724Ssos struct ata_channel *ch = device_get_softc(request->parent); 451183724Ssos struct ata_ahci_cmd_tab *ctp; 452183724Ssos struct ata_ahci_cmd_list *clp; 453183724Ssos int offset = ch->unit << 7; 454198717Smav int port = request->unit & 0x0f; 455183724Ssos int entries = 0; 456183724Ssos int fis_size; 457183724Ssos 458183724Ssos /* get a piece of the workspace for this request */ 459183724Ssos ctp = (struct ata_ahci_cmd_tab *) 460198717Smav (ch->dma.work + ATA_AHCI_CT_OFFSET); 461183724Ssos 462183724Ssos /* setup the FIS for this request */ 463183724Ssos if (!(fis_size = ata_ahci_setup_fis(ctp, request))) { 464198717Smav device_printf(request->parent, "setting up SATA FIS failed\n"); 465183724Ssos request->result = EIO; 466183724Ssos return ATA_OP_FINISHED; 467183724Ssos } 468183724Ssos 469183724Ssos /* if request moves data setup and load SG list */ 470183724Ssos if (request->flags & (ATA_R_READ | ATA_R_WRITE)) { 471183724Ssos if (ch->dma.load(request, ctp->prd_tab, &entries)) { 472198717Smav device_printf(request->parent, "setting up DMA failed\n"); 473183724Ssos request->result = EIO; 474183724Ssos return ATA_OP_FINISHED; 475183724Ssos } 476183724Ssos } 477183724Ssos 478183724Ssos /* setup the command list entry */ 479183724Ssos clp = (struct ata_ahci_cmd_list *) 480198717Smav (ch->dma.work + ATA_AHCI_CL_OFFSET); 481183724Ssos 482183724Ssos clp->prd_length = entries; 483183724Ssos clp->cmd_flags = (request->flags & ATA_R_WRITE ? ATA_AHCI_CMD_WRITE : 0) | 484183724Ssos (request->flags & ATA_R_ATAPI ? 485183724Ssos (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) | 486183724Ssos (fis_size / sizeof(u_int32_t)) | 487183724Ssos (port << 12); 488183724Ssos clp->bytecount = 0; 489198717Smav clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET); 490183724Ssos 491183724Ssos /* set command type bit */ 492183724Ssos if (request->flags & ATA_R_ATAPI) 493183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 494183724Ssos ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) | 495183724Ssos ATA_AHCI_P_CMD_ATAPI); 496183724Ssos else 497183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 498183724Ssos ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & 499183724Ssos ~ATA_AHCI_P_CMD_ATAPI); 500183724Ssos 501219337Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 502219337Smarius BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 503219337Smarius 504183724Ssos /* issue command to controller */ 505198717Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, 1); 506183724Ssos 507183724Ssos if (!(request->flags & ATA_R_ATAPI)) { 508183724Ssos /* device reset doesn't interrupt */ 509183724Ssos if (request->u.ata.command == ATA_DEVICE_RESET) { 510183724Ssos u_int32_t tf_data; 511183724Ssos int timeout = 1000000; 512183724Ssos 513183724Ssos do { 514183724Ssos DELAY(10); 515183724Ssos tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + (ch->unit<<7)); 516183724Ssos } while ((tf_data & ATA_S_BUSY) && timeout--); 517183724Ssos if (bootverbose) 518183724Ssos device_printf(ch->dev, "device_reset timeout=%dus\n", 519183724Ssos (1000000-timeout)*10); 520183724Ssos request->status = tf_data; 521183724Ssos if (request->status & ATA_S_ERROR) 522183724Ssos request->error = tf_data >> 8; 523183724Ssos return ATA_OP_FINISHED; 524183724Ssos } 525183724Ssos } 526183724Ssos 527183724Ssos /* start the timeout */ 528183724Ssos callout_reset(&request->callout, request->timeout * hz, 529183724Ssos (timeout_t*)ata_timeout, request); 530183724Ssos return ATA_OP_CONTINUES; 531183724Ssos} 532183724Ssos 533183724Ssos/* must be called with ATA channel locked and state_mtx held */ 534183724Ssosstatic int 535183724Ssosata_ahci_end_transaction(struct ata_request *request) 536183724Ssos{ 537198717Smav struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); 538183724Ssos struct ata_channel *ch = device_get_softc(request->parent); 539183724Ssos struct ata_ahci_cmd_list *clp; 540183724Ssos u_int32_t tf_data; 541183724Ssos int offset = ch->unit << 7; 542183724Ssos 543183724Ssos /* kill the timeout */ 544183724Ssos callout_stop(&request->callout); 545183724Ssos 546219337Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 547219337Smarius BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 548219337Smarius 549183724Ssos /* get status */ 550183724Ssos tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset); 551183724Ssos request->status = tf_data; 552183724Ssos 553183724Ssos /* if error status get details */ 554183724Ssos if (request->status & ATA_S_ERROR) 555183724Ssos request->error = tf_data >> 8; 556183724Ssos 557242156Smav /* Read back registers to the request struct. */ 558242156Smav if ((request->flags & ATA_R_ATAPI) == 0 && 559242156Smav ((request->status & ATA_S_ERROR) || 560242156Smav (request->flags & (ATA_R_CONTROL | ATA_R_NEEDRESULT)))) { 561183724Ssos u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; 562183724Ssos 563183724Ssos request->u.ata.count = fis[12] | ((u_int16_t)fis[13] << 8); 564183724Ssos request->u.ata.lba = fis[4] | ((u_int64_t)fis[5] << 8) | 565183724Ssos ((u_int64_t)fis[6] << 16); 566198717Smav if (request->flags & ATA_R_48BIT) 567183724Ssos request->u.ata.lba |= ((u_int64_t)fis[8] << 24) | 568183724Ssos ((u_int64_t)fis[9] << 32) | 569183724Ssos ((u_int64_t)fis[10] << 40); 570183724Ssos else 571183724Ssos request->u.ata.lba |= ((u_int64_t)(fis[7] & 0x0f) << 24); 572183724Ssos } 573183724Ssos 574183724Ssos /* record how much data we actually moved */ 575183724Ssos clp = (struct ata_ahci_cmd_list *) 576198717Smav (ch->dma.work + ATA_AHCI_CL_OFFSET); 577213092Smav request->donecount = le32toh(clp->bytecount); 578183724Ssos 579183724Ssos /* release SG list etc */ 580183724Ssos ch->dma.unload(request); 581183724Ssos 582183724Ssos return ATA_OP_FINISHED; 583183724Ssos} 584183724Ssos 585183724Ssosstatic int 586183724Ssosata_ahci_issue_cmd(device_t dev, u_int16_t flags, int timeout) 587183724Ssos{ 588183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 589183724Ssos struct ata_channel *ch = device_get_softc(dev); 590183724Ssos struct ata_ahci_cmd_list *clp = 591183724Ssos (struct ata_ahci_cmd_list *)(ch->dma.work + ATA_AHCI_CL_OFFSET); 592183724Ssos struct ata_ahci_cmd_tab *ctp = 593183724Ssos (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); 594183724Ssos u_int32_t status = 0; 595183724Ssos int offset = ch->unit << 7; 596183724Ssos int port = (ctp->cfis[1] & 0x0f); 597183724Ssos int count; 598183724Ssos 599183724Ssos clp->prd_length = 0; 600183724Ssos clp->cmd_flags = (20 / sizeof(u_int32_t)) | flags | (port << 12); 601183724Ssos clp->bytecount = 0; 602183724Ssos clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET); 603183724Ssos 604219337Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 605219337Smarius BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 606219337Smarius 607183724Ssos /* issue command to controller */ 608183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, 1); 609183724Ssos 610183724Ssos /* poll for command finished */ 611183724Ssos for (count = 0; count < timeout; count++) { 612183724Ssos DELAY(1000); 613183724Ssos if (!((status = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset)) & 1)) 614183724Ssos break; 615183724Ssos } 616183724Ssos 617219337Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 618219337Smarius BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 619219337Smarius 620183724Ssos /* clear interrupts */ 621183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, 622190581Smav ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset)); 623183724Ssos 624188918Smav if (timeout && (count >= timeout)) { 625188918Smav if (bootverbose) { 626188918Smav device_printf(dev, "ahci_issue_cmd timeout: %d of %dms, status=%08x\n", 627188918Smav count, timeout, status); 628188918Smav } 629183724Ssos return EIO; 630188918Smav } 631183724Ssos 632183724Ssos return 0; 633183724Ssos} 634183724Ssos 635183724Ssosstatic int 636183724Ssosata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result) 637183724Ssos{ 638183724Ssos struct ata_channel *ch = device_get_softc(dev); 639183724Ssos struct ata_ahci_cmd_tab *ctp = 640183724Ssos (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); 641183724Ssos u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; 642183724Ssos 643214016Smav if (port < 0) { 644214016Smav *result = ATA_IDX_INL(ch, reg); 645214016Smav return (0); 646214016Smav } 647214016Smav if (port < ATA_PM) { 648214016Smav switch (reg) { 649214016Smav case ATA_SSTATUS: 650214016Smav reg = 0; 651214016Smav break; 652214016Smav case ATA_SERROR: 653214016Smav reg = 1; 654214016Smav break; 655214016Smav case ATA_SCONTROL: 656214016Smav reg = 2; 657214016Smav break; 658214016Smav default: 659214016Smav return (EINVAL); 660214016Smav } 661214016Smav } 662183724Ssos bzero(ctp->cfis, 64); 663183724Ssos ctp->cfis[0] = 0x27; /* host to device */ 664183724Ssos ctp->cfis[1] = 0x8f; /* command FIS to PM port */ 665183724Ssos ctp->cfis[2] = ATA_READ_PM; 666183724Ssos ctp->cfis[3] = reg; 667183724Ssos ctp->cfis[7] = port | ATA_D_LBA; 668183724Ssos ctp->cfis[15] = ATA_A_4BIT; 669183724Ssos 670183724Ssos if (ata_ahci_issue_cmd(dev, 0, 10)) { 671183724Ssos device_printf(dev, "error reading PM port\n"); 672183724Ssos return EIO; 673183724Ssos } 674183724Ssos 675183724Ssos *result = fis[12] | (fis[4] << 8) | (fis[5] << 16) | (fis[6] << 24); 676183724Ssos return 0; 677183724Ssos} 678183724Ssos 679183724Ssosstatic int 680183724Ssosata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t value) 681183724Ssos{ 682183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 683183724Ssos struct ata_channel *ch = device_get_softc(dev); 684183724Ssos struct ata_ahci_cmd_tab *ctp = 685183724Ssos (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); 686183724Ssos int offset = ch->unit << 7; 687183724Ssos 688214016Smav if (port < 0) { 689214016Smav ATA_IDX_OUTL(ch, reg, value); 690214016Smav return (0); 691214016Smav } 692214016Smav if (port < ATA_PM) { 693214016Smav switch (reg) { 694214016Smav case ATA_SSTATUS: 695214016Smav reg = 0; 696214016Smav break; 697214016Smav case ATA_SERROR: 698214016Smav reg = 1; 699214016Smav break; 700214016Smav case ATA_SCONTROL: 701214016Smav reg = 2; 702214016Smav break; 703214016Smav default: 704214016Smav return (EINVAL); 705214016Smav } 706214016Smav } 707183724Ssos bzero(ctp->cfis, 64); 708183724Ssos ctp->cfis[0] = 0x27; /* host to device */ 709183724Ssos ctp->cfis[1] = 0x8f; /* command FIS to PM port */ 710183724Ssos ctp->cfis[2] = ATA_WRITE_PM; 711183724Ssos ctp->cfis[3] = reg; 712183724Ssos ctp->cfis[7] = port | ATA_D_LBA; 713183724Ssos ctp->cfis[12] = value & 0xff; 714201758Smbr ctp->cfis[4] = (value >> 8) & 0xff; 715201758Smbr ctp->cfis[5] = (value >> 16) & 0xff; 716201758Smbr ctp->cfis[6] = (value >> 24) & 0xff; 717183724Ssos ctp->cfis[15] = ATA_A_4BIT; 718183724Ssos 719183724Ssos if (ata_ahci_issue_cmd(dev, 0, 100)) { 720183724Ssos device_printf(dev, "error writing PM port\n"); 721183724Ssos return ATA_E_ABORT; 722183724Ssos } 723183724Ssos 724183724Ssos return (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) >> 8) & 0xff; 725183724Ssos} 726183724Ssos 727183724Ssosstatic void 728188621Smavata_ahci_stop(device_t dev) 729183724Ssos{ 730183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 731183724Ssos struct ata_channel *ch = device_get_softc(dev); 732183724Ssos u_int32_t cmd; 733183724Ssos int offset = ch->unit << 7; 734183724Ssos int timeout; 735183724Ssos 736183724Ssos /* kill off all activity on this channel */ 737183724Ssos cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 738183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 739190581Smav cmd & ~ATA_AHCI_P_CMD_ST); 740183724Ssos 741183724Ssos /* XXX SOS this is not entirely wrong */ 742183724Ssos timeout = 0; 743183724Ssos do { 744183724Ssos DELAY(1000); 745183724Ssos if (timeout++ > 1000) { 746183724Ssos device_printf(dev, "stopping AHCI engine failed\n"); 747183724Ssos break; 748183724Ssos } 749183724Ssos } 750183724Ssos while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_CR); 751188621Smav} 752183724Ssos 753188621Smavstatic void 754188621Smavata_ahci_clo(device_t dev) 755188621Smav{ 756188621Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 757188621Smav struct ata_channel *ch = device_get_softc(dev); 758188621Smav u_int32_t cmd; 759188621Smav int offset = ch->unit << 7; 760188621Smav int timeout; 761188621Smav 762183724Ssos /* issue Command List Override if supported */ 763193277Smav if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SCLO) { 764183724Ssos cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 765183724Ssos cmd |= ATA_AHCI_P_CMD_CLO; 766183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd); 767183724Ssos timeout = 0; 768183724Ssos do { 769183724Ssos DELAY(1000); 770183724Ssos if (timeout++ > 1000) { 771183724Ssos device_printf(dev, "executing CLO failed\n"); 772183724Ssos break; 773183724Ssos } 774183724Ssos } 775183724Ssos while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD+offset)&ATA_AHCI_P_CMD_CLO); 776183724Ssos } 777188621Smav} 778183724Ssos 779188621Smavstatic void 780188621Smavata_ahci_start(device_t dev) 781188621Smav{ 782188621Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 783188621Smav struct ata_channel *ch = device_get_softc(dev); 784188621Smav u_int32_t cmd; 785188621Smav int offset = ch->unit << 7; 786188621Smav 787183724Ssos /* clear SATA error register */ 788183724Ssos ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); 789183724Ssos 790183724Ssos /* clear any interrupts pending on this channel */ 791183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, 792183724Ssos ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset)); 793183724Ssos 794183724Ssos /* start operations on this channel */ 795183724Ssos cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 796183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 797190581Smav cmd | ATA_AHCI_P_CMD_ST | 798183724Ssos (ch->devices & ATA_PORTMULTIPLIER ? ATA_AHCI_P_CMD_PMA : 0)); 799183724Ssos} 800183724Ssos 801190581Smavstatic void 802190581Smavata_ahci_stop_fr(device_t dev) 803190581Smav{ 804190581Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 805190581Smav struct ata_channel *ch = device_get_softc(dev); 806190581Smav u_int32_t cmd; 807190581Smav int offset = ch->unit << 7; 808190581Smav int timeout; 809190581Smav 810190581Smav /* kill off all activity on this channel */ 811190581Smav cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 812190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd & ~ATA_AHCI_P_CMD_FRE); 813190581Smav 814190581Smav timeout = 0; 815190581Smav do { 816190581Smav DELAY(1000); 817190581Smav if (timeout++ > 1000) { 818190581Smav device_printf(dev, "stopping AHCI FR engine failed\n"); 819190581Smav break; 820190581Smav } 821190581Smav } 822190581Smav while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_FR); 823190581Smav} 824190581Smav 825190581Smavstatic void 826190581Smavata_ahci_start_fr(device_t dev) 827190581Smav{ 828190581Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 829190581Smav struct ata_channel *ch = device_get_softc(dev); 830190581Smav u_int32_t cmd; 831190581Smav int offset = ch->unit << 7; 832190581Smav 833190581Smav /* start FIS reception on this channel */ 834190581Smav cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 835190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd | ATA_AHCI_P_CMD_FRE); 836190581Smav} 837190581Smav 838188648Smavstatic int 839188905Smavata_ahci_wait_ready(device_t dev, int t) 840188621Smav{ 841188621Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 842188621Smav struct ata_channel *ch = device_get_softc(dev); 843188621Smav int offset = ch->unit << 7; 844188621Smav int timeout = 0; 845190581Smav uint32_t val; 846188621Smav 847190581Smav while ((val = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset)) & 848188621Smav (ATA_S_BUSY | ATA_S_DRQ)) { 849188621Smav DELAY(1000); 850188905Smav if (timeout++ > t) { 851190581Smav device_printf(dev, "port is not ready (timeout %dms) tfd = %08x\n", t, val); 852190581Smav return (EBUSY); 853188621Smav } 854188621Smav } 855188621Smav if (bootverbose) 856188621Smav device_printf(dev, "ready wait time=%dms\n", timeout); 857188648Smav return (0); 858188621Smav} 859188621Smav 860190581Smavstatic int 861190581Smavata_ahci_hardreset(device_t dev, int port, uint32_t *signature) 862190581Smav{ 863190581Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 864190581Smav struct ata_channel *ch = device_get_softc(dev); 865190581Smav int offset = ch->unit << 7; 866190581Smav 867190581Smav *signature = 0xffffffff; 868190581Smav ata_ahci_stop(dev); 869190581Smav /* Reset port */ 870190581Smav if (!ata_sata_phy_reset(dev, port, 0)) 871190581Smav return (ENOENT); 872190581Smav /* Wait for clearing busy status. */ 873212081Smav if (ata_ahci_wait_ready(dev, 15000)) { 874190581Smav device_printf(dev, "hardware reset timeout\n"); 875190581Smav return (EBUSY); 876190581Smav } 877190581Smav *signature = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset); 878190581Smav ata_ahci_start(dev); 879190581Smav return (0); 880190581Smav} 881190581Smav 882183724Ssosstatic u_int32_t 883183724Ssosata_ahci_softreset(device_t dev, int port) 884183724Ssos{ 885183724Ssos struct ata_channel *ch = device_get_softc(dev); 886183724Ssos struct ata_ahci_cmd_tab *ctp = 887183724Ssos (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); 888200117Smav u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; 889183724Ssos 890188918Smav if (bootverbose) 891188918Smav device_printf(dev, "software reset port %d...\n", port); 892188918Smav 893188621Smav /* kick controller into sane state */ 894188621Smav ata_ahci_stop(dev); 895188621Smav ata_ahci_clo(dev); 896188621Smav ata_ahci_start(dev); 897183724Ssos 898183724Ssos /* pull reset active */ 899183724Ssos bzero(ctp->cfis, 64); 900183724Ssos ctp->cfis[0] = 0x27; 901183724Ssos ctp->cfis[1] = port & 0x0f; 902183724Ssos //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM; 903183724Ssos ctp->cfis[15] = (ATA_A_4BIT | ATA_A_RESET); 904183724Ssos 905188918Smav if (ata_ahci_issue_cmd(dev, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY,100)) { 906188918Smav device_printf(dev, "software reset set timeout\n"); 907188918Smav return (-1); 908188918Smav } 909183724Ssos 910188862Smav ata_udelay(50); 911183724Ssos 912183724Ssos /* pull reset inactive -> device softreset */ 913183724Ssos bzero(ctp->cfis, 64); 914183724Ssos ctp->cfis[0] = 0x27; 915183724Ssos ctp->cfis[1] = port & 0x0f; 916183724Ssos //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM; 917183724Ssos ctp->cfis[15] = ATA_A_4BIT; 918190581Smav ata_ahci_issue_cmd(dev, 0, 3000); 919183724Ssos 920190581Smav if (ata_ahci_wait_ready(dev, 0)) { 921188918Smav device_printf(dev, "software reset clear timeout\n"); 922188648Smav return (-1); 923188918Smav } 924183724Ssos 925200117Smav return (((u_int32_t)fis[6] << 24) | 926200117Smav ((u_int32_t)fis[5] << 16) | 927200117Smav ((u_int32_t)fis[4] << 8) | 928200117Smav (u_int32_t)fis[12]); 929183724Ssos} 930183724Ssos 931199322Smavstatic void 932183724Ssosata_ahci_reset(device_t dev) 933183724Ssos{ 934183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 935183724Ssos struct ata_channel *ch = device_get_softc(dev); 936188621Smav u_int32_t signature; 937183724Ssos int offset = ch->unit << 7; 938183724Ssos 939188918Smav if (bootverbose) 940188918Smav device_printf(dev, "AHCI reset...\n"); 941188918Smav 942188861Smav /* Disable port interrupts */ 943188861Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0); 944188861Smav 945190581Smav if (ata_ahci_hardreset(dev, -1, &signature)) { 946183724Ssos if (bootverbose) 947188918Smav device_printf(dev, "AHCI reset done: phy reset found no device\n"); 948183724Ssos ch->devices = 0; 949183724Ssos 950188621Smav /* enable wanted port interrupts */ 951188621Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 952188621Smav (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)); 953183724Ssos return; 954183724Ssos } 955183724Ssos 956188621Smav /* enable wanted port interrupts */ 957188621Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 958188621Smav (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | 959188621Smav ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | 960191674Smav ((ch->pm_level == 0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) | 961191674Smav ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | 962191674Smav ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)); 963199262Smav /* 964199262Smav * Only probe for PortMultiplier if HW has support. 965199262Smav * Ignore Marvell, which is not working, 966199262Smav */ 967199262Smav if ((ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) && 968199262Smav pci_get_vendor(ctlr->dev) != 0x11ab) { 969183724Ssos signature = ata_ahci_softreset(dev, ATA_PM); 970188648Smav /* Workaround for some ATI chips, failing to soft-reset 971188648Smav * when port multiplicator supported, but absent. 972188648Smav * XXX: We can also check PxIS.IPMS==1 here to be sure. */ 973188648Smav if (signature == 0xffffffff) 974188648Smav signature = ata_ahci_softreset(dev, 0); 975188648Smav } else { 976183724Ssos signature = ata_ahci_softreset(dev, 0); 977183724Ssos } 978183724Ssos if (bootverbose) 979183724Ssos device_printf(dev, "SIGNATURE: %08x\n", signature); 980183724Ssos 981188906Smav switch (signature >> 16) { 982188906Smav case 0x0000: 983183724Ssos ch->devices = ATA_ATA_MASTER; 984183724Ssos break; 985188906Smav case 0x9669: 986183724Ssos ch->devices = ATA_PORTMULTIPLIER; 987183724Ssos ata_pm_identify(dev); 988183724Ssos break; 989188906Smav case 0xeb14: 990183724Ssos ch->devices = ATA_ATAPI_MASTER; 991183724Ssos break; 992183724Ssos default: /* SOS XXX */ 993183724Ssos if (bootverbose) 994188935Smav device_printf(dev, "Unknown signature, assuming disk device\n"); 995183724Ssos ch->devices = ATA_ATA_MASTER; 996183724Ssos } 997183724Ssos if (bootverbose) 998188918Smav device_printf(dev, "AHCI reset done: devices=%08x\n", ch->devices); 999183724Ssos} 1000183724Ssos 1001183724Ssosstatic void 1002183724Ssosata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 1003183724Ssos{ 1004183724Ssos struct ata_dmasetprd_args *args = xsc; 1005183724Ssos struct ata_ahci_dma_prd *prd = args->dmatab; 1006183724Ssos int i; 1007183724Ssos 1008183724Ssos if (!(args->error = error)) { 1009183724Ssos for (i = 0; i < nsegs; i++) { 1010183724Ssos prd[i].dba = htole64(segs[i].ds_addr); 1011183724Ssos prd[i].dbc = htole32((segs[i].ds_len - 1) & ATA_AHCI_PRD_MASK); 1012183724Ssos } 1013183724Ssos } 1014183724Ssos 1015183724Ssos KASSERT(nsegs <= ATA_AHCI_DMA_ENTRIES, ("too many DMA segment entries\n")); 1016183724Ssos args->nsegs = nsegs; 1017183724Ssos} 1018183724Ssos 1019188769Smavstatic void 1020183724Ssosata_ahci_dmainit(device_t dev) 1021183724Ssos{ 1022183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 1023183724Ssos struct ata_channel *ch = device_get_softc(dev); 1024183724Ssos 1025183724Ssos /* note start and stop are not used here */ 1026183724Ssos ch->dma.setprd = ata_ahci_dmasetprd; 1027195439Smav ch->dma.max_iosize = (ATA_AHCI_DMA_ENTRIES - 1) * PAGE_SIZE; 1028183724Ssos if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_64BIT) 1029183724Ssos ch->dma.max_address = BUS_SPACE_MAXADDR; 1030216013Smarius ata_dmainit(dev); 1031183724Ssos} 1032183724Ssos 1033183724Ssosstatic int 1034183724Ssosata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *request) 1035183724Ssos{ 1036183724Ssos bzero(ctp->cfis, 64); 1037183724Ssos if (request->flags & ATA_R_ATAPI) { 1038183724Ssos bzero(ctp->acmd, 32); 1039183724Ssos bcopy(request->u.atapi.ccb, ctp->acmd, 16); 1040183724Ssos } 1041183724Ssos return ata_request2fis_h2d(request, &ctp->cfis[0]); 1042183724Ssos} 1043183724Ssos 1044183724SsosATA_DECLARE_DRIVER(ata_ahci); 1045199322Smavstatic device_method_t ata_ahci_ata_methods[] = { 1046199322Smav DEVMETHOD(device_probe, ata_ahci_ata_probe), 1047199322Smav DEVMETHOD(device_attach, ata_ahci_ata_attach), 1048199322Smav DEVMETHOD(device_detach, ata_pci_detach), 1049199322Smav DEVMETHOD(device_suspend, ata_pci_suspend), 1050199322Smav DEVMETHOD(device_resume, ata_pci_resume), 1051199322Smav DEVMETHOD(device_shutdown, bus_generic_shutdown), 1052199322Smav DEVMETHOD(bus_read_ivar, ata_pci_read_ivar), 1053199322Smav DEVMETHOD(bus_write_ivar, ata_pci_write_ivar), 1054199322Smav DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), 1055199322Smav DEVMETHOD(bus_release_resource, ata_pci_release_resource), 1056199322Smav DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 1057199322Smav DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1058199322Smav DEVMETHOD(bus_setup_intr, ata_pci_setup_intr), 1059199322Smav DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr), 1060233282Smarius DEVMETHOD_END 1061199322Smav}; 1062199322Smavstatic driver_t ata_ahci_ata_driver = { 1063199322Smav "atapci", 1064199322Smav ata_ahci_ata_methods, 1065199322Smav sizeof(struct ata_pci_controller) 1066199322Smav}; 1067233282SmariusDRIVER_MODULE(ata_ahci_ata, atapci, ata_ahci_ata_driver, ata_pci_devclass, 1068233282Smarius NULL, NULL); 1069