1183724Ssos/*- 2183724Ssos * 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 "opt_ata.h" 31183724Ssos#include <sys/param.h> 32183724Ssos#include <sys/module.h> 33183724Ssos#include <sys/systm.h> 34183724Ssos#include <sys/kernel.h> 35183724Ssos#include <sys/ata.h> 36183724Ssos#include <sys/bus.h> 37183724Ssos#include <sys/endian.h> 38183724Ssos#include <sys/malloc.h> 39183724Ssos#include <sys/lock.h> 40183724Ssos#include <sys/mutex.h> 41183724Ssos#include <sys/sema.h> 42183724Ssos#include <sys/taskqueue.h> 43183724Ssos#include <vm/uma.h> 44183724Ssos#include <machine/stdarg.h> 45183724Ssos#include <machine/resource.h> 46183724Ssos#include <machine/bus.h> 47183724Ssos#include <sys/rman.h> 48183724Ssos#include <dev/pci/pcivar.h> 49183724Ssos#include <dev/pci/pcireg.h> 50183724Ssos#include <dev/ata/ata-all.h> 51183724Ssos#include <dev/ata/ata-pci.h> 52183724Ssos#include <ata_if.h> 53183724Ssos 54183724Ssos/* local prototypes */ 55199322Smavstatic int ata_ahci_ch_attach(device_t dev); 56199322Smavstatic int ata_ahci_ch_detach(device_t dev); 57199322Smavstatic int ata_ahci_ch_suspend(device_t dev); 58199322Smavstatic int ata_ahci_ch_resume(device_t dev); 59199322Smavstatic int ata_ahci_ctlr_reset(device_t dev); 60199322Smavstatic void ata_ahci_reset(device_t dev); 61183724Ssosstatic int ata_ahci_suspend(device_t dev); 62183724Ssosstatic int ata_ahci_status(device_t dev); 63183724Ssosstatic int ata_ahci_begin_transaction(struct ata_request *request); 64183724Ssosstatic int ata_ahci_end_transaction(struct ata_request *request); 65183724Ssosstatic int ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result); 66183724Ssosstatic int ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t result); 67190581Smavstatic int ata_ahci_hardreset(device_t dev, int port, uint32_t *signature); 68183724Ssosstatic u_int32_t ata_ahci_softreset(device_t dev, int port); 69183724Ssosstatic void ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); 70183724Ssosstatic int ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *equest); 71188769Smavstatic void ata_ahci_dmainit(device_t dev); 72190581Smavstatic void ata_ahci_start(device_t dev); 73190581Smavstatic void ata_ahci_stop(device_t dev); 74190581Smavstatic void ata_ahci_clo(device_t dev); 75190581Smavstatic void ata_ahci_start_fr(device_t dev); 76190581Smavstatic void ata_ahci_stop_fr(device_t dev); 77183724Ssos 78183724Ssos/* 79183724Ssos * AHCI v1.x compliant SATA chipset support functions 80183724Ssos */ 81183724Ssosstatic int 82183724Ssosata_ahci_probe(device_t dev) 83183724Ssos{ 84183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 85183724Ssos char buffer[64]; 86183724Ssos 87183724Ssos /* is this a possible AHCI candidate ? */ 88186296Smav if (pci_get_class(dev) != PCIC_STORAGE || 89186296Smav pci_get_subclass(dev) != PCIS_STORAGE_SATA) 90186296Smav return (ENXIO); 91183724Ssos 92183724Ssos /* is this PCI device flagged as an AHCI compliant chip ? */ 93191601Sjkim if (pci_get_progif(dev) != PCIP_STORAGE_SATA_AHCI_1_0) 94191600Sjkim return (ENXIO); 95183724Ssos 96183724Ssos if (bootverbose) 97183724Ssos sprintf(buffer, "%s (ID=%08x) AHCI controller", 98183724Ssos ata_pcivendor2str(dev), pci_get_devid(dev)); 99183724Ssos else 100183724Ssos sprintf(buffer, "%s AHCI controller", ata_pcivendor2str(dev)); 101183724Ssos device_set_desc_copy(dev, buffer); 102183724Ssos ctlr->chipinit = ata_ahci_chipinit; 103191600Sjkim return (BUS_PROBE_GENERIC); 104183724Ssos} 105183724Ssos 106199322Smavstatic int 107199322Smavata_ahci_ata_probe(device_t dev) 108199322Smav{ 109199322Smav struct ata_pci_controller *ctlr = device_get_softc(dev); 110199322Smav 111199322Smav if ((intptr_t)device_get_ivars(dev) >= 0) 112199322Smav return (ENXIO); 113199322Smav device_set_desc_copy(dev, "AHCI SATA controller"); 114199322Smav ctlr->chipinit = ata_ahci_chipinit; 115199322Smav return (BUS_PROBE_GENERIC); 116199322Smav} 117199322Smav 118199322Smavstatic int 119199322Smavata_ahci_ata_attach(device_t dev) 120199322Smav{ 121199322Smav struct ata_pci_controller *ctlr = device_get_softc(dev); 122199322Smav device_t child; 123199322Smav int unit; 124199322Smav 125199322Smav /* do chipset specific setups only needed once */ 126199322Smav ctlr->legacy = 0; 127199322Smav ctlr->ichannels = -1; 128199322Smav ctlr->ch_attach = ata_pci_ch_attach; 129199322Smav ctlr->ch_detach = ata_pci_ch_detach; 130199322Smav ctlr->dev = dev; 131199322Smav if (ctlr->chipinit(dev)) 132199322Smav return ENXIO; 133199322Smav /* attach all channels on this controller */ 134199322Smav for (unit = 0; unit < ctlr->channels; unit++) { 135199322Smav if ((ctlr->ichannels & (1 << unit)) == 0) 136199322Smav continue; 137199322Smav child = device_add_child(dev, "ata", 138199322Smav ((unit == 0 || unit == 1) && ctlr->legacy) ? 139199322Smav unit : devclass_find_free_unit(ata_devclass, 2)); 140199322Smav if (child == NULL) 141199322Smav device_printf(dev, "failed to add ata child device\n"); 142199322Smav else 143199322Smav device_set_ivars(child, (void *)(intptr_t)unit); 144199322Smav } 145199322Smav bus_generic_attach(dev); 146199322Smav return 0; 147199322Smav} 148199322Smav 149183724Ssosint 150183724Ssosata_ahci_chipinit(device_t dev) 151183724Ssos{ 152183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 153193277Smav int error, speed; 154193277Smav u_int32_t caps, version; 155183724Ssos 156183724Ssos /* if we have a memory BAR(5) we are likely on an AHCI part */ 157183724Ssos ctlr->r_type2 = SYS_RES_MEMORY; 158183724Ssos ctlr->r_rid2 = PCIR_BAR(5); 159183724Ssos if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, 160183724Ssos &ctlr->r_rid2, RF_ACTIVE))) 161183724Ssos return ENXIO; 162183724Ssos 163183724Ssos /* setup interrupt delivery if not done allready by a vendor driver */ 164183724Ssos if (!ctlr->r_irq) { 165186250Smav if (ata_setup_interrupt(dev, ata_generic_intr)) { 166186250Smav bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2); 167183724Ssos return ENXIO; 168186250Smav } 169183724Ssos } 170183724Ssos else 171183724Ssos device_printf(dev, "AHCI called from vendor specific driver\n"); 172183724Ssos 173183724Ssos /* reset controller */ 174186250Smav if ((error = ata_ahci_ctlr_reset(dev)) != 0) { 175186250Smav bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2); 176186250Smav return (error); 177186250Smav }; 178183724Ssos 179183724Ssos /* get the number of HW channels */ 180188694Smav ctlr->ichannels = ATA_INL(ctlr->r_res2, ATA_AHCI_PI); 181199322Smav ctlr->channels = MAX(flsl(ctlr->ichannels), 182191674Smav (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_NPMASK) + 1); 183232716Smav if (pci_get_devid(dev) == ATA_M88SE6111) 184199322Smav ctlr->channels = 1; 185232716Smav else if (pci_get_devid(dev) == ATA_M88SE6121) 186199322Smav ctlr->channels = 2; 187232716Smav else if (pci_get_devid(dev) == ATA_M88SE6141 || 188232716Smav pci_get_devid(dev) == ATA_M88SE6145) 189199322Smav ctlr->channels = 4; 190183724Ssos 191183724Ssos ctlr->reset = ata_ahci_reset; 192188765Smav ctlr->ch_attach = ata_ahci_ch_attach; 193188769Smav ctlr->ch_detach = ata_ahci_ch_detach; 194190581Smav ctlr->ch_suspend = ata_ahci_ch_suspend; 195190581Smav ctlr->ch_resume = ata_ahci_ch_resume; 196183724Ssos ctlr->setmode = ata_sata_setmode; 197200171Smav ctlr->getrev = ata_sata_getrev; 198183724Ssos ctlr->suspend = ata_ahci_suspend; 199183724Ssos ctlr->resume = ata_ahci_ctlr_reset; 200183724Ssos 201193277Smav /* announce we support the HW */ 202193277Smav version = ATA_INL(ctlr->r_res2, ATA_AHCI_VS); 203193277Smav caps = ATA_INL(ctlr->r_res2, ATA_AHCI_CAP); 204193277Smav speed = (caps & ATA_AHCI_CAP_ISS) >> ATA_AHCI_CAP_ISS_SHIFT; 205193277Smav device_printf(dev, 206193277Smav "AHCI v%x.%02x controller with %d %sGbps ports, PM %s\n", 207193277Smav ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f), 208193277Smav ((version >> 4) & 0xf0) + (version & 0x0f), 209193277Smav (caps & ATA_AHCI_CAP_NPMASK) + 1, 210193277Smav ((speed == 1) ? "1.5":((speed == 2) ? "3": 211193277Smav ((speed == 3) ? "6":"?"))), 212193277Smav (caps & ATA_AHCI_CAP_SPM) ? 213193277Smav "supported" : "not supported"); 214193277Smav if (bootverbose) { 215193277Smav device_printf(dev, "Caps:%s%s%s%s%s%s%s%s %sGbps", 216193277Smav (caps & ATA_AHCI_CAP_64BIT) ? " 64bit":"", 217193277Smav (caps & ATA_AHCI_CAP_SNCQ) ? " NCQ":"", 218193277Smav (caps & ATA_AHCI_CAP_SSNTF) ? " SNTF":"", 219193277Smav (caps & ATA_AHCI_CAP_SMPS) ? " MPS":"", 220193277Smav (caps & ATA_AHCI_CAP_SSS) ? " SS":"", 221193277Smav (caps & ATA_AHCI_CAP_SALP) ? " ALP":"", 222193277Smav (caps & ATA_AHCI_CAP_SAL) ? " AL":"", 223193277Smav (caps & ATA_AHCI_CAP_SCLO) ? " CLO":"", 224193277Smav ((speed == 1) ? "1.5":((speed == 2) ? "3": 225193277Smav ((speed == 3) ? "6":"?")))); 226193277Smav printf("%s%s%s%s%s%s %dcmd%s%s%s %dports\n", 227193277Smav (caps & ATA_AHCI_CAP_SAM) ? " AM":"", 228193277Smav (caps & ATA_AHCI_CAP_SPM) ? " PM":"", 229193277Smav (caps & ATA_AHCI_CAP_FBSS) ? " FBS":"", 230193277Smav (caps & ATA_AHCI_CAP_PMD) ? " PMD":"", 231193277Smav (caps & ATA_AHCI_CAP_SSC) ? " SSC":"", 232193277Smav (caps & ATA_AHCI_CAP_PSC) ? " PSC":"", 233193277Smav ((caps & ATA_AHCI_CAP_NCS) >> ATA_AHCI_CAP_NCS_SHIFT) + 1, 234193277Smav (caps & ATA_AHCI_CAP_CCCS) ? " CCC":"", 235193277Smav (caps & ATA_AHCI_CAP_EMS) ? " EM":"", 236193277Smav (caps & ATA_AHCI_CAP_SXS) ? " eSATA":"", 237193277Smav (caps & ATA_AHCI_CAP_NPMASK) + 1); 238193277Smav } 239193277Smav return 0; 240183724Ssos} 241183724Ssos 242199322Smavstatic int 243183724Ssosata_ahci_ctlr_reset(device_t dev) 244183724Ssos{ 245183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 246188621Smav int timeout; 247183724Ssos 248183724Ssos /* enable AHCI mode */ 249183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE); 250183724Ssos 251183724Ssos /* reset AHCI controller */ 252188621Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE|ATA_AHCI_GHC_HR); 253188621Smav for (timeout = 1000; timeout > 0; timeout--) { 254188621Smav DELAY(1000); 255188621Smav if ((ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & ATA_AHCI_GHC_HR) == 0) 256188621Smav break; 257188621Smav } 258188621Smav if (timeout == 0) { 259183724Ssos device_printf(dev, "AHCI controller reset failure\n"); 260183724Ssos return ENXIO; 261183724Ssos } 262183724Ssos 263183724Ssos /* reenable AHCI mode */ 264183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE); 265183724Ssos 266183724Ssos /* clear interrupts */ 267183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, ATA_INL(ctlr->r_res2, ATA_AHCI_IS)); 268183724Ssos 269183724Ssos /* enable AHCI interrupts */ 270183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, 271183724Ssos ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_IE); 272183724Ssos 273183724Ssos return 0; 274183724Ssos} 275183724Ssos 276183724Ssosstatic int 277183724Ssosata_ahci_suspend(device_t dev) 278183724Ssos{ 279183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 280183724Ssos 281183724Ssos /* disable interupts so the state change(s) doesn't trigger */ 282183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, 283183724Ssos ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & (~ATA_AHCI_GHC_IE)); 284183724Ssos return 0; 285183724Ssos} 286183724Ssos 287199322Smavstatic int 288188765Smavata_ahci_ch_attach(device_t dev) 289183724Ssos{ 290183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 291183724Ssos struct ata_channel *ch = device_get_softc(dev); 292183724Ssos int offset = ch->unit << 7; 293183724Ssos 294188765Smav ata_ahci_dmainit(dev); 295188765Smav 296183724Ssos /* set the SATA resources */ 297183724Ssos ch->r_io[ATA_SSTATUS].res = ctlr->r_res2; 298183724Ssos ch->r_io[ATA_SSTATUS].offset = ATA_AHCI_P_SSTS + offset; 299183724Ssos ch->r_io[ATA_SERROR].res = ctlr->r_res2; 300183724Ssos ch->r_io[ATA_SERROR].offset = ATA_AHCI_P_SERR + offset; 301183724Ssos ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; 302183724Ssos ch->r_io[ATA_SCONTROL].offset = ATA_AHCI_P_SCTL + offset; 303183724Ssos ch->r_io[ATA_SACTIVE].res = ctlr->r_res2; 304183724Ssos ch->r_io[ATA_SACTIVE].offset = ATA_AHCI_P_SACT + offset; 305183724Ssos 306183724Ssos ch->hw.status = ata_ahci_status; 307183724Ssos ch->hw.begin_transaction = ata_ahci_begin_transaction; 308183724Ssos ch->hw.end_transaction = ata_ahci_end_transaction; 309183724Ssos ch->hw.command = NULL; /* not used here */ 310183724Ssos ch->hw.softreset = ata_ahci_softreset; 311183724Ssos ch->hw.pm_read = ata_ahci_pm_read; 312183724Ssos ch->hw.pm_write = ata_ahci_pm_write; 313200171Smav ch->flags |= ATA_NO_SLAVE; 314200171Smav ch->flags |= ATA_SATA; 315183724Ssos 316190581Smav ata_ahci_ch_resume(dev); 317183724Ssos return 0; 318183724Ssos} 319183724Ssos 320199322Smavstatic int 321188769Smavata_ahci_ch_detach(device_t dev) 322188769Smav{ 323219337Smarius struct ata_channel *ch = device_get_softc(dev); 324219337Smarius 325219337Smarius if (ch->dma.work_tag && ch->dma.work_map) 326219337Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 327219337Smarius BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 328190581Smav ata_ahci_ch_suspend(dev); 329190581Smav ata_dmafini(dev); 330190581Smav return (0); 331190581Smav} 332190581Smav 333199322Smavstatic int 334190581Smavata_ahci_ch_suspend(device_t dev) 335190581Smav{ 336188877Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 337188877Smav struct ata_channel *ch = device_get_softc(dev); 338188877Smav int offset = ch->unit << 7; 339188769Smav 340188877Smav /* Disable port interrupts. */ 341188877Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0); 342188877Smav /* Reset command register. */ 343190581Smav ata_ahci_stop(dev); 344190581Smav ata_ahci_stop_fr(dev); 345188877Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 0); 346188877Smav 347188877Smav /* Allow everything including partial and slumber modes. */ 348188877Smav ATA_IDX_OUTL(ch, ATA_SCONTROL, 0); 349188877Smav /* Request slumber mode transition and give some time to get there. */ 350188877Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, ATA_AHCI_P_CMD_SLUMBER); 351188877Smav DELAY(100); 352188877Smav /* Disable PHY. */ 353188877Smav ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_DISABLE); 354188877Smav 355188769Smav return (0); 356188769Smav} 357188769Smav 358199322Smavstatic int 359190581Smavata_ahci_ch_resume(device_t dev) 360190581Smav{ 361190581Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 362190581Smav struct ata_channel *ch = device_get_softc(dev); 363190581Smav uint64_t work; 364190581Smav int offset = ch->unit << 7; 365190581Smav 366190581Smav /* Disable port interrupts */ 367190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0); 368190581Smav 369190581Smav /* setup work areas */ 370190581Smav work = ch->dma.work_bus + ATA_AHCI_CL_OFFSET; 371190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff); 372190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32); 373190581Smav 374190581Smav work = ch->dma.work_bus + ATA_AHCI_FB_OFFSET; 375190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff); 376190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32); 377190581Smav 378190581Smav /* activate the channel and power/spin up device */ 379190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 380191674Smav (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | 381191674Smav ((ch->pm_level > 1) ? ATA_AHCI_P_CMD_ALPE : 0) | 382191674Smav ((ch->pm_level > 2) ? ATA_AHCI_P_CMD_ASP : 0 ))); 383190581Smav ata_ahci_start_fr(dev); 384190581Smav ata_ahci_start(dev); 385190581Smav 386190581Smav return (0); 387190581Smav} 388190581Smav 389183724Ssosstatic int 390183724Ssosata_ahci_status(device_t dev) 391183724Ssos{ 392183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 393183724Ssos struct ata_channel *ch = device_get_softc(dev); 394183724Ssos u_int32_t action = ATA_INL(ctlr->r_res2, ATA_AHCI_IS); 395183724Ssos int offset = ch->unit << 7; 396183724Ssos 397183724Ssos#define ATA_AHCI_STATBITS \ 398183724Ssos (ATA_AHCI_P_IX_IF|ATA_AHCI_P_IX_HBD|ATA_AHCI_P_IX_HBF|ATA_AHCI_P_IX_TFE) 399183724Ssos 400183724Ssos if (action & (1 << ch->unit)) { 401183724Ssos u_int32_t istatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset); 402183724Ssos u_int32_t cstatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset); 403183724Ssos 404183724Ssos /* clear interrupt(s) */ 405183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, istatus); 406188658Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, 1 << ch->unit); 407183724Ssos 408183724Ssos /* do we have any PHY events ? */ 409183724Ssos if (istatus & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) 410214016Smav ata_sata_phy_check_events(dev, -1); 411183724Ssos 412183724Ssos /* do we have a potentially hanging engine to take care of? */ 413183724Ssos /* XXX SOS what todo on NCQ */ 414183724Ssos if ((istatus & ATA_AHCI_STATBITS) && (cstatus & 1)) { 415183724Ssos 416183724Ssos u_int32_t cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 417183724Ssos int timeout = 0; 418183724Ssos 419183724Ssos /* kill off all activity on this channel */ 420183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 421183724Ssos cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); 422183724Ssos 423183724Ssos /* XXX SOS this is not entirely wrong */ 424183724Ssos do { 425183724Ssos DELAY(1000); 426183724Ssos if (timeout++ > 1000) { 427183724Ssos device_printf(dev, "stopping AHCI engine failed\n"); 428183724Ssos break; 429183724Ssos } 430183724Ssos } while (ATA_INL(ctlr->r_res2, 431183724Ssos ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_CR); 432183724Ssos 433183724Ssos /* start operations on this channel */ 434183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 435183724Ssos cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); 436183724Ssos 437183724Ssos return 1; 438183724Ssos } 439183724Ssos else 440183724Ssos /* XXX SOS what todo on NCQ */ 441183724Ssos return (!(cstatus & 1)); 442183724Ssos } 443183724Ssos return 0; 444183724Ssos} 445183724Ssos 446183724Ssos/* must be called with ATA channel locked and state_mtx held */ 447183724Ssosstatic int 448183724Ssosata_ahci_begin_transaction(struct ata_request *request) 449183724Ssos{ 450198717Smav struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); 451183724Ssos struct ata_channel *ch = device_get_softc(request->parent); 452183724Ssos struct ata_ahci_cmd_tab *ctp; 453183724Ssos struct ata_ahci_cmd_list *clp; 454183724Ssos int offset = ch->unit << 7; 455198717Smav int port = request->unit & 0x0f; 456183724Ssos int entries = 0; 457183724Ssos int fis_size; 458183724Ssos 459183724Ssos /* get a piece of the workspace for this request */ 460183724Ssos ctp = (struct ata_ahci_cmd_tab *) 461198717Smav (ch->dma.work + ATA_AHCI_CT_OFFSET); 462183724Ssos 463183724Ssos /* setup the FIS for this request */ 464183724Ssos if (!(fis_size = ata_ahci_setup_fis(ctp, request))) { 465198717Smav device_printf(request->parent, "setting up SATA FIS failed\n"); 466183724Ssos request->result = EIO; 467183724Ssos return ATA_OP_FINISHED; 468183724Ssos } 469183724Ssos 470183724Ssos /* if request moves data setup and load SG list */ 471183724Ssos if (request->flags & (ATA_R_READ | ATA_R_WRITE)) { 472183724Ssos if (ch->dma.load(request, ctp->prd_tab, &entries)) { 473198717Smav device_printf(request->parent, "setting up DMA failed\n"); 474183724Ssos request->result = EIO; 475183724Ssos return ATA_OP_FINISHED; 476183724Ssos } 477183724Ssos } 478183724Ssos 479183724Ssos /* setup the command list entry */ 480183724Ssos clp = (struct ata_ahci_cmd_list *) 481198717Smav (ch->dma.work + ATA_AHCI_CL_OFFSET); 482183724Ssos 483183724Ssos clp->prd_length = entries; 484183724Ssos clp->cmd_flags = (request->flags & ATA_R_WRITE ? ATA_AHCI_CMD_WRITE : 0) | 485183724Ssos (request->flags & ATA_R_ATAPI ? 486183724Ssos (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH) : 0) | 487183724Ssos (fis_size / sizeof(u_int32_t)) | 488183724Ssos (port << 12); 489183724Ssos clp->bytecount = 0; 490198717Smav clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET); 491183724Ssos 492183724Ssos /* set command type bit */ 493183724Ssos if (request->flags & ATA_R_ATAPI) 494183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 495183724Ssos ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) | 496183724Ssos ATA_AHCI_P_CMD_ATAPI); 497183724Ssos else 498183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 499183724Ssos ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & 500183724Ssos ~ATA_AHCI_P_CMD_ATAPI); 501183724Ssos 502219337Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 503219337Smarius BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 504219337Smarius 505183724Ssos /* issue command to controller */ 506198717Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, 1); 507183724Ssos 508183724Ssos if (!(request->flags & ATA_R_ATAPI)) { 509183724Ssos /* device reset doesn't interrupt */ 510183724Ssos if (request->u.ata.command == ATA_DEVICE_RESET) { 511183724Ssos u_int32_t tf_data; 512183724Ssos int timeout = 1000000; 513183724Ssos 514183724Ssos do { 515183724Ssos DELAY(10); 516183724Ssos tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + (ch->unit<<7)); 517183724Ssos } while ((tf_data & ATA_S_BUSY) && timeout--); 518183724Ssos if (bootverbose) 519183724Ssos device_printf(ch->dev, "device_reset timeout=%dus\n", 520183724Ssos (1000000-timeout)*10); 521183724Ssos request->status = tf_data; 522183724Ssos if (request->status & ATA_S_ERROR) 523183724Ssos request->error = tf_data >> 8; 524183724Ssos return ATA_OP_FINISHED; 525183724Ssos } 526183724Ssos } 527183724Ssos 528183724Ssos /* start the timeout */ 529183724Ssos callout_reset(&request->callout, request->timeout * hz, 530183724Ssos (timeout_t*)ata_timeout, request); 531183724Ssos return ATA_OP_CONTINUES; 532183724Ssos} 533183724Ssos 534183724Ssos/* must be called with ATA channel locked and state_mtx held */ 535183724Ssosstatic int 536183724Ssosata_ahci_end_transaction(struct ata_request *request) 537183724Ssos{ 538198717Smav struct ata_pci_controller *ctlr=device_get_softc(device_get_parent(request->parent)); 539183724Ssos struct ata_channel *ch = device_get_softc(request->parent); 540183724Ssos struct ata_ahci_cmd_list *clp; 541183724Ssos u_int32_t tf_data; 542183724Ssos int offset = ch->unit << 7; 543183724Ssos 544183724Ssos /* kill the timeout */ 545183724Ssos callout_stop(&request->callout); 546183724Ssos 547219337Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 548219337Smarius BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 549219337Smarius 550183724Ssos /* get status */ 551183724Ssos tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset); 552183724Ssos request->status = tf_data; 553183724Ssos 554183724Ssos /* if error status get details */ 555183724Ssos if (request->status & ATA_S_ERROR) 556183724Ssos request->error = tf_data >> 8; 557183724Ssos 558243125Smav /* Read back registers to the request struct. */ 559243125Smav if ((request->flags & ATA_R_ATAPI) == 0 && 560243125Smav ((request->status & ATA_S_ERROR) || 561243125Smav (request->flags & (ATA_R_CONTROL | ATA_R_NEEDRESULT)))) { 562183724Ssos u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; 563183724Ssos 564183724Ssos request->u.ata.count = fis[12] | ((u_int16_t)fis[13] << 8); 565183724Ssos request->u.ata.lba = fis[4] | ((u_int64_t)fis[5] << 8) | 566183724Ssos ((u_int64_t)fis[6] << 16); 567198717Smav if (request->flags & ATA_R_48BIT) 568183724Ssos request->u.ata.lba |= ((u_int64_t)fis[8] << 24) | 569183724Ssos ((u_int64_t)fis[9] << 32) | 570183724Ssos ((u_int64_t)fis[10] << 40); 571183724Ssos else 572183724Ssos request->u.ata.lba |= ((u_int64_t)(fis[7] & 0x0f) << 24); 573183724Ssos } 574183724Ssos 575183724Ssos /* record how much data we actually moved */ 576183724Ssos clp = (struct ata_ahci_cmd_list *) 577198717Smav (ch->dma.work + ATA_AHCI_CL_OFFSET); 578213092Smav request->donecount = le32toh(clp->bytecount); 579183724Ssos 580183724Ssos /* release SG list etc */ 581183724Ssos ch->dma.unload(request); 582183724Ssos 583183724Ssos return ATA_OP_FINISHED; 584183724Ssos} 585183724Ssos 586183724Ssosstatic int 587183724Ssosata_ahci_issue_cmd(device_t dev, u_int16_t flags, int timeout) 588183724Ssos{ 589183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 590183724Ssos struct ata_channel *ch = device_get_softc(dev); 591183724Ssos struct ata_ahci_cmd_list *clp = 592183724Ssos (struct ata_ahci_cmd_list *)(ch->dma.work + ATA_AHCI_CL_OFFSET); 593183724Ssos struct ata_ahci_cmd_tab *ctp = 594183724Ssos (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); 595183724Ssos u_int32_t status = 0; 596183724Ssos int offset = ch->unit << 7; 597183724Ssos int port = (ctp->cfis[1] & 0x0f); 598183724Ssos int count; 599183724Ssos 600183724Ssos clp->prd_length = 0; 601183724Ssos clp->cmd_flags = (20 / sizeof(u_int32_t)) | flags | (port << 12); 602183724Ssos clp->bytecount = 0; 603183724Ssos clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET); 604183724Ssos 605219337Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 606219337Smarius BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 607219337Smarius 608183724Ssos /* issue command to controller */ 609183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, 1); 610183724Ssos 611183724Ssos /* poll for command finished */ 612183724Ssos for (count = 0; count < timeout; count++) { 613183724Ssos DELAY(1000); 614183724Ssos if (!((status = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset)) & 1)) 615183724Ssos break; 616183724Ssos } 617183724Ssos 618219337Smarius bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map, 619219337Smarius BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 620219337Smarius 621183724Ssos /* clear interrupts */ 622183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, 623190581Smav ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset)); 624183724Ssos 625188918Smav if (timeout && (count >= timeout)) { 626188918Smav if (bootverbose) { 627188918Smav device_printf(dev, "ahci_issue_cmd timeout: %d of %dms, status=%08x\n", 628188918Smav count, timeout, status); 629188918Smav } 630183724Ssos return EIO; 631188918Smav } 632183724Ssos 633183724Ssos return 0; 634183724Ssos} 635183724Ssos 636183724Ssosstatic int 637183724Ssosata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result) 638183724Ssos{ 639183724Ssos struct ata_channel *ch = device_get_softc(dev); 640183724Ssos struct ata_ahci_cmd_tab *ctp = 641183724Ssos (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); 642183724Ssos u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; 643183724Ssos 644214016Smav if (port < 0) { 645214016Smav *result = ATA_IDX_INL(ch, reg); 646214016Smav return (0); 647214016Smav } 648214016Smav if (port < ATA_PM) { 649214016Smav switch (reg) { 650214016Smav case ATA_SSTATUS: 651214016Smav reg = 0; 652214016Smav break; 653214016Smav case ATA_SERROR: 654214016Smav reg = 1; 655214016Smav break; 656214016Smav case ATA_SCONTROL: 657214016Smav reg = 2; 658214016Smav break; 659214016Smav default: 660214016Smav return (EINVAL); 661214016Smav } 662214016Smav } 663183724Ssos bzero(ctp->cfis, 64); 664183724Ssos ctp->cfis[0] = 0x27; /* host to device */ 665183724Ssos ctp->cfis[1] = 0x8f; /* command FIS to PM port */ 666183724Ssos ctp->cfis[2] = ATA_READ_PM; 667183724Ssos ctp->cfis[3] = reg; 668183724Ssos ctp->cfis[7] = port | ATA_D_LBA; 669183724Ssos ctp->cfis[15] = ATA_A_4BIT; 670183724Ssos 671183724Ssos if (ata_ahci_issue_cmd(dev, 0, 10)) { 672183724Ssos device_printf(dev, "error reading PM port\n"); 673183724Ssos return EIO; 674183724Ssos } 675183724Ssos 676183724Ssos *result = fis[12] | (fis[4] << 8) | (fis[5] << 16) | (fis[6] << 24); 677183724Ssos return 0; 678183724Ssos} 679183724Ssos 680183724Ssosstatic int 681183724Ssosata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t value) 682183724Ssos{ 683183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 684183724Ssos struct ata_channel *ch = device_get_softc(dev); 685183724Ssos struct ata_ahci_cmd_tab *ctp = 686183724Ssos (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); 687183724Ssos int offset = ch->unit << 7; 688183724Ssos 689214016Smav if (port < 0) { 690214016Smav ATA_IDX_OUTL(ch, reg, value); 691214016Smav return (0); 692214016Smav } 693214016Smav if (port < ATA_PM) { 694214016Smav switch (reg) { 695214016Smav case ATA_SSTATUS: 696214016Smav reg = 0; 697214016Smav break; 698214016Smav case ATA_SERROR: 699214016Smav reg = 1; 700214016Smav break; 701214016Smav case ATA_SCONTROL: 702214016Smav reg = 2; 703214016Smav break; 704214016Smav default: 705214016Smav return (EINVAL); 706214016Smav } 707214016Smav } 708183724Ssos bzero(ctp->cfis, 64); 709183724Ssos ctp->cfis[0] = 0x27; /* host to device */ 710183724Ssos ctp->cfis[1] = 0x8f; /* command FIS to PM port */ 711183724Ssos ctp->cfis[2] = ATA_WRITE_PM; 712183724Ssos ctp->cfis[3] = reg; 713183724Ssos ctp->cfis[7] = port | ATA_D_LBA; 714183724Ssos ctp->cfis[12] = value & 0xff; 715201758Smbr ctp->cfis[4] = (value >> 8) & 0xff; 716201758Smbr ctp->cfis[5] = (value >> 16) & 0xff; 717201758Smbr ctp->cfis[6] = (value >> 24) & 0xff; 718183724Ssos ctp->cfis[15] = ATA_A_4BIT; 719183724Ssos 720183724Ssos if (ata_ahci_issue_cmd(dev, 0, 100)) { 721183724Ssos device_printf(dev, "error writing PM port\n"); 722183724Ssos return ATA_E_ABORT; 723183724Ssos } 724183724Ssos 725183724Ssos return (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) >> 8) & 0xff; 726183724Ssos} 727183724Ssos 728183724Ssosstatic void 729188621Smavata_ahci_stop(device_t dev) 730183724Ssos{ 731183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 732183724Ssos struct ata_channel *ch = device_get_softc(dev); 733183724Ssos u_int32_t cmd; 734183724Ssos int offset = ch->unit << 7; 735183724Ssos int timeout; 736183724Ssos 737183724Ssos /* kill off all activity on this channel */ 738183724Ssos cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 739183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 740190581Smav cmd & ~ATA_AHCI_P_CMD_ST); 741183724Ssos 742183724Ssos /* XXX SOS this is not entirely wrong */ 743183724Ssos timeout = 0; 744183724Ssos do { 745183724Ssos DELAY(1000); 746183724Ssos if (timeout++ > 1000) { 747183724Ssos device_printf(dev, "stopping AHCI engine failed\n"); 748183724Ssos break; 749183724Ssos } 750183724Ssos } 751183724Ssos while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_CR); 752188621Smav} 753183724Ssos 754188621Smavstatic void 755188621Smavata_ahci_clo(device_t dev) 756188621Smav{ 757188621Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 758188621Smav struct ata_channel *ch = device_get_softc(dev); 759188621Smav u_int32_t cmd; 760188621Smav int offset = ch->unit << 7; 761188621Smav int timeout; 762188621Smav 763183724Ssos /* issue Command List Override if supported */ 764193277Smav if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SCLO) { 765183724Ssos cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 766183724Ssos cmd |= ATA_AHCI_P_CMD_CLO; 767183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd); 768183724Ssos timeout = 0; 769183724Ssos do { 770183724Ssos DELAY(1000); 771183724Ssos if (timeout++ > 1000) { 772183724Ssos device_printf(dev, "executing CLO failed\n"); 773183724Ssos break; 774183724Ssos } 775183724Ssos } 776183724Ssos while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD+offset)&ATA_AHCI_P_CMD_CLO); 777183724Ssos } 778188621Smav} 779183724Ssos 780188621Smavstatic void 781188621Smavata_ahci_start(device_t dev) 782188621Smav{ 783188621Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 784188621Smav struct ata_channel *ch = device_get_softc(dev); 785188621Smav u_int32_t cmd; 786188621Smav int offset = ch->unit << 7; 787188621Smav 788183724Ssos /* clear SATA error register */ 789183724Ssos ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); 790183724Ssos 791183724Ssos /* clear any interrupts pending on this channel */ 792183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, 793183724Ssos ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset)); 794183724Ssos 795183724Ssos /* start operations on this channel */ 796183724Ssos cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 797183724Ssos ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 798190581Smav cmd | ATA_AHCI_P_CMD_ST | 799183724Ssos (ch->devices & ATA_PORTMULTIPLIER ? ATA_AHCI_P_CMD_PMA : 0)); 800183724Ssos} 801183724Ssos 802190581Smavstatic void 803190581Smavata_ahci_stop_fr(device_t dev) 804190581Smav{ 805190581Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 806190581Smav struct ata_channel *ch = device_get_softc(dev); 807190581Smav u_int32_t cmd; 808190581Smav int offset = ch->unit << 7; 809190581Smav int timeout; 810190581Smav 811190581Smav /* kill off all activity on this channel */ 812190581Smav cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 813190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd & ~ATA_AHCI_P_CMD_FRE); 814190581Smav 815190581Smav timeout = 0; 816190581Smav do { 817190581Smav DELAY(1000); 818190581Smav if (timeout++ > 1000) { 819190581Smav device_printf(dev, "stopping AHCI FR engine failed\n"); 820190581Smav break; 821190581Smav } 822190581Smav } 823190581Smav while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_FR); 824190581Smav} 825190581Smav 826190581Smavstatic void 827190581Smavata_ahci_start_fr(device_t dev) 828190581Smav{ 829190581Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 830190581Smav struct ata_channel *ch = device_get_softc(dev); 831190581Smav u_int32_t cmd; 832190581Smav int offset = ch->unit << 7; 833190581Smav 834190581Smav /* start FIS reception on this channel */ 835190581Smav cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); 836190581Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd | ATA_AHCI_P_CMD_FRE); 837190581Smav} 838190581Smav 839188648Smavstatic int 840188905Smavata_ahci_wait_ready(device_t dev, int t) 841188621Smav{ 842188621Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 843188621Smav struct ata_channel *ch = device_get_softc(dev); 844188621Smav int offset = ch->unit << 7; 845188621Smav int timeout = 0; 846190581Smav uint32_t val; 847188621Smav 848190581Smav while ((val = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset)) & 849188621Smav (ATA_S_BUSY | ATA_S_DRQ)) { 850188621Smav DELAY(1000); 851188905Smav if (timeout++ > t) { 852190581Smav device_printf(dev, "port is not ready (timeout %dms) tfd = %08x\n", t, val); 853190581Smav return (EBUSY); 854188621Smav } 855188621Smav } 856188621Smav if (bootverbose) 857188621Smav device_printf(dev, "ready wait time=%dms\n", timeout); 858188648Smav return (0); 859188621Smav} 860188621Smav 861190581Smavstatic int 862190581Smavata_ahci_hardreset(device_t dev, int port, uint32_t *signature) 863190581Smav{ 864190581Smav struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 865190581Smav struct ata_channel *ch = device_get_softc(dev); 866190581Smav int offset = ch->unit << 7; 867190581Smav 868190581Smav *signature = 0xffffffff; 869190581Smav ata_ahci_stop(dev); 870190581Smav /* Reset port */ 871190581Smav if (!ata_sata_phy_reset(dev, port, 0)) 872190581Smav return (ENOENT); 873190581Smav /* Wait for clearing busy status. */ 874212081Smav if (ata_ahci_wait_ready(dev, 15000)) { 875190581Smav device_printf(dev, "hardware reset timeout\n"); 876190581Smav return (EBUSY); 877190581Smav } 878190581Smav *signature = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset); 879190581Smav ata_ahci_start(dev); 880190581Smav return (0); 881190581Smav} 882190581Smav 883183724Ssosstatic u_int32_t 884183724Ssosata_ahci_softreset(device_t dev, int port) 885183724Ssos{ 886183724Ssos struct ata_channel *ch = device_get_softc(dev); 887183724Ssos struct ata_ahci_cmd_tab *ctp = 888183724Ssos (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); 889200117Smav u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; 890183724Ssos 891188918Smav if (bootverbose) 892188918Smav device_printf(dev, "software reset port %d...\n", port); 893188918Smav 894188621Smav /* kick controller into sane state */ 895188621Smav ata_ahci_stop(dev); 896188621Smav ata_ahci_clo(dev); 897188621Smav ata_ahci_start(dev); 898183724Ssos 899183724Ssos /* pull reset active */ 900183724Ssos bzero(ctp->cfis, 64); 901183724Ssos ctp->cfis[0] = 0x27; 902183724Ssos ctp->cfis[1] = port & 0x0f; 903183724Ssos //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM; 904183724Ssos ctp->cfis[15] = (ATA_A_4BIT | ATA_A_RESET); 905183724Ssos 906188918Smav if (ata_ahci_issue_cmd(dev, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY,100)) { 907188918Smav device_printf(dev, "software reset set timeout\n"); 908188918Smav return (-1); 909188918Smav } 910183724Ssos 911188862Smav ata_udelay(50); 912183724Ssos 913183724Ssos /* pull reset inactive -> device softreset */ 914183724Ssos bzero(ctp->cfis, 64); 915183724Ssos ctp->cfis[0] = 0x27; 916183724Ssos ctp->cfis[1] = port & 0x0f; 917183724Ssos //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM; 918183724Ssos ctp->cfis[15] = ATA_A_4BIT; 919190581Smav ata_ahci_issue_cmd(dev, 0, 3000); 920183724Ssos 921190581Smav if (ata_ahci_wait_ready(dev, 0)) { 922188918Smav device_printf(dev, "software reset clear timeout\n"); 923188648Smav return (-1); 924188918Smav } 925183724Ssos 926200117Smav return (((u_int32_t)fis[6] << 24) | 927200117Smav ((u_int32_t)fis[5] << 16) | 928200117Smav ((u_int32_t)fis[4] << 8) | 929200117Smav (u_int32_t)fis[12]); 930183724Ssos} 931183724Ssos 932199322Smavstatic void 933183724Ssosata_ahci_reset(device_t dev) 934183724Ssos{ 935183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 936183724Ssos struct ata_channel *ch = device_get_softc(dev); 937188621Smav u_int32_t signature; 938183724Ssos int offset = ch->unit << 7; 939183724Ssos 940188918Smav if (bootverbose) 941188918Smav device_printf(dev, "AHCI reset...\n"); 942188918Smav 943188861Smav /* Disable port interrupts */ 944188861Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0); 945188861Smav 946190581Smav if (ata_ahci_hardreset(dev, -1, &signature)) { 947183724Ssos if (bootverbose) 948188918Smav device_printf(dev, "AHCI reset done: phy reset found no device\n"); 949183724Ssos ch->devices = 0; 950183724Ssos 951188621Smav /* enable wanted port interrupts */ 952188621Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 953188621Smav (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)); 954183724Ssos return; 955183724Ssos } 956183724Ssos 957188621Smav /* enable wanted port interrupts */ 958188621Smav ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 959188621Smav (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | 960188621Smav ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | 961191674Smav ((ch->pm_level == 0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) | 962191674Smav ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | 963191674Smav ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)); 964199262Smav /* 965199262Smav * Only probe for PortMultiplier if HW has support. 966199262Smav * Ignore Marvell, which is not working, 967199262Smav */ 968199262Smav if ((ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) && 969199262Smav pci_get_vendor(ctlr->dev) != 0x11ab) { 970183724Ssos signature = ata_ahci_softreset(dev, ATA_PM); 971188648Smav /* Workaround for some ATI chips, failing to soft-reset 972188648Smav * when port multiplicator supported, but absent. 973188648Smav * XXX: We can also check PxIS.IPMS==1 here to be sure. */ 974188648Smav if (signature == 0xffffffff) 975188648Smav signature = ata_ahci_softreset(dev, 0); 976188648Smav } else { 977183724Ssos signature = ata_ahci_softreset(dev, 0); 978183724Ssos } 979183724Ssos if (bootverbose) 980183724Ssos device_printf(dev, "SIGNATURE: %08x\n", signature); 981183724Ssos 982188906Smav switch (signature >> 16) { 983188906Smav case 0x0000: 984183724Ssos ch->devices = ATA_ATA_MASTER; 985183724Ssos break; 986188906Smav case 0x9669: 987183724Ssos ch->devices = ATA_PORTMULTIPLIER; 988183724Ssos ata_pm_identify(dev); 989183724Ssos break; 990188906Smav case 0xeb14: 991183724Ssos ch->devices = ATA_ATAPI_MASTER; 992183724Ssos break; 993183724Ssos default: /* SOS XXX */ 994183724Ssos if (bootverbose) 995188935Smav device_printf(dev, "Unknown signature, assuming disk device\n"); 996183724Ssos ch->devices = ATA_ATA_MASTER; 997183724Ssos } 998183724Ssos if (bootverbose) 999188918Smav device_printf(dev, "AHCI reset done: devices=%08x\n", ch->devices); 1000183724Ssos} 1001183724Ssos 1002183724Ssosstatic void 1003183724Ssosata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 1004183724Ssos{ 1005183724Ssos struct ata_dmasetprd_args *args = xsc; 1006183724Ssos struct ata_ahci_dma_prd *prd = args->dmatab; 1007183724Ssos int i; 1008183724Ssos 1009183724Ssos if (!(args->error = error)) { 1010183724Ssos for (i = 0; i < nsegs; i++) { 1011183724Ssos prd[i].dba = htole64(segs[i].ds_addr); 1012183724Ssos prd[i].dbc = htole32((segs[i].ds_len - 1) & ATA_AHCI_PRD_MASK); 1013183724Ssos } 1014183724Ssos } 1015183724Ssos 1016183724Ssos KASSERT(nsegs <= ATA_AHCI_DMA_ENTRIES, ("too many DMA segment entries\n")); 1017183724Ssos args->nsegs = nsegs; 1018183724Ssos} 1019183724Ssos 1020188769Smavstatic void 1021183724Ssosata_ahci_dmainit(device_t dev) 1022183724Ssos{ 1023183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 1024183724Ssos struct ata_channel *ch = device_get_softc(dev); 1025183724Ssos 1026183724Ssos /* note start and stop are not used here */ 1027183724Ssos ch->dma.setprd = ata_ahci_dmasetprd; 1028195439Smav ch->dma.max_iosize = (ATA_AHCI_DMA_ENTRIES - 1) * PAGE_SIZE; 1029183724Ssos if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_64BIT) 1030183724Ssos ch->dma.max_address = BUS_SPACE_MAXADDR; 1031216013Smarius ata_dmainit(dev); 1032183724Ssos} 1033183724Ssos 1034183724Ssosstatic int 1035183724Ssosata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *request) 1036183724Ssos{ 1037183724Ssos bzero(ctp->cfis, 64); 1038183724Ssos if (request->flags & ATA_R_ATAPI) { 1039183724Ssos bzero(ctp->acmd, 32); 1040183724Ssos bcopy(request->u.atapi.ccb, ctp->acmd, 16); 1041183724Ssos } 1042183724Ssos return ata_request2fis_h2d(request, &ctp->cfis[0]); 1043183724Ssos} 1044183724Ssos 1045183724SsosATA_DECLARE_DRIVER(ata_ahci); 1046199322Smavstatic device_method_t ata_ahci_ata_methods[] = { 1047199322Smav DEVMETHOD(device_probe, ata_ahci_ata_probe), 1048199322Smav DEVMETHOD(device_attach, ata_ahci_ata_attach), 1049199322Smav DEVMETHOD(device_detach, ata_pci_detach), 1050199322Smav DEVMETHOD(device_suspend, ata_pci_suspend), 1051199322Smav DEVMETHOD(device_resume, ata_pci_resume), 1052199322Smav DEVMETHOD(device_shutdown, bus_generic_shutdown), 1053199322Smav DEVMETHOD(bus_read_ivar, ata_pci_read_ivar), 1054199322Smav DEVMETHOD(bus_write_ivar, ata_pci_write_ivar), 1055199322Smav DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), 1056199322Smav DEVMETHOD(bus_release_resource, ata_pci_release_resource), 1057199322Smav DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 1058199322Smav DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1059199322Smav DEVMETHOD(bus_setup_intr, ata_pci_setup_intr), 1060199322Smav DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr), 1061233717Smarius DEVMETHOD_END 1062199322Smav}; 1063199322Smavstatic driver_t ata_ahci_ata_driver = { 1064199322Smav "atapci", 1065199322Smav ata_ahci_ata_methods, 1066199322Smav sizeof(struct ata_pci_controller) 1067199322Smav}; 1068233717SmariusDRIVER_MODULE(ata_ahci_ata, atapci, ata_ahci_ata_driver, ata_pci_devclass, 1069233717Smarius NULL, NULL); 1070