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 */ 54183724Ssosstatic int ata_intel_chipinit(device_t dev); 55224270Smavstatic int ata_intel_chipdeinit(device_t dev); 56188765Smavstatic int ata_intel_ch_attach(device_t dev); 57183724Ssosstatic void ata_intel_reset(device_t dev); 58200171Smavstatic int ata_intel_old_setmode(device_t dev, int target, int mode); 59200171Smavstatic int ata_intel_new_setmode(device_t dev, int target, int mode); 60200857Smavstatic int ata_intel_sch_setmode(device_t dev, int target, int mode); 61200171Smavstatic int ata_intel_sata_getrev(device_t dev, int target); 62214016Smavstatic int ata_intel_sata_status(device_t dev); 63217774Smavstatic int ata_intel_sata_ahci_read(device_t dev, int port, 64217774Smav int reg, u_int32_t *result); 65214016Smavstatic int ata_intel_sata_cscr_read(device_t dev, int port, 66214016Smav int reg, u_int32_t *result); 67214016Smavstatic int ata_intel_sata_sidpr_read(device_t dev, int port, 68214016Smav int reg, u_int32_t *result); 69217774Smavstatic int ata_intel_sata_ahci_write(device_t dev, int port, 70217774Smav int reg, u_int32_t result); 71214016Smavstatic int ata_intel_sata_cscr_write(device_t dev, int port, 72214016Smav int reg, u_int32_t result); 73214016Smavstatic int ata_intel_sata_sidpr_write(device_t dev, int port, 74214016Smav int reg, u_int32_t result); 75252203Smavstatic int ata_intel_sata_sidpr_test(device_t dev); 76188765Smavstatic int ata_intel_31244_ch_attach(device_t dev); 77188769Smavstatic int ata_intel_31244_ch_detach(device_t dev); 78183724Ssosstatic int ata_intel_31244_status(device_t dev); 79183724Ssosstatic void ata_intel_31244_tf_write(struct ata_request *request); 80183724Ssosstatic void ata_intel_31244_reset(device_t dev); 81183724Ssos 82183724Ssos/* misc defines */ 83183724Ssos#define INTEL_AHCI 1 84214016Smav#define INTEL_ICH5 2 85214016Smav#define INTEL_6CH 4 86214016Smav#define INTEL_6CH2 8 87217774Smav#define INTEL_ICH7 16 88183724Ssos 89224270Smavstruct ata_intel_data { 90224270Smav struct mtx lock; 91224270Smav u_char smap[4]; 92224270Smav}; 93224270Smav 94224270Smav#define ATA_INTEL_SMAP(ctlr, ch) \ 95224270Smav &((struct ata_intel_data *)((ctlr)->chipset_data))->smap[(ch)->unit * 2] 96224270Smav#define ATA_INTEL_LOCK(ctlr) \ 97224270Smav mtx_lock(&((struct ata_intel_data *)((ctlr)->chipset_data))->lock) 98224270Smav#define ATA_INTEL_UNLOCK(ctlr) \ 99224270Smav mtx_unlock(&((struct ata_intel_data *)((ctlr)->chipset_data))->lock) 100224270Smav 101183724Ssos/* 102183724Ssos * Intel chipset support functions 103183724Ssos */ 104183724Ssosstatic int 105183724Ssosata_intel_probe(device_t dev) 106183724Ssos{ 107183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 108242625Sdim static const struct ata_chip_id ids[] = 109183724Ssos {{ ATA_I82371FB, 0, 0, 2, ATA_WDMA2, "PIIX" }, 110183724Ssos { ATA_I82371SB, 0, 0, 2, ATA_WDMA2, "PIIX3" }, 111183724Ssos { ATA_I82371AB, 0, 0, 2, ATA_UDMA2, "PIIX4" }, 112183724Ssos { ATA_I82443MX, 0, 0, 2, ATA_UDMA2, "PIIX4" }, 113183724Ssos { ATA_I82451NX, 0, 0, 2, ATA_UDMA2, "PIIX4" }, 114183724Ssos { ATA_I82801AB, 0, 0, 2, ATA_UDMA2, "ICH0" }, 115183724Ssos { ATA_I82801AA, 0, 0, 2, ATA_UDMA4, "ICH" }, 116183724Ssos { ATA_I82372FB, 0, 0, 2, ATA_UDMA4, "ICH" }, 117183724Ssos { ATA_I82801BA, 0, 0, 2, ATA_UDMA5, "ICH2" }, 118183724Ssos { ATA_I82801BA_1, 0, 0, 2, ATA_UDMA5, "ICH2" }, 119183724Ssos { ATA_I82801CA, 0, 0, 2, ATA_UDMA5, "ICH3" }, 120183724Ssos { ATA_I82801CA_1, 0, 0, 2, ATA_UDMA5, "ICH3" }, 121183724Ssos { ATA_I82801DB, 0, 0, 2, ATA_UDMA5, "ICH4" }, 122183724Ssos { ATA_I82801DB_1, 0, 0, 2, ATA_UDMA5, "ICH4" }, 123183724Ssos { ATA_I82801EB, 0, 0, 2, ATA_UDMA5, "ICH5" }, 124214016Smav { ATA_I82801EB_S1, 0, INTEL_ICH5, 2, ATA_SA150, "ICH5" }, 125214016Smav { ATA_I82801EB_R1, 0, INTEL_ICH5, 2, ATA_SA150, "ICH5" }, 126183724Ssos { ATA_I6300ESB, 0, 0, 2, ATA_UDMA5, "6300ESB" }, 127214016Smav { ATA_I6300ESB_S1, 0, INTEL_ICH5, 2, ATA_SA150, "6300ESB" }, 128214016Smav { ATA_I6300ESB_R1, 0, INTEL_ICH5, 2, ATA_SA150, "6300ESB" }, 129183724Ssos { ATA_I82801FB, 0, 0, 2, ATA_UDMA5, "ICH6" }, 130183724Ssos { ATA_I82801FB_S1, 0, INTEL_AHCI, 0, ATA_SA150, "ICH6" }, 131183724Ssos { ATA_I82801FB_R1, 0, INTEL_AHCI, 0, ATA_SA150, "ICH6" }, 132183724Ssos { ATA_I82801FBM, 0, INTEL_AHCI, 0, ATA_SA150, "ICH6M" }, 133183724Ssos { ATA_I82801GB, 0, 0, 1, ATA_UDMA5, "ICH7" }, 134217774Smav { ATA_I82801GB_S1, 0, INTEL_ICH7, 0, ATA_SA300, "ICH7" }, 135217774Smav { ATA_I82801GB_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH7" }, 136183724Ssos { ATA_I82801GB_AH, 0, INTEL_AHCI, 0, ATA_SA300, "ICH7" }, 137217774Smav { ATA_I82801GBM_S1, 0, INTEL_ICH7, 0, ATA_SA150, "ICH7M" }, 138217774Smav { ATA_I82801GBM_R1, 0, INTEL_AHCI, 0, ATA_SA150, "ICH7M" }, 139193205Sdelphij { ATA_I82801GBM_AH, 0, INTEL_AHCI, 0, ATA_SA150, "ICH7M" }, 140183724Ssos { ATA_I63XXESB2, 0, 0, 1, ATA_UDMA5, "63XXESB2" }, 141214016Smav { ATA_I63XXESB2_S1, 0, 0, 0, ATA_SA300, "63XXESB2" }, 142183724Ssos { ATA_I63XXESB2_S2, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" }, 143183724Ssos { ATA_I63XXESB2_R1, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" }, 144183724Ssos { ATA_I63XXESB2_R2, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" }, 145214016Smav { ATA_I82801HB_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH8" }, 146214016Smav { ATA_I82801HB_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH8" }, 147183724Ssos { ATA_I82801HB_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" }, 148183724Ssos { ATA_I82801HB_AH4, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" }, 149183724Ssos { ATA_I82801HB_AH6, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" }, 150183724Ssos { ATA_I82801HBM, 0, 0, 1, ATA_UDMA5, "ICH8M" }, 151214016Smav { ATA_I82801HBM_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH8M" }, 152183724Ssos { ATA_I82801HBM_S2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8M" }, 153183724Ssos { ATA_I82801HBM_S3, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8M" }, 154214016Smav { ATA_I82801IB_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH9" }, 155214016Smav { ATA_I82801IB_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH9" }, 156220920Smav { ATA_I82801IB_S3, 0, INTEL_6CH2, 0, ATA_SA300, "ICH9" }, 157183724Ssos { ATA_I82801IB_AH4, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" }, 158183724Ssos { ATA_I82801IB_AH6, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" }, 159183724Ssos { ATA_I82801IB_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" }, 160228497Smav { ATA_I82801IBM_S1, 0, INTEL_6CH2, 0, ATA_SA300, "ICH9M" }, 161228497Smav { ATA_I82801IBM_AH, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9M" }, 162228497Smav { ATA_I82801IBM_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9M" }, 163228497Smav { ATA_I82801IBM_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH9M" }, 164214016Smav { ATA_I82801JIB_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH10" }, 165183724Ssos { ATA_I82801JIB_AH, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, 166183724Ssos { ATA_I82801JIB_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, 167214016Smav { ATA_I82801JIB_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH10" }, 168214016Smav { ATA_I82801JD_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH10" }, 169183724Ssos { ATA_I82801JD_AH, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, 170183724Ssos { ATA_I82801JD_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, 171214016Smav { ATA_I82801JD_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH10" }, 172214016Smav { ATA_I82801JI_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH10" }, 173199074Smav { ATA_I82801JI_AH, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, 174199074Smav { ATA_I82801JI_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, 175214016Smav { ATA_I82801JI_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH10" }, 176214016Smav { ATA_5Series_S1, 0, INTEL_6CH, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 177214016Smav { ATA_5Series_S2, 0, INTEL_6CH2, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 178211920Smav { ATA_5Series_AH1, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 179211920Smav { ATA_5Series_AH2, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 180211920Smav { ATA_5Series_R1, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 181214016Smav { ATA_5Series_S3, 0, INTEL_6CH2, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 182214016Smav { ATA_5Series_S4, 0, INTEL_6CH, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 183211920Smav { ATA_5Series_AH3, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 184211920Smav { ATA_5Series_R2, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 185214016Smav { ATA_5Series_S5, 0, INTEL_6CH2, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 186214016Smav { ATA_5Series_S6, 0, INTEL_6CH, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 187211920Smav { ATA_5Series_AH4, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, 188214016Smav { ATA_CPT_S1, 0, INTEL_6CH, 0, ATA_SA300, "Cougar Point" }, 189214016Smav { ATA_CPT_S2, 0, INTEL_6CH, 0, ATA_SA300, "Cougar Point" }, 190211920Smav { ATA_CPT_AH1, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, 191211920Smav { ATA_CPT_AH2, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, 192211920Smav { ATA_CPT_R1, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, 193211920Smav { ATA_CPT_R2, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, 194214016Smav { ATA_CPT_S3, 0, INTEL_6CH2, 0, ATA_SA300, "Cougar Point" }, 195214016Smav { ATA_CPT_S4, 0, INTEL_6CH2, 0, ATA_SA300, "Cougar Point" }, 196218149Sjfv { ATA_PBG_S1, 0, INTEL_6CH, 0, ATA_SA300, "Patsburg" }, 197218149Sjfv { ATA_PBG_AH1, 0, INTEL_AHCI, 0, ATA_SA300, "Patsburg" }, 198218149Sjfv { ATA_PBG_R1, 0, INTEL_AHCI, 0, ATA_SA300, "Patsburg" }, 199218149Sjfv { ATA_PBG_R2, 0, INTEL_AHCI, 0, ATA_SA300, "Patsburg" }, 200229671Sjimharris { ATA_PBG_R3, 0, INTEL_AHCI, 0, ATA_SA300, "Patsburg" }, 201218149Sjfv { ATA_PBG_S2, 0, INTEL_6CH2, 0, ATA_SA300, "Patsburg" }, 202221789Sjfv { ATA_PPT_S1, 0, INTEL_6CH, 0, ATA_SA300, "Panther Point" }, 203221789Sjfv { ATA_PPT_S2, 0, INTEL_6CH, 0, ATA_SA300, "Panther Point" }, 204221789Sjfv { ATA_PPT_AH1, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, 205221789Sjfv { ATA_PPT_AH2, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, 206221789Sjfv { ATA_PPT_R1, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, 207221789Sjfv { ATA_PPT_R2, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, 208221789Sjfv { ATA_PPT_R3, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, 209221789Sjfv { ATA_PPT_R4, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, 210221789Sjfv { ATA_PPT_S3, 0, INTEL_6CH2, 0, ATA_SA300, "Panther Point" }, 211221789Sjfv { ATA_PPT_S4, 0, INTEL_6CH2, 0, ATA_SA300, "Panther Point" }, 212221789Sjfv { ATA_PPT_R5, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, 213221789Sjfv { ATA_PPT_R6, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, 214244983Sjfv { ATA_LPT_S1, 0, INTEL_6CH, 0, ATA_SA300, "Lynx Point" }, 215244983Sjfv { ATA_LPT_S2, 0, INTEL_6CH, 0, ATA_SA300, "Lynx Point" }, 216244983Sjfv { ATA_LPT_AH1, 0, INTEL_AHCI, 0, ATA_SA300, "Lynx Point" }, 217244983Sjfv { ATA_LPT_AH2, 0, INTEL_AHCI, 0, ATA_SA300, "Lynx Point" }, 218244983Sjfv { ATA_LPT_R1, 0, INTEL_AHCI, 0, ATA_SA300, "Lynx Point" }, 219244983Sjfv { ATA_LPT_R2, 0, INTEL_AHCI, 0, ATA_SA300, "Lynx Point" }, 220244983Sjfv { ATA_LPT_R3, 0, INTEL_AHCI, 0, ATA_SA300, "Lynx Point" }, 221244983Sjfv { ATA_LPT_R4, 0, INTEL_AHCI, 0, ATA_SA300, "Lynx Point" }, 222244983Sjfv { ATA_LPT_S3, 0, INTEL_6CH2, 0, ATA_SA300, "Lynx Point" }, 223244983Sjfv { ATA_LPT_S4, 0, INTEL_6CH2, 0, ATA_SA300, "Lynx Point" }, 224244983Sjfv { ATA_LPT_R5, 0, INTEL_AHCI, 0, ATA_SA300, "Lynx Point" }, 225244983Sjfv { ATA_LPT_R6, 0, INTEL_AHCI, 0, ATA_SA300, "Lynx Point" }, 226183724Ssos { ATA_I31244, 0, 0, 2, ATA_SA150, "31244" }, 227200857Smav { ATA_ISCH, 0, 0, 1, ATA_UDMA5, "SCH" }, 228218140Sjfv { ATA_DH89XXCC, 0, INTEL_AHCI, 0, ATA_SA300, "DH89xxCC" }, 229253475Sjfv { ATA_COLETOCRK_S1, 0, INTEL_6CH2, 0, ATA_SA300, "COLETOCRK" }, 230253475Sjfv { ATA_COLETOCRK_S2, 0, INTEL_6CH2, 0, ATA_SA300, "COLETOCRK" }, 231253475Sjfv { ATA_COLETOCRK_AH1,0, INTEL_AHCI, 0, ATA_SA300, "COLETOCRK" }, 232183724Ssos { 0, 0, 0, 0, 0, 0}}; 233183724Ssos 234183724Ssos if (pci_get_vendor(dev) != ATA_INTEL_ID) 235183724Ssos return ENXIO; 236183724Ssos 237183724Ssos if (!(ctlr->chip = ata_match_chip(dev, ids))) 238183724Ssos return ENXIO; 239183724Ssos 240183724Ssos ata_set_desc(dev); 241183724Ssos ctlr->chipinit = ata_intel_chipinit; 242224270Smav ctlr->chipdeinit = ata_intel_chipdeinit; 243194893Smav return (BUS_PROBE_DEFAULT); 244183724Ssos} 245183724Ssos 246183724Ssosstatic int 247183724Ssosata_intel_chipinit(device_t dev) 248183724Ssos{ 249183724Ssos struct ata_pci_controller *ctlr = device_get_softc(dev); 250224270Smav struct ata_intel_data *data; 251183724Ssos 252183724Ssos if (ata_setup_interrupt(dev, ata_generic_intr)) 253183724Ssos return ENXIO; 254183724Ssos 255224270Smav data = malloc(sizeof(struct ata_intel_data), M_ATAPCI, M_WAITOK | M_ZERO); 256224270Smav mtx_init(&data->lock, "Intel SATA lock", NULL, MTX_DEF); 257224270Smav ctlr->chipset_data = (void *)data; 258214016Smav 259183724Ssos /* good old PIIX needs special treatment (not implemented) */ 260183724Ssos if (ctlr->chip->chipid == ATA_I82371FB) { 261183724Ssos ctlr->setmode = ata_intel_old_setmode; 262183724Ssos } 263183724Ssos 264183724Ssos /* the intel 31244 needs special care if in DPA mode */ 265183724Ssos else if (ctlr->chip->chipid == ATA_I31244) { 266183724Ssos if (pci_get_subclass(dev) != PCIS_STORAGE_IDE) { 267183724Ssos ctlr->r_type2 = SYS_RES_MEMORY; 268183724Ssos ctlr->r_rid2 = PCIR_BAR(0); 269183724Ssos if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, 270183724Ssos &ctlr->r_rid2, 271183724Ssos RF_ACTIVE))) 272183724Ssos return ENXIO; 273183724Ssos ctlr->channels = 4; 274188765Smav ctlr->ch_attach = ata_intel_31244_ch_attach; 275188769Smav ctlr->ch_detach = ata_intel_31244_ch_detach; 276183724Ssos ctlr->reset = ata_intel_31244_reset; 277183724Ssos } 278183724Ssos ctlr->setmode = ata_sata_setmode; 279200171Smav ctlr->getrev = ata_sata_getrev; 280183724Ssos } 281200857Smav /* SCH */ 282200857Smav else if (ctlr->chip->chipid == ATA_ISCH) { 283200857Smav ctlr->channels = 1; 284200857Smav ctlr->ch_attach = ata_intel_ch_attach; 285200857Smav ctlr->ch_detach = ata_pci_ch_detach; 286200857Smav ctlr->setmode = ata_intel_sch_setmode; 287200857Smav } 288183724Ssos /* non SATA intel chips goes here */ 289183724Ssos else if (ctlr->chip->max_dma < ATA_SA150) { 290183724Ssos ctlr->channels = ctlr->chip->cfg2; 291188765Smav ctlr->ch_attach = ata_intel_ch_attach; 292188769Smav ctlr->ch_detach = ata_pci_ch_detach; 293183724Ssos ctlr->setmode = ata_intel_new_setmode; 294183724Ssos } 295183724Ssos 296183724Ssos /* SATA parts can be either compat or AHCI */ 297183724Ssos else { 298183724Ssos /* force all ports active "the legacy way" */ 299183724Ssos pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f, 2); 300183724Ssos 301188765Smav ctlr->ch_attach = ata_intel_ch_attach; 302188769Smav ctlr->ch_detach = ata_pci_ch_detach; 303183724Ssos ctlr->reset = ata_intel_reset; 304183724Ssos 305183724Ssos /* 306183724Ssos * if we have AHCI capability and AHCI or RAID mode enabled 307183724Ssos * in BIOS we try for AHCI mode 308183724Ssos */ 309214016Smav if ((ctlr->chip->cfg1 & INTEL_AHCI) && 310183724Ssos (pci_read_config(dev, 0x90, 1) & 0xc0) && 311183724Ssos (ata_ahci_chipinit(dev) != ENXIO)) 312183724Ssos return 0; 313217774Smav 314217774Smav /* BAR(5) may point to SATA interface registers */ 315217774Smav if ((ctlr->chip->cfg1 & INTEL_ICH7)) { 316217774Smav ctlr->r_type2 = SYS_RES_MEMORY; 317217774Smav ctlr->r_rid2 = PCIR_BAR(5); 318217774Smav ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, 319217774Smav &ctlr->r_rid2, RF_ACTIVE); 320217774Smav if (ctlr->r_res2 != NULL) { 321217774Smav /* Set SCRAE bit to enable registers access. */ 322217774Smav pci_write_config(dev, 0x94, 323217774Smav pci_read_config(dev, 0x94, 4) | (1 << 9), 4); 324217774Smav /* Set Ports Implemented register bits. */ 325217774Smav ATA_OUTL(ctlr->r_res2, 0x0C, 326217774Smav ATA_INL(ctlr->r_res2, 0x0C) | 0xf); 327217774Smav } 328223097Smav /* Skip BAR(5) on ICH8M Apples, system locks up on access. */ 329223097Smav } else if (ctlr->chip->chipid != ATA_I82801HBM_S1 || 330223097Smav pci_get_subvendor(dev) != 0x106b) { 331217774Smav ctlr->r_type2 = SYS_RES_IOPORT; 332217774Smav ctlr->r_rid2 = PCIR_BAR(5); 333217774Smav ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, 334217774Smav &ctlr->r_rid2, RF_ACTIVE); 335217774Smav } 336217774Smav if (ctlr->r_res2 != NULL || 337217774Smav (ctlr->chip->cfg1 & INTEL_ICH5)) 338217774Smav ctlr->getrev = ata_intel_sata_getrev; 339200171Smav ctlr->setmode = ata_sata_setmode; 340183724Ssos } 341183724Ssos return 0; 342183724Ssos} 343183724Ssos 344183724Ssosstatic int 345224270Smavata_intel_chipdeinit(device_t dev) 346224270Smav{ 347224270Smav struct ata_pci_controller *ctlr = device_get_softc(dev); 348224270Smav struct ata_intel_data *data; 349224270Smav 350224270Smav data = ctlr->chipset_data; 351224270Smav mtx_destroy(&data->lock); 352224270Smav free(data, M_ATAPCI); 353224270Smav ctlr->chipset_data = NULL; 354224270Smav return (0); 355224270Smav} 356224270Smav 357224270Smavstatic int 358188765Smavata_intel_ch_attach(device_t dev) 359183724Ssos{ 360214016Smav struct ata_pci_controller *ctlr; 361214016Smav struct ata_channel *ch; 362214016Smav u_char *smap; 363214016Smav u_int map; 364183724Ssos 365214016Smav /* setup the usual register normal pci style */ 366214016Smav if (ata_pci_ch_attach(dev)) 367214016Smav return (ENXIO); 368183724Ssos 369214016Smav ctlr = device_get_softc(device_get_parent(dev)); 370214016Smav ch = device_get_softc(dev); 371183724Ssos 372214016Smav /* if r_res2 is valid it points to SATA interface registers */ 373214016Smav if (ctlr->r_res2) { 374214016Smav ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2; 375214016Smav ch->r_io[ATA_IDX_ADDR].offset = 0x00; 376214016Smav ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2; 377214016Smav ch->r_io[ATA_IDX_DATA].offset = 0x04; 378214016Smav } 379214016Smav 380214016Smav ch->flags |= ATA_ALWAYS_DMASTAT; 381214016Smav if (ctlr->chip->max_dma >= ATA_SA150) { 382224270Smav smap = ATA_INTEL_SMAP(ctlr, ch); 383214016Smav map = pci_read_config(device_get_parent(dev), 0x90, 1); 384214016Smav if (ctlr->chip->cfg1 & INTEL_ICH5) { 385214016Smav map &= 0x07; 386214016Smav if ((map & 0x04) == 0) { 387214016Smav ch->flags |= ATA_SATA; 388214016Smav ch->flags |= ATA_NO_SLAVE; 389214016Smav smap[0] = (map & 0x01) ^ ch->unit; 390214016Smav smap[1] = 0; 391214016Smav } else if ((map & 0x02) == 0 && ch->unit == 0) { 392214016Smav ch->flags |= ATA_SATA; 393214016Smav smap[0] = (map & 0x01) ? 1 : 0; 394214016Smav smap[1] = (map & 0x01) ? 0 : 1; 395214016Smav } else if ((map & 0x02) != 0 && ch->unit == 1) { 396214016Smav ch->flags |= ATA_SATA; 397214016Smav smap[0] = (map & 0x01) ? 1 : 0; 398214016Smav smap[1] = (map & 0x01) ? 0 : 1; 399214016Smav } 400214016Smav } else if (ctlr->chip->cfg1 & INTEL_6CH2) { 401214016Smav ch->flags |= ATA_SATA; 402214016Smav ch->flags |= ATA_NO_SLAVE; 403220920Smav smap[0] = (ch->unit == 0) ? 0 : 1; 404214016Smav smap[1] = 0; 405214016Smav } else { 406214016Smav map &= 0x03; 407214016Smav if (map == 0x00) { 408214016Smav ch->flags |= ATA_SATA; 409214016Smav smap[0] = (ch->unit == 0) ? 0 : 1; 410214016Smav smap[1] = (ch->unit == 0) ? 2 : 3; 411214016Smav } else if (map == 0x02 && ch->unit == 0) { 412214016Smav ch->flags |= ATA_SATA; 413214016Smav smap[0] = 0; 414214016Smav smap[1] = 2; 415214016Smav } else if (map == 0x01 && ch->unit == 1) { 416214016Smav ch->flags |= ATA_SATA; 417214016Smav smap[0] = 1; 418214016Smav smap[1] = 3; 419214016Smav } 420214016Smav } 421214016Smav if (ch->flags & ATA_SATA) { 422214016Smav if ((ctlr->chip->cfg1 & INTEL_ICH5)) { 423214016Smav ch->hw.pm_read = ata_intel_sata_cscr_read; 424214016Smav ch->hw.pm_write = ata_intel_sata_cscr_write; 425214016Smav } else if (ctlr->r_res2) { 426217774Smav if ((ctlr->chip->cfg1 & INTEL_ICH7)) { 427217774Smav ch->hw.pm_read = ata_intel_sata_ahci_read; 428217774Smav ch->hw.pm_write = ata_intel_sata_ahci_write; 429252203Smav } else if (ata_intel_sata_sidpr_test(dev)) { 430217774Smav ch->hw.pm_read = ata_intel_sata_sidpr_read; 431217774Smav ch->hw.pm_write = ata_intel_sata_sidpr_write; 432217774Smav }; 433214016Smav } 434214016Smav if (ch->hw.pm_write != NULL) { 435252203Smav ch->flags |= ATA_PERIODIC_POLL; 436252203Smav ch->hw.status = ata_intel_sata_status; 437214016Smav ata_sata_scr_write(ch, 0, 438214016Smav ATA_SERROR, 0xffffffff); 439214016Smav if ((ch->flags & ATA_NO_SLAVE) == 0) { 440214016Smav ata_sata_scr_write(ch, 1, 441214016Smav ATA_SERROR, 0xffffffff); 442214016Smav } 443214016Smav } 444214016Smav } else 445214016Smav ctlr->setmode = ata_intel_new_setmode; 446214016Smav } else if (ctlr->chip->chipid != ATA_ISCH) 447214016Smav ch->flags |= ATA_CHECKS_CABLE; 448214016Smav return (0); 449183724Ssos} 450183724Ssos 451183724Ssosstatic void 452183724Ssosata_intel_reset(device_t dev) 453183724Ssos{ 454214016Smav device_t parent = device_get_parent(dev); 455214016Smav struct ata_pci_controller *ctlr = device_get_softc(parent); 456214016Smav struct ata_channel *ch = device_get_softc(dev); 457220929Smav int mask, pshift, timeout, devs; 458214016Smav u_char *smap; 459220929Smav uint16_t pcs; 460183724Ssos 461214016Smav /* In combined mode, skip SATA stuff for PATA channel. */ 462214016Smav if ((ch->flags & ATA_SATA) == 0) 463214016Smav return (ata_generic_reset(dev)); 464214016Smav 465214016Smav /* Do hard-reset on respective SATA ports. */ 466224270Smav smap = ATA_INTEL_SMAP(ctlr, ch); 467214016Smav mask = 1 << smap[0]; 468214016Smav if ((ch->flags & ATA_NO_SLAVE) == 0) 469214016Smav mask |= (1 << smap[1]); 470214016Smav pci_write_config(parent, 0x92, 471214016Smav pci_read_config(parent, 0x92, 2) & ~mask, 2); 472214016Smav DELAY(10); 473214016Smav pci_write_config(parent, 0x92, 474214016Smav pci_read_config(parent, 0x92, 2) | mask, 2); 475214016Smav 476214016Smav /* Wait up to 1 sec for "connect well". */ 477214016Smav if (ctlr->chip->cfg1 & (INTEL_6CH | INTEL_6CH2)) 478220929Smav pshift = 8; 479200171Smav else 480220929Smav pshift = 4; 481214016Smav for (timeout = 0; timeout < 100 ; timeout++) { 482220929Smav pcs = (pci_read_config(parent, 0x92, 2) >> pshift) & mask; 483220929Smav if ((pcs == mask) && (ATA_IDX_INB(ch, ATA_STATUS) != 0xff)) 484214016Smav break; 485214016Smav ata_udelay(10000); 486214016Smav } 487183724Ssos 488220929Smav if (bootverbose) 489220929Smav device_printf(dev, "SATA reset: ports status=0x%02x\n", pcs); 490214016Smav /* If any device found, do soft-reset. */ 491214016Smav if (ch->hw.pm_read != NULL) { 492220929Smav devs = ata_sata_phy_reset(dev, 0, 2) ? ATA_ATA_MASTER : 0; 493214016Smav if ((ch->flags & ATA_NO_SLAVE) == 0) 494220929Smav devs |= ata_sata_phy_reset(dev, 1, 2) ? 495220929Smav ATA_ATA_SLAVE : 0; 496220929Smav } else { 497220929Smav devs = (pcs & (1 << smap[0])) ? ATA_ATA_MASTER : 0; 498220929Smav if ((ch->flags & ATA_NO_SLAVE) == 0) 499220929Smav devs |= (pcs & (1 << smap[1])) ? 500220929Smav ATA_ATA_SLAVE : 0; 501220929Smav } 502220929Smav if (devs) { 503220929Smav ata_generic_reset(dev); 504220929Smav /* Reset may give fake slave when only ATAPI master present. */ 505220929Smav ch->devices &= (devs | (devs * ATA_ATAPI_MASTER)); 506214016Smav } else 507214016Smav ch->devices = 0; 508183724Ssos} 509183724Ssos 510200171Smavstatic int 511200171Smavata_intel_old_setmode(device_t dev, int target, int mode) 512183724Ssos{ 513200171Smav device_t parent = device_get_parent(dev); 514200171Smav struct ata_pci_controller *ctlr = device_get_softc(parent); 515200171Smav 516200171Smav mode = min(mode, ctlr->chip->max_dma); 517200171Smav return (mode); 518183724Ssos} 519183724Ssos 520200171Smavstatic int 521200171Smavata_intel_new_setmode(device_t dev, int target, int mode) 522183724Ssos{ 523200171Smav device_t parent = device_get_parent(dev); 524200171Smav struct ata_pci_controller *ctlr = device_get_softc(parent); 525200171Smav struct ata_channel *ch = device_get_softc(dev); 526200171Smav int devno = (ch->unit << 1) + target; 527200171Smav int piomode; 528200171Smav u_int32_t reg40 = pci_read_config(parent, 0x40, 4); 529200171Smav u_int8_t reg44 = pci_read_config(parent, 0x44, 1); 530200171Smav u_int8_t reg48 = pci_read_config(parent, 0x48, 1); 531200171Smav u_int16_t reg4a = pci_read_config(parent, 0x4a, 2); 532200171Smav u_int16_t reg54 = pci_read_config(parent, 0x54, 2); 533200171Smav u_int32_t mask40 = 0, new40 = 0; 534200171Smav u_int8_t mask44 = 0, new44 = 0; 535233282Smarius static const uint8_t timings[] = 536233282Smarius { 0x00, 0x00, 0x10, 0x21, 0x23, 0x00, 0x21, 0x23 }; 537233282Smarius static const uint8_t utimings[] = 538233282Smarius { 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 }; 539183724Ssos 540214016Smav /* In combined mode, skip PATA stuff for SATA channel. */ 541214016Smav if (ch->flags & ATA_SATA) 542214016Smav return (ata_sata_setmode(dev, target, mode)); 543214016Smav 544200171Smav mode = min(mode, ctlr->chip->max_dma); 545209872Smav if (ata_dma_check_80pin && mode > ATA_UDMA2 && 546209872Smav !(reg54 & (0x10 << devno))) { 547200171Smav ata_print_cable(dev, "controller"); 548200171Smav mode = ATA_UDMA2; 549200171Smav } 550200171Smav /* Enable/disable UDMA and set timings. */ 551183724Ssos if (mode >= ATA_UDMA0) { 552200171Smav pci_write_config(parent, 0x48, reg48 | (0x0001 << devno), 2); 553200171Smav pci_write_config(parent, 0x4a, 554200171Smav (reg4a & ~(0x3 << (devno << 2))) | 555200171Smav (utimings[mode & ATA_MODE_MASK] << (devno<<2)), 2); 556200171Smav piomode = ATA_PIO4; 557200171Smav } else { 558200171Smav pci_write_config(parent, 0x48, reg48 & ~(0x0001 << devno), 2); 559200171Smav pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (devno << 2))),2); 560200171Smav piomode = mode; 561183724Ssos } 562183724Ssos reg54 |= 0x0400; 563200171Smav /* Set UDMA reference clock (33/66/133MHz). */ 564200171Smav reg54 &= ~(0x1001 << devno); 565183724Ssos if (mode >= ATA_UDMA5) 566183724Ssos reg54 |= (0x1000 << devno); 567200171Smav else if (mode >= ATA_UDMA3) 568200171Smav reg54 |= (0x1 << devno); 569200171Smav pci_write_config(parent, 0x54, reg54, 2); 570200171Smav /* Allow PIO/WDMA timing controls. */ 571183724Ssos reg40 &= ~0x00ff00ff; 572183724Ssos reg40 |= 0x40774077; 573200171Smav /* Set PIO/WDMA timings. */ 574200171Smav if (target == 0) { 575183724Ssos mask40 = 0x3300; 576200171Smav new40 = timings[ata_mode2idx(piomode)] << 8; 577200171Smav } else { 578183724Ssos mask44 = 0x0f; 579200171Smav new44 = ((timings[ata_mode2idx(piomode)] & 0x30) >> 2) | 580200171Smav (timings[ata_mode2idx(piomode)] & 0x03); 581183724Ssos } 582183724Ssos if (ch->unit) { 583183724Ssos mask40 <<= 16; 584183724Ssos new40 <<= 16; 585183724Ssos mask44 <<= 4; 586183724Ssos new44 <<= 4; 587183724Ssos } 588200171Smav pci_write_config(parent, 0x40, (reg40 & ~mask40) | new40, 4); 589200171Smav pci_write_config(parent, 0x44, (reg44 & ~mask44) | new44, 1); 590200171Smav return (mode); 591183724Ssos} 592183724Ssos 593200171Smavstatic int 594200857Smavata_intel_sch_setmode(device_t dev, int target, int mode) 595200857Smav{ 596200857Smav device_t parent = device_get_parent(dev); 597200857Smav struct ata_pci_controller *ctlr = device_get_softc(parent); 598200857Smav u_int8_t dtim = 0x80 + (target << 2); 599200857Smav u_int32_t tim = pci_read_config(parent, dtim, 4); 600200857Smav int piomode; 601200857Smav 602200857Smav mode = min(mode, ctlr->chip->max_dma); 603200857Smav if (mode >= ATA_UDMA0) { 604200857Smav tim |= (0x1 << 31); 605200857Smav tim &= ~(0x7 << 16); 606200857Smav tim |= ((mode & ATA_MODE_MASK) << 16); 607200857Smav piomode = ATA_PIO4; 608200857Smav } else if (mode >= ATA_WDMA0) { 609200857Smav tim &= ~(0x1 << 31); 610200857Smav tim &= ~(0x3 << 8); 611200857Smav tim |= ((mode & ATA_MODE_MASK) << 8); 612200857Smav piomode = (mode == ATA_WDMA0) ? ATA_PIO0 : 613200857Smav (mode == ATA_WDMA1) ? ATA_PIO3 : ATA_PIO4; 614200857Smav } else 615200857Smav piomode = mode; 616200857Smav tim &= ~(0x7); 617200857Smav tim |= (piomode & 0x7); 618200857Smav pci_write_config(parent, dtim, tim, 4); 619200857Smav return (mode); 620200857Smav} 621200857Smav 622200857Smavstatic int 623200171Smavata_intel_sata_getrev(device_t dev, int target) 624183724Ssos{ 625200171Smav struct ata_channel *ch = device_get_softc(dev); 626214016Smav uint32_t status; 627183724Ssos 628214016Smav if (ata_sata_scr_read(ch, target, ATA_SSTATUS, &status) == 0) 629214016Smav return ((status & 0x0f0) >> 4); 630214016Smav return (0xff); 631183724Ssos} 632183724Ssos 633183724Ssosstatic int 634214016Smavata_intel_sata_status(device_t dev) 635214016Smav{ 636214016Smav struct ata_channel *ch = device_get_softc(dev); 637214016Smav 638214016Smav ata_sata_phy_check_events(dev, 0); 639214016Smav if ((ch->flags & ATA_NO_SLAVE) == 0) 640214016Smav ata_sata_phy_check_events(dev, 1); 641214016Smav 642214016Smav return ata_pci_status(dev); 643214016Smav} 644214016Smav 645214016Smavstatic int 646217774Smavata_intel_sata_ahci_read(device_t dev, int port, int reg, u_int32_t *result) 647217774Smav{ 648217774Smav struct ata_pci_controller *ctlr; 649217774Smav struct ata_channel *ch; 650217774Smav device_t parent; 651217774Smav u_char *smap; 652217774Smav int offset; 653217774Smav 654217774Smav parent = device_get_parent(dev); 655217774Smav ctlr = device_get_softc(parent); 656217774Smav ch = device_get_softc(dev); 657217774Smav port = (port == 1) ? 1 : 0; 658224270Smav smap = ATA_INTEL_SMAP(ctlr, ch); 659217774Smav offset = 0x100 + smap[port] * 0x80; 660217774Smav switch (reg) { 661217774Smav case ATA_SSTATUS: 662217774Smav reg = 0x28; 663217774Smav break; 664217774Smav case ATA_SCONTROL: 665217774Smav reg = 0x2c; 666217774Smav break; 667217774Smav case ATA_SERROR: 668217774Smav reg = 0x30; 669217774Smav break; 670217774Smav default: 671217774Smav return (EINVAL); 672217774Smav } 673217774Smav *result = ATA_INL(ctlr->r_res2, offset + reg); 674217774Smav return (0); 675217774Smav} 676217774Smav 677217774Smavstatic int 678214016Smavata_intel_sata_cscr_read(device_t dev, int port, int reg, u_int32_t *result) 679214016Smav{ 680214016Smav struct ata_pci_controller *ctlr; 681214016Smav struct ata_channel *ch; 682214016Smav device_t parent; 683214016Smav u_char *smap; 684214016Smav 685214016Smav parent = device_get_parent(dev); 686214016Smav ctlr = device_get_softc(parent); 687214016Smav ch = device_get_softc(dev); 688224270Smav smap = ATA_INTEL_SMAP(ctlr, ch); 689214016Smav port = (port == 1) ? 1 : 0; 690214016Smav switch (reg) { 691214016Smav case ATA_SSTATUS: 692214016Smav reg = 0; 693214016Smav break; 694214016Smav case ATA_SERROR: 695214016Smav reg = 1; 696214016Smav break; 697214016Smav case ATA_SCONTROL: 698214016Smav reg = 2; 699214016Smav break; 700214016Smav default: 701214016Smav return (EINVAL); 702214016Smav } 703224270Smav ATA_INTEL_LOCK(ctlr); 704214016Smav pci_write_config(parent, 0xa0, 705214016Smav 0x50 + smap[port] * 0x10 + reg * 4, 4); 706214016Smav *result = pci_read_config(parent, 0xa4, 4); 707224270Smav ATA_INTEL_UNLOCK(ctlr); 708214016Smav return (0); 709214016Smav} 710214016Smav 711214016Smavstatic int 712214016Smavata_intel_sata_sidpr_read(device_t dev, int port, int reg, u_int32_t *result) 713214016Smav{ 714214016Smav struct ata_pci_controller *ctlr; 715214016Smav struct ata_channel *ch; 716214016Smav device_t parent; 717214016Smav 718214016Smav parent = device_get_parent(dev); 719214016Smav ctlr = device_get_softc(parent); 720214016Smav ch = device_get_softc(dev); 721214016Smav port = (port == 1) ? 1 : 0; 722214016Smav switch (reg) { 723214016Smav case ATA_SSTATUS: 724214016Smav reg = 0; 725214016Smav break; 726214016Smav case ATA_SCONTROL: 727214016Smav reg = 1; 728214016Smav break; 729214016Smav case ATA_SERROR: 730214016Smav reg = 2; 731214016Smav break; 732214016Smav default: 733214016Smav return (EINVAL); 734214016Smav } 735224270Smav ATA_INTEL_LOCK(ctlr); 736214016Smav ATA_IDX_OUTL(ch, ATA_IDX_ADDR, ((ch->unit * 2 + port) << 8) + reg); 737214016Smav *result = ATA_IDX_INL(ch, ATA_IDX_DATA); 738224270Smav ATA_INTEL_UNLOCK(ctlr); 739214016Smav return (0); 740214016Smav} 741214016Smav 742214016Smavstatic int 743217774Smavata_intel_sata_ahci_write(device_t dev, int port, int reg, u_int32_t value) 744217774Smav{ 745217774Smav struct ata_pci_controller *ctlr; 746217774Smav struct ata_channel *ch; 747217774Smav device_t parent; 748217774Smav u_char *smap; 749217774Smav int offset; 750217774Smav 751217774Smav parent = device_get_parent(dev); 752217774Smav ctlr = device_get_softc(parent); 753217774Smav ch = device_get_softc(dev); 754217774Smav port = (port == 1) ? 1 : 0; 755224270Smav smap = ATA_INTEL_SMAP(ctlr, ch); 756217774Smav offset = 0x100 + smap[port] * 0x80; 757217774Smav switch (reg) { 758217774Smav case ATA_SSTATUS: 759217774Smav reg = 0x28; 760217774Smav break; 761217774Smav case ATA_SCONTROL: 762217774Smav reg = 0x2c; 763217774Smav break; 764217774Smav case ATA_SERROR: 765217774Smav reg = 0x30; 766217774Smav break; 767217774Smav default: 768217774Smav return (EINVAL); 769217774Smav } 770217774Smav ATA_OUTL(ctlr->r_res2, offset + reg, value); 771217774Smav return (0); 772217774Smav} 773217774Smav 774217774Smavstatic int 775214016Smavata_intel_sata_cscr_write(device_t dev, int port, int reg, u_int32_t value) 776214016Smav{ 777214016Smav struct ata_pci_controller *ctlr; 778214016Smav struct ata_channel *ch; 779214016Smav device_t parent; 780214016Smav u_char *smap; 781214016Smav 782214016Smav parent = device_get_parent(dev); 783214016Smav ctlr = device_get_softc(parent); 784214016Smav ch = device_get_softc(dev); 785224270Smav smap = ATA_INTEL_SMAP(ctlr, ch); 786214016Smav port = (port == 1) ? 1 : 0; 787214016Smav switch (reg) { 788214016Smav case ATA_SSTATUS: 789214016Smav reg = 0; 790214016Smav break; 791214016Smav case ATA_SERROR: 792214016Smav reg = 1; 793214016Smav break; 794214016Smav case ATA_SCONTROL: 795214016Smav reg = 2; 796214016Smav break; 797214016Smav default: 798214016Smav return (EINVAL); 799214016Smav } 800224270Smav ATA_INTEL_LOCK(ctlr); 801214016Smav pci_write_config(parent, 0xa0, 802214016Smav 0x50 + smap[port] * 0x10 + reg * 4, 4); 803214016Smav pci_write_config(parent, 0xa4, value, 4); 804224270Smav ATA_INTEL_UNLOCK(ctlr); 805214016Smav return (0); 806214016Smav} 807214016Smav 808214016Smavstatic int 809214016Smavata_intel_sata_sidpr_write(device_t dev, int port, int reg, u_int32_t value) 810214016Smav{ 811214016Smav struct ata_pci_controller *ctlr; 812214016Smav struct ata_channel *ch; 813214016Smav device_t parent; 814214016Smav 815214016Smav parent = device_get_parent(dev); 816214016Smav ctlr = device_get_softc(parent); 817214016Smav ch = device_get_softc(dev); 818214016Smav port = (port == 1) ? 1 : 0; 819214016Smav switch (reg) { 820214016Smav case ATA_SSTATUS: 821214016Smav reg = 0; 822214016Smav break; 823214016Smav case ATA_SCONTROL: 824214016Smav reg = 1; 825214016Smav break; 826214016Smav case ATA_SERROR: 827214016Smav reg = 2; 828214016Smav break; 829214016Smav default: 830214016Smav return (EINVAL); 831214016Smav } 832224270Smav ATA_INTEL_LOCK(ctlr); 833214016Smav ATA_IDX_OUTL(ch, ATA_IDX_ADDR, ((ch->unit * 2 + port) << 8) + reg); 834214016Smav ATA_IDX_OUTL(ch, ATA_IDX_DATA, value); 835224270Smav ATA_INTEL_UNLOCK(ctlr); 836214016Smav return (0); 837214016Smav} 838214016Smav 839214016Smavstatic int 840252203Smavata_intel_sata_sidpr_test(device_t dev) 841252203Smav{ 842252203Smav struct ata_channel *ch = device_get_softc(dev); 843252203Smav int port; 844252203Smav uint32_t val; 845252203Smav 846252203Smav port = (ch->flags & ATA_NO_SLAVE) ? 0 : 1; 847252203Smav for (; port >= 0; port--) { 848252203Smav ata_intel_sata_sidpr_read(dev, port, ATA_SCONTROL, &val); 849252203Smav if ((val & ATA_SC_IPM_MASK) == 850252203Smav (ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)) 851252203Smav return (1); 852252203Smav val |= ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER; 853252203Smav ata_intel_sata_sidpr_write(dev, port, ATA_SCONTROL, val); 854252203Smav ata_intel_sata_sidpr_read(dev, port, ATA_SCONTROL, &val); 855252203Smav if ((val & ATA_SC_IPM_MASK) == 856252203Smav (ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)) 857252203Smav return (1); 858252203Smav } 859252203Smav if (bootverbose) 860252203Smav device_printf(dev, 861252203Smav "SControl registers are not functional: %08x\n", val); 862252203Smav return (0); 863252203Smav} 864252203Smav 865252203Smavstatic int 866188765Smavata_intel_31244_ch_attach(device_t dev) 867183724Ssos{ 868183724Ssos struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 869183724Ssos struct ata_channel *ch = device_get_softc(dev); 870183724Ssos int i; 871183724Ssos int ch_offset; 872183724Ssos 873188769Smav ata_pci_dmainit(dev); 874188769Smav 875183724Ssos ch_offset = 0x200 + ch->unit * 0x200; 876183724Ssos 877183724Ssos for (i = ATA_DATA; i < ATA_MAX_RES; i++) 878183724Ssos ch->r_io[i].res = ctlr->r_res2; 879183724Ssos 880183724Ssos /* setup ATA registers */ 881183724Ssos ch->r_io[ATA_DATA].offset = ch_offset + 0x00; 882183724Ssos ch->r_io[ATA_FEATURE].offset = ch_offset + 0x06; 883183724Ssos ch->r_io[ATA_COUNT].offset = ch_offset + 0x08; 884183724Ssos ch->r_io[ATA_SECTOR].offset = ch_offset + 0x0c; 885183724Ssos ch->r_io[ATA_CYL_LSB].offset = ch_offset + 0x10; 886183724Ssos ch->r_io[ATA_CYL_MSB].offset = ch_offset + 0x14; 887183724Ssos ch->r_io[ATA_DRIVE].offset = ch_offset + 0x18; 888183724Ssos ch->r_io[ATA_COMMAND].offset = ch_offset + 0x1d; 889183724Ssos ch->r_io[ATA_ERROR].offset = ch_offset + 0x04; 890183724Ssos ch->r_io[ATA_STATUS].offset = ch_offset + 0x1c; 891183724Ssos ch->r_io[ATA_ALTSTAT].offset = ch_offset + 0x28; 892183724Ssos ch->r_io[ATA_CONTROL].offset = ch_offset + 0x29; 893183724Ssos 894183724Ssos /* setup DMA registers */ 895183724Ssos ch->r_io[ATA_SSTATUS].offset = ch_offset + 0x100; 896183724Ssos ch->r_io[ATA_SERROR].offset = ch_offset + 0x104; 897183724Ssos ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x108; 898183724Ssos 899183724Ssos /* setup SATA registers */ 900183724Ssos ch->r_io[ATA_BMCMD_PORT].offset = ch_offset + 0x70; 901183724Ssos ch->r_io[ATA_BMSTAT_PORT].offset = ch_offset + 0x72; 902183724Ssos ch->r_io[ATA_BMDTP_PORT].offset = ch_offset + 0x74; 903183724Ssos 904183724Ssos ch->flags |= ATA_NO_SLAVE; 905200171Smav ch->flags |= ATA_SATA; 906183724Ssos ata_pci_hw(dev); 907183724Ssos ch->hw.status = ata_intel_31244_status; 908183724Ssos ch->hw.tf_write = ata_intel_31244_tf_write; 909183724Ssos 910183724Ssos /* enable PHY state change interrupt */ 911183724Ssos ATA_OUTL(ctlr->r_res2, 0x4, 912183724Ssos ATA_INL(ctlr->r_res2, 0x04) | (0x01 << (ch->unit << 3))); 913183724Ssos return 0; 914183724Ssos} 915183724Ssos 916183724Ssosstatic int 917188769Smavata_intel_31244_ch_detach(device_t dev) 918188769Smav{ 919188769Smav 920188769Smav ata_pci_dmafini(dev); 921188769Smav return (0); 922188769Smav} 923188769Smav 924188769Smavstatic int 925183724Ssosata_intel_31244_status(device_t dev) 926183724Ssos{ 927183724Ssos /* do we have any PHY events ? */ 928214016Smav ata_sata_phy_check_events(dev, -1); 929183724Ssos 930183724Ssos /* any drive action to take care of ? */ 931183724Ssos return ata_pci_status(dev); 932183724Ssos} 933183724Ssos 934183724Ssosstatic void 935183724Ssosata_intel_31244_tf_write(struct ata_request *request) 936183724Ssos{ 937198717Smav struct ata_channel *ch = device_get_softc(request->parent); 938183724Ssos 939198717Smav if (request->flags & ATA_R_48BIT) { 940183724Ssos ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature); 941183724Ssos ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count); 942183724Ssos ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) | 943183724Ssos (request->u.ata.lba & 0x00ff)); 944183724Ssos ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) | 945183724Ssos ((request->u.ata.lba >> 8) & 0x00ff)); 946183724Ssos ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) | 947183724Ssos ((request->u.ata.lba >> 16) & 0x00ff)); 948198717Smav ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(request->unit)); 949183724Ssos } 950183724Ssos else { 951183724Ssos ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature); 952183724Ssos ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count); 953183724Ssos ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba); 954183724Ssos ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8); 955183724Ssos ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16); 956183724Ssos ATA_IDX_OUTB(ch, ATA_DRIVE, 957198717Smav ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit) | 958183724Ssos ((request->u.ata.lba >> 24) & 0x0f)); 959183724Ssos } 960183724Ssos} 961183724Ssos 962183724Ssosstatic void 963183724Ssosata_intel_31244_reset(device_t dev) 964183724Ssos{ 965209884Smav struct ata_channel *ch = device_get_softc(dev); 966209884Smav 967190581Smav if (ata_sata_phy_reset(dev, -1, 1)) 968183724Ssos ata_generic_reset(dev); 969209884Smav else 970209884Smav ch->devices = 0; 971183724Ssos} 972183724Ssos 973183724SsosATA_DECLARE_DRIVER(ata_intel); 974183724SsosMODULE_DEPEND(ata_intel, ata_ahci, 1, 1, 1); 975