xref: /freebsd/sys/dev/ata/chipsets/ata-intel.c (revision fdafd315)
113014ca0SSøren Schmidt /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
49a14aa01SUlrich Spörlein  * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
513014ca0SSøren Schmidt  * All rights reserved.
613014ca0SSøren Schmidt  *
713014ca0SSøren Schmidt  * Redistribution and use in source and binary forms, with or without
813014ca0SSøren Schmidt  * modification, are permitted provided that the following conditions
913014ca0SSøren Schmidt  * are met:
1013014ca0SSøren Schmidt  * 1. Redistributions of source code must retain the above copyright
1113014ca0SSøren Schmidt  *    notice, this list of conditions and the following disclaimer,
1213014ca0SSøren Schmidt  *    without modification, immediately at the beginning of the file.
1313014ca0SSøren Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
1413014ca0SSøren Schmidt  *    notice, this list of conditions and the following disclaimer in the
1513014ca0SSøren Schmidt  *    documentation and/or other materials provided with the distribution.
1613014ca0SSøren Schmidt  *
1713014ca0SSøren Schmidt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1813014ca0SSøren Schmidt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1913014ca0SSøren Schmidt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2013014ca0SSøren Schmidt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2113014ca0SSøren Schmidt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2213014ca0SSøren Schmidt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2313014ca0SSøren Schmidt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2413014ca0SSøren Schmidt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2513014ca0SSøren Schmidt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2613014ca0SSøren Schmidt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2713014ca0SSøren Schmidt  */
2813014ca0SSøren Schmidt 
2913014ca0SSøren Schmidt #include <sys/param.h>
3013014ca0SSøren Schmidt #include <sys/module.h>
3113014ca0SSøren Schmidt #include <sys/systm.h>
3213014ca0SSøren Schmidt #include <sys/kernel.h>
3313014ca0SSøren Schmidt #include <sys/ata.h>
3413014ca0SSøren Schmidt #include <sys/bus.h>
3513014ca0SSøren Schmidt #include <sys/endian.h>
3613014ca0SSøren Schmidt #include <sys/malloc.h>
3713014ca0SSøren Schmidt #include <sys/lock.h>
3813014ca0SSøren Schmidt #include <sys/mutex.h>
3913014ca0SSøren Schmidt #include <sys/sema.h>
4013014ca0SSøren Schmidt #include <sys/taskqueue.h>
4113014ca0SSøren Schmidt #include <vm/uma.h>
4213014ca0SSøren Schmidt #include <machine/stdarg.h>
4313014ca0SSøren Schmidt #include <machine/resource.h>
4413014ca0SSøren Schmidt #include <machine/bus.h>
4513014ca0SSøren Schmidt #include <sys/rman.h>
4613014ca0SSøren Schmidt #include <dev/pci/pcivar.h>
4713014ca0SSøren Schmidt #include <dev/pci/pcireg.h>
4813014ca0SSøren Schmidt #include <dev/ata/ata-all.h>
4913014ca0SSøren Schmidt #include <dev/ata/ata-pci.h>
5013014ca0SSøren Schmidt #include <ata_if.h>
5113014ca0SSøren Schmidt 
5213014ca0SSøren Schmidt /* local prototypes */
5313014ca0SSøren Schmidt static int ata_intel_chipinit(device_t dev);
54dd60e051SAlexander Motin static int ata_intel_chipdeinit(device_t dev);
5504ff88ceSAlexander Motin static int ata_intel_ch_attach(device_t dev);
5613014ca0SSøren Schmidt static void ata_intel_reset(device_t dev);
57066f913aSAlexander Motin static int ata_intel_old_setmode(device_t dev, int target, int mode);
58066f913aSAlexander Motin static int ata_intel_new_setmode(device_t dev, int target, int mode);
597aab51b3SAlexander Motin static int ata_intel_sch_setmode(device_t dev, int target, int mode);
60066f913aSAlexander Motin static int ata_intel_sata_getrev(device_t dev, int target);
61bda55b6aSAlexander Motin static int ata_intel_sata_status(device_t dev);
62f1bfc8abSAlexander Motin static int ata_intel_sata_ahci_read(device_t dev, int port,
63f1bfc8abSAlexander Motin     int reg, u_int32_t *result);
64bda55b6aSAlexander Motin static int ata_intel_sata_cscr_read(device_t dev, int port,
65bda55b6aSAlexander Motin     int reg, u_int32_t *result);
66bda55b6aSAlexander Motin static int ata_intel_sata_sidpr_read(device_t dev, int port,
67bda55b6aSAlexander Motin     int reg, u_int32_t *result);
68f1bfc8abSAlexander Motin static int ata_intel_sata_ahci_write(device_t dev, int port,
69f1bfc8abSAlexander Motin     int reg, u_int32_t result);
70bda55b6aSAlexander Motin static int ata_intel_sata_cscr_write(device_t dev, int port,
71bda55b6aSAlexander Motin     int reg, u_int32_t result);
72bda55b6aSAlexander Motin static int ata_intel_sata_sidpr_write(device_t dev, int port,
73bda55b6aSAlexander Motin     int reg, u_int32_t result);
74f49c6198SAlexander Motin static int ata_intel_sata_sidpr_test(device_t dev);
7504ff88ceSAlexander Motin static int ata_intel_31244_ch_attach(device_t dev);
7678d15416SAlexander Motin static int ata_intel_31244_ch_detach(device_t dev);
7713014ca0SSøren Schmidt static int ata_intel_31244_status(device_t dev);
7813014ca0SSøren Schmidt static void ata_intel_31244_tf_write(struct ata_request *request);
7913014ca0SSøren Schmidt static void ata_intel_31244_reset(device_t dev);
8013014ca0SSøren Schmidt 
8113014ca0SSøren Schmidt /* misc defines */
82bda55b6aSAlexander Motin #define INTEL_ICH5	2
83bda55b6aSAlexander Motin #define INTEL_6CH	4
84bda55b6aSAlexander Motin #define INTEL_6CH2	8
85f1bfc8abSAlexander Motin #define INTEL_ICH7	16
8613014ca0SSøren Schmidt 
87dd60e051SAlexander Motin struct ata_intel_data {
88dd60e051SAlexander Motin 	struct mtx	lock;
89dd60e051SAlexander Motin 	u_char		smap[4];
90dd60e051SAlexander Motin };
91dd60e051SAlexander Motin 
92dd60e051SAlexander Motin #define ATA_INTEL_SMAP(ctlr, ch) \
93dd60e051SAlexander Motin     &((struct ata_intel_data *)((ctlr)->chipset_data))->smap[(ch)->unit * 2]
94dd60e051SAlexander Motin #define ATA_INTEL_LOCK(ctlr) \
95dd60e051SAlexander Motin     mtx_lock(&((struct ata_intel_data *)((ctlr)->chipset_data))->lock)
96dd60e051SAlexander Motin #define ATA_INTEL_UNLOCK(ctlr) \
97dd60e051SAlexander Motin     mtx_unlock(&((struct ata_intel_data *)((ctlr)->chipset_data))->lock)
98dd60e051SAlexander Motin 
9913014ca0SSøren Schmidt /*
10013014ca0SSøren Schmidt  * Intel chipset support functions
10113014ca0SSøren Schmidt  */
10213014ca0SSøren Schmidt static int
ata_intel_probe(device_t dev)10313014ca0SSøren Schmidt ata_intel_probe(device_t dev)
10413014ca0SSøren Schmidt {
10513014ca0SSøren Schmidt     struct ata_pci_controller *ctlr = device_get_softc(dev);
10629658c96SDimitry Andric     static const struct ata_chip_id ids[] =
10713014ca0SSøren Schmidt     {{ ATA_I82371FB,     0,          0, 2, ATA_WDMA2, "PIIX" },
10813014ca0SSøren Schmidt      { ATA_I82371SB,     0,          0, 2, ATA_WDMA2, "PIIX3" },
10913014ca0SSøren Schmidt      { ATA_I82371AB,     0,          0, 2, ATA_UDMA2, "PIIX4" },
11013014ca0SSøren Schmidt      { ATA_I82443MX,     0,          0, 2, ATA_UDMA2, "PIIX4" },
11113014ca0SSøren Schmidt      { ATA_I82451NX,     0,          0, 2, ATA_UDMA2, "PIIX4" },
11213014ca0SSøren Schmidt      { ATA_I82801AB,     0,          0, 2, ATA_UDMA2, "ICH0" },
11313014ca0SSøren Schmidt      { ATA_I82801AA,     0,          0, 2, ATA_UDMA4, "ICH" },
11413014ca0SSøren Schmidt      { ATA_I82372FB,     0,          0, 2, ATA_UDMA4, "ICH" },
11513014ca0SSøren Schmidt      { ATA_I82801BA,     0,          0, 2, ATA_UDMA5, "ICH2" },
11613014ca0SSøren Schmidt      { ATA_I82801BA_1,   0,          0, 2, ATA_UDMA5, "ICH2" },
11713014ca0SSøren Schmidt      { ATA_I82801CA,     0,          0, 2, ATA_UDMA5, "ICH3" },
11813014ca0SSøren Schmidt      { ATA_I82801CA_1,   0,          0, 2, ATA_UDMA5, "ICH3" },
11913014ca0SSøren Schmidt      { ATA_I82801DB,     0,          0, 2, ATA_UDMA5, "ICH4" },
12013014ca0SSøren Schmidt      { ATA_I82801DB_1,   0,          0, 2, ATA_UDMA5, "ICH4" },
12113014ca0SSøren Schmidt      { ATA_I82801EB,     0,          0, 2, ATA_UDMA5, "ICH5" },
122bda55b6aSAlexander Motin      { ATA_I82801EB_S1,  0, INTEL_ICH5, 2, ATA_SA150, "ICH5" },
123bda55b6aSAlexander Motin      { ATA_I82801EB_R1,  0, INTEL_ICH5, 2, ATA_SA150, "ICH5" },
12413014ca0SSøren Schmidt      { ATA_I6300ESB,     0,          0, 2, ATA_UDMA5, "6300ESB" },
125bda55b6aSAlexander Motin      { ATA_I6300ESB_S1,  0, INTEL_ICH5, 2, ATA_SA150, "6300ESB" },
126bda55b6aSAlexander Motin      { ATA_I6300ESB_R1,  0, INTEL_ICH5, 2, ATA_SA150, "6300ESB" },
12713014ca0SSøren Schmidt      { ATA_I82801FB,     0,          0, 2, ATA_UDMA5, "ICH6" },
128cdc58367SAlexander Motin      { ATA_I82801FB_S1,  0,          0, 0, ATA_SA150, "ICH6" },
129cdc58367SAlexander Motin      { ATA_I82801FB_R1,  0,          0, 0, ATA_SA150, "ICH6" },
130cdc58367SAlexander Motin      { ATA_I82801FBM,    0,          0, 0, ATA_SA150, "ICH6M" },
13113014ca0SSøren Schmidt      { ATA_I82801GB,     0,          0, 1, ATA_UDMA5, "ICH7" },
132f1bfc8abSAlexander Motin      { ATA_I82801GB_S1,  0, INTEL_ICH7, 0, ATA_SA300, "ICH7" },
133f1bfc8abSAlexander Motin      { ATA_I82801GBM_S1, 0, INTEL_ICH7, 0, ATA_SA150, "ICH7M" },
13413014ca0SSøren Schmidt      { ATA_I63XXESB2,    0,          0, 1, ATA_UDMA5, "63XXESB2" },
135bda55b6aSAlexander Motin      { ATA_I63XXESB2_S1, 0,          0, 0, ATA_SA300, "63XXESB2" },
136bda55b6aSAlexander Motin      { ATA_I82801HB_S1,  0, INTEL_6CH,  0, ATA_SA300, "ICH8" },
137bda55b6aSAlexander Motin      { ATA_I82801HB_S2,  0, INTEL_6CH2, 0, ATA_SA300, "ICH8" },
13813014ca0SSøren Schmidt      { ATA_I82801HBM,    0,          0, 1, ATA_UDMA5, "ICH8M" },
139bda55b6aSAlexander Motin      { ATA_I82801HBM_S1, 0, INTEL_6CH,  0, ATA_SA300, "ICH8M" },
140bda55b6aSAlexander Motin      { ATA_I82801IB_S1,  0, INTEL_6CH,  0, ATA_SA300, "ICH9" },
141bda55b6aSAlexander Motin      { ATA_I82801IB_S2,  0, INTEL_6CH2, 0, ATA_SA300, "ICH9" },
14253479021SAlexander Motin      { ATA_I82801IB_S3,  0, INTEL_6CH2, 0, ATA_SA300, "ICH9" },
143dd3ebdbaSAlexander Motin      { ATA_I82801IBM_S1, 0, INTEL_6CH2, 0, ATA_SA300, "ICH9M" },
144dd3ebdbaSAlexander Motin      { ATA_I82801IBM_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH9M" },
145bda55b6aSAlexander Motin      { ATA_I82801JIB_S1, 0, INTEL_6CH,  0, ATA_SA300, "ICH10" },
146bda55b6aSAlexander Motin      { ATA_I82801JIB_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH10" },
147bda55b6aSAlexander Motin      { ATA_I82801JD_S1,  0, INTEL_6CH,  0, ATA_SA300, "ICH10" },
148bda55b6aSAlexander Motin      { ATA_I82801JD_S2,  0, INTEL_6CH2, 0, ATA_SA300, "ICH10" },
149bda55b6aSAlexander Motin      { ATA_I82801JI_S1,  0, INTEL_6CH,  0, ATA_SA300, "ICH10" },
150bda55b6aSAlexander Motin      { ATA_I82801JI_S2,  0, INTEL_6CH2, 0, ATA_SA300, "ICH10" },
1516750c3d0SAlexander Motin      { ATA_IBP_S1,       0, INTEL_6CH,  0, ATA_SA300, "Ibex Peak" },
1526750c3d0SAlexander Motin      { ATA_IBP_S2,       0, INTEL_6CH2, 0, ATA_SA300, "Ibex Peak" },
1536750c3d0SAlexander Motin      { ATA_IBP_S3,       0, INTEL_6CH2, 0, ATA_SA300, "Ibex Peak" },
1546750c3d0SAlexander Motin      { ATA_IBP_S4,       0, INTEL_6CH,  0, ATA_SA300, "Ibex Peak-M" },
1556750c3d0SAlexander Motin      { ATA_IBP_S5,       0, INTEL_6CH2, 0, ATA_SA300, "Ibex Peak-M" },
1566750c3d0SAlexander Motin      { ATA_IBP_S6,       0, INTEL_6CH,  0, ATA_SA300, "Ibex Peak-M" },
157709c835aSAlexander Motin      { ATA_CPT_S1,       0, INTEL_6CH,  0, ATA_SA600, "Cougar Point" },
158709c835aSAlexander Motin      { ATA_CPT_S2,       0, INTEL_6CH,  0, ATA_SA600, "Cougar Point" },
159bda55b6aSAlexander Motin      { ATA_CPT_S3,       0, INTEL_6CH2, 0, ATA_SA300, "Cougar Point" },
160bda55b6aSAlexander Motin      { ATA_CPT_S4,       0, INTEL_6CH2, 0, ATA_SA300, "Cougar Point" },
161709c835aSAlexander Motin      { ATA_PBG_S1,       0, INTEL_6CH,  0, ATA_SA600, "Patsburg" },
162bf0477b2SJack F Vogel      { ATA_PBG_S2,       0, INTEL_6CH2, 0, ATA_SA300, "Patsburg" },
163709c835aSAlexander Motin      { ATA_PPT_S1,       0, INTEL_6CH,  0, ATA_SA600, "Panther Point" },
164709c835aSAlexander Motin      { ATA_PPT_S2,       0, INTEL_6CH,  0, ATA_SA600, "Panther Point" },
16573e3bb65SJack F Vogel      { ATA_PPT_S3,       0, INTEL_6CH2, 0, ATA_SA300, "Panther Point" },
16673e3bb65SJack F Vogel      { ATA_PPT_S4,       0, INTEL_6CH2, 0, ATA_SA300, "Panther Point" },
167709c835aSAlexander Motin      { ATA_AVOTON_S1,    0, INTEL_6CH,  0, ATA_SA600, "Avoton" },
168709c835aSAlexander Motin      { ATA_AVOTON_S2,    0, INTEL_6CH,  0, ATA_SA600, "Avoton" },
169eda36fb4SAlexander Motin      { ATA_AVOTON_S3,    0, INTEL_6CH2, 0, ATA_SA300, "Avoton" },
170eda36fb4SAlexander Motin      { ATA_AVOTON_S4,    0, INTEL_6CH2, 0, ATA_SA300, "Avoton" },
171709c835aSAlexander Motin      { ATA_LPT_S1,       0, INTEL_6CH,  0, ATA_SA600, "Lynx Point" },
172709c835aSAlexander Motin      { ATA_LPT_S2,       0, INTEL_6CH,  0, ATA_SA600, "Lynx Point" },
173709c835aSAlexander Motin      { ATA_LPT_S3,       0, INTEL_6CH2, 0, ATA_SA600, "Lynx Point" },
174709c835aSAlexander Motin      { ATA_LPT_S4,       0, INTEL_6CH2, 0, ATA_SA600, "Lynx Point" },
175709c835aSAlexander Motin      { ATA_WCPT_S1,      0, INTEL_6CH,  0, ATA_SA600, "Wildcat Point" },
176709c835aSAlexander Motin      { ATA_WCPT_S2,      0, INTEL_6CH,  0, ATA_SA600, "Wildcat Point" },
177709c835aSAlexander Motin      { ATA_WCPT_S3,      0, INTEL_6CH2, 0, ATA_SA600, "Wildcat Point" },
178709c835aSAlexander Motin      { ATA_WCPT_S4,      0, INTEL_6CH2, 0, ATA_SA600, "Wildcat Point" },
179709c835aSAlexander Motin      { ATA_WELLS_S1,     0, INTEL_6CH,  0, ATA_SA600, "Wellsburg" },
180709c835aSAlexander Motin      { ATA_WELLS_S2,     0, INTEL_6CH2, 0, ATA_SA600, "Wellsburg" },
181709c835aSAlexander Motin      { ATA_WELLS_S3,     0, INTEL_6CH,  0, ATA_SA600, "Wellsburg" },
182709c835aSAlexander Motin      { ATA_WELLS_S4,     0, INTEL_6CH2, 0, ATA_SA600, "Wellsburg" },
183709c835aSAlexander Motin      { ATA_LPTLP_S1,     0, INTEL_6CH,  0, ATA_SA600, "Lynx Point-LP" },
184709c835aSAlexander Motin      { ATA_LPTLP_S2,     0, INTEL_6CH,  0, ATA_SA600, "Lynx Point-LP" },
185eda36fb4SAlexander Motin      { ATA_LPTLP_S3,     0, INTEL_6CH2, 0, ATA_SA300, "Lynx Point-LP" },
186eda36fb4SAlexander Motin      { ATA_LPTLP_S4,     0, INTEL_6CH2, 0, ATA_SA300, "Lynx Point-LP" },
18713014ca0SSøren Schmidt      { ATA_I31244,       0,          0, 2, ATA_SA150, "31244" },
1887aab51b3SAlexander Motin      { ATA_ISCH,         0,          0, 1, ATA_UDMA5, "SCH" },
189428e286dSJack F Vogel      { ATA_COLETOCRK_S1, 0, INTEL_6CH2, 0, ATA_SA300, "COLETOCRK" },
190428e286dSJack F Vogel      { ATA_COLETOCRK_S2, 0, INTEL_6CH2, 0, ATA_SA300, "COLETOCRK" },
19105d1c205SDmitry Luhtionov      { ATA_IBT_S1,       0,          0, 0, ATA_SA300, "BayTrail" },
19205d1c205SDmitry Luhtionov      { ATA_IBT_S2,       0,          0, 0, ATA_SA300, "BayTrail" },
19313014ca0SSøren Schmidt      { 0, 0, 0, 0, 0, 0}};
19413014ca0SSøren Schmidt 
19513014ca0SSøren Schmidt     if (pci_get_vendor(dev) != ATA_INTEL_ID)
19613014ca0SSøren Schmidt 	return ENXIO;
19713014ca0SSøren Schmidt 
19813014ca0SSøren Schmidt     if (!(ctlr->chip = ata_match_chip(dev, ids)))
19913014ca0SSøren Schmidt 	return ENXIO;
20013014ca0SSøren Schmidt 
20113014ca0SSøren Schmidt     ata_set_desc(dev);
20213014ca0SSøren Schmidt     ctlr->chipinit = ata_intel_chipinit;
203dd60e051SAlexander Motin     ctlr->chipdeinit = ata_intel_chipdeinit;
2043036de3cSAlexander Motin     return (BUS_PROBE_LOW_PRIORITY);
20513014ca0SSøren Schmidt }
20613014ca0SSøren Schmidt 
20713014ca0SSøren Schmidt static int
ata_intel_chipinit(device_t dev)20813014ca0SSøren Schmidt ata_intel_chipinit(device_t dev)
20913014ca0SSøren Schmidt {
21013014ca0SSøren Schmidt     struct ata_pci_controller *ctlr = device_get_softc(dev);
211dd60e051SAlexander Motin     struct ata_intel_data *data;
21213014ca0SSøren Schmidt 
21313014ca0SSøren Schmidt     if (ata_setup_interrupt(dev, ata_generic_intr))
21413014ca0SSøren Schmidt 	return ENXIO;
21513014ca0SSøren Schmidt 
216dd60e051SAlexander Motin     data = malloc(sizeof(struct ata_intel_data), M_ATAPCI, M_WAITOK | M_ZERO);
217dd60e051SAlexander Motin     mtx_init(&data->lock, "Intel SATA lock", NULL, MTX_DEF);
218dd60e051SAlexander Motin     ctlr->chipset_data = (void *)data;
219bda55b6aSAlexander Motin 
22013014ca0SSøren Schmidt     /* good old PIIX needs special treatment (not implemented) */
22113014ca0SSøren Schmidt     if (ctlr->chip->chipid == ATA_I82371FB) {
22213014ca0SSøren Schmidt 	ctlr->setmode = ata_intel_old_setmode;
22313014ca0SSøren Schmidt     }
22413014ca0SSøren Schmidt 
22513014ca0SSøren Schmidt     /* the intel 31244 needs special care if in DPA mode */
22613014ca0SSøren Schmidt     else if (ctlr->chip->chipid == ATA_I31244) {
22713014ca0SSøren Schmidt 	if (pci_get_subclass(dev) != PCIS_STORAGE_IDE) {
22813014ca0SSøren Schmidt 	    ctlr->r_type2 = SYS_RES_MEMORY;
22913014ca0SSøren Schmidt 	    ctlr->r_rid2 = PCIR_BAR(0);
23013014ca0SSøren Schmidt 	    if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
23113014ca0SSøren Schmidt 							&ctlr->r_rid2,
23213014ca0SSøren Schmidt 							RF_ACTIVE)))
23313014ca0SSøren Schmidt 		return ENXIO;
23413014ca0SSøren Schmidt 	    ctlr->channels = 4;
23504ff88ceSAlexander Motin 	    ctlr->ch_attach = ata_intel_31244_ch_attach;
23678d15416SAlexander Motin 	    ctlr->ch_detach = ata_intel_31244_ch_detach;
23713014ca0SSøren Schmidt 	    ctlr->reset = ata_intel_31244_reset;
23813014ca0SSøren Schmidt 	}
23913014ca0SSøren Schmidt 	ctlr->setmode = ata_sata_setmode;
240066f913aSAlexander Motin 	ctlr->getrev = ata_sata_getrev;
24113014ca0SSøren Schmidt     }
2427aab51b3SAlexander Motin     /* SCH */
2437aab51b3SAlexander Motin     else if (ctlr->chip->chipid == ATA_ISCH) {
2447aab51b3SAlexander Motin 	ctlr->channels = 1;
2457aab51b3SAlexander Motin 	ctlr->ch_attach = ata_intel_ch_attach;
2467aab51b3SAlexander Motin 	ctlr->ch_detach = ata_pci_ch_detach;
2477aab51b3SAlexander Motin 	ctlr->setmode = ata_intel_sch_setmode;
2487aab51b3SAlexander Motin     }
24913014ca0SSøren Schmidt     /* non SATA intel chips goes here */
25013014ca0SSøren Schmidt     else if (ctlr->chip->max_dma < ATA_SA150) {
25113014ca0SSøren Schmidt 	ctlr->channels = ctlr->chip->cfg2;
25204ff88ceSAlexander Motin 	ctlr->ch_attach = ata_intel_ch_attach;
25378d15416SAlexander Motin 	ctlr->ch_detach = ata_pci_ch_detach;
25413014ca0SSøren Schmidt 	ctlr->setmode = ata_intel_new_setmode;
25513014ca0SSøren Schmidt     }
25613014ca0SSøren Schmidt 
25713014ca0SSøren Schmidt     /* SATA parts can be either compat or AHCI */
25813014ca0SSøren Schmidt     else {
25913014ca0SSøren Schmidt 	/* force all ports active "the legacy way" */
26013014ca0SSøren Schmidt 	pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f, 2);
26113014ca0SSøren Schmidt 
26204ff88ceSAlexander Motin 	ctlr->ch_attach = ata_intel_ch_attach;
26378d15416SAlexander Motin 	ctlr->ch_detach = ata_pci_ch_detach;
26413014ca0SSøren Schmidt 	ctlr->reset = ata_intel_reset;
26513014ca0SSøren Schmidt 
266f1bfc8abSAlexander Motin 	/* BAR(5) may point to SATA interface registers */
267f1bfc8abSAlexander Motin 	if ((ctlr->chip->cfg1 & INTEL_ICH7)) {
268f1bfc8abSAlexander Motin 		ctlr->r_type2 = SYS_RES_MEMORY;
269f1bfc8abSAlexander Motin 		ctlr->r_rid2 = PCIR_BAR(5);
270f1bfc8abSAlexander Motin 		ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
271f1bfc8abSAlexander Motin 		    &ctlr->r_rid2, RF_ACTIVE);
272f1bfc8abSAlexander Motin 		if (ctlr->r_res2 != NULL) {
273f1bfc8abSAlexander Motin 			/* Set SCRAE bit to enable registers access. */
274f1bfc8abSAlexander Motin 			pci_write_config(dev, 0x94,
275f1bfc8abSAlexander Motin 			    pci_read_config(dev, 0x94, 4) | (1 << 9), 4);
276f1bfc8abSAlexander Motin 			/* Set Ports Implemented register bits. */
277f1bfc8abSAlexander Motin 			ATA_OUTL(ctlr->r_res2, 0x0C,
278f1bfc8abSAlexander Motin 			    ATA_INL(ctlr->r_res2, 0x0C) | 0xf);
279f1bfc8abSAlexander Motin 		}
280e292b310SAlexander Motin 	/* Skip BAR(5) on ICH8M Apples, system locks up on access. */
281e292b310SAlexander Motin 	} else if (ctlr->chip->chipid != ATA_I82801HBM_S1 ||
282e292b310SAlexander Motin 	    pci_get_subvendor(dev) != 0x106b) {
28313014ca0SSøren Schmidt 		ctlr->r_type2 = SYS_RES_IOPORT;
28413014ca0SSøren Schmidt 		ctlr->r_rid2 = PCIR_BAR(5);
285f1bfc8abSAlexander Motin 		ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
286f1bfc8abSAlexander Motin 		    &ctlr->r_rid2, RF_ACTIVE);
287f1bfc8abSAlexander Motin 	}
288f1bfc8abSAlexander Motin 	if (ctlr->r_res2 != NULL ||
289f1bfc8abSAlexander Motin 	    (ctlr->chip->cfg1 & INTEL_ICH5))
290066f913aSAlexander Motin 		ctlr->getrev = ata_intel_sata_getrev;
29113014ca0SSøren Schmidt 	ctlr->setmode = ata_sata_setmode;
29213014ca0SSøren Schmidt     }
29313014ca0SSøren Schmidt     return 0;
29413014ca0SSøren Schmidt }
29513014ca0SSøren Schmidt 
29613014ca0SSøren Schmidt static int
ata_intel_chipdeinit(device_t dev)297dd60e051SAlexander Motin ata_intel_chipdeinit(device_t dev)
298dd60e051SAlexander Motin {
299dd60e051SAlexander Motin 	struct ata_pci_controller *ctlr = device_get_softc(dev);
300dd60e051SAlexander Motin 	struct ata_intel_data *data;
301dd60e051SAlexander Motin 
302dd60e051SAlexander Motin 	data = ctlr->chipset_data;
303dd60e051SAlexander Motin 	mtx_destroy(&data->lock);
304dd60e051SAlexander Motin 	free(data, M_ATAPCI);
305dd60e051SAlexander Motin 	ctlr->chipset_data = NULL;
306dd60e051SAlexander Motin 	return (0);
307dd60e051SAlexander Motin }
308dd60e051SAlexander Motin 
309dd60e051SAlexander Motin static int
ata_intel_ch_attach(device_t dev)31004ff88ceSAlexander Motin ata_intel_ch_attach(device_t dev)
31113014ca0SSøren Schmidt {
312bda55b6aSAlexander Motin 	struct ata_pci_controller *ctlr;
313bda55b6aSAlexander Motin 	struct ata_channel *ch;
314bda55b6aSAlexander Motin 	u_char *smap;
315bda55b6aSAlexander Motin 	u_int map;
31613014ca0SSøren Schmidt 
31713014ca0SSøren Schmidt 	/* setup the usual register normal pci style */
31804ff88ceSAlexander Motin 	if (ata_pci_ch_attach(dev))
319bda55b6aSAlexander Motin 		return (ENXIO);
320bda55b6aSAlexander Motin 
321bda55b6aSAlexander Motin 	ctlr = device_get_softc(device_get_parent(dev));
322bda55b6aSAlexander Motin 	ch = device_get_softc(dev);
32313014ca0SSøren Schmidt 
32413014ca0SSøren Schmidt 	/* if r_res2 is valid it points to SATA interface registers */
32513014ca0SSøren Schmidt 	if (ctlr->r_res2) {
32613014ca0SSøren Schmidt 		ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;
32713014ca0SSøren Schmidt 		ch->r_io[ATA_IDX_ADDR].offset = 0x00;
32813014ca0SSøren Schmidt 		ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2;
32913014ca0SSøren Schmidt 		ch->r_io[ATA_IDX_DATA].offset = 0x04;
33013014ca0SSøren Schmidt 	}
33113014ca0SSøren Schmidt 
33213014ca0SSøren Schmidt 	ch->flags |= ATA_ALWAYS_DMASTAT;
333066f913aSAlexander Motin 	if (ctlr->chip->max_dma >= ATA_SA150) {
334dd60e051SAlexander Motin 		smap = ATA_INTEL_SMAP(ctlr, ch);
335bda55b6aSAlexander Motin 		map = pci_read_config(device_get_parent(dev), 0x90, 1);
336bda55b6aSAlexander Motin 		if (ctlr->chip->cfg1 & INTEL_ICH5) {
337bda55b6aSAlexander Motin 			map &= 0x07;
338bda55b6aSAlexander Motin 			if ((map & 0x04) == 0) {
339066f913aSAlexander Motin 				ch->flags |= ATA_SATA;
340bda55b6aSAlexander Motin 				ch->flags |= ATA_NO_SLAVE;
341bda55b6aSAlexander Motin 				smap[0] = (map & 0x01) ^ ch->unit;
342bda55b6aSAlexander Motin 				smap[1] = 0;
343bda55b6aSAlexander Motin 			} else if ((map & 0x02) == 0 && ch->unit == 0) {
344bda55b6aSAlexander Motin 				ch->flags |= ATA_SATA;
345bda55b6aSAlexander Motin 				smap[0] = (map & 0x01) ? 1 : 0;
346bda55b6aSAlexander Motin 				smap[1] = (map & 0x01) ? 0 : 1;
347bda55b6aSAlexander Motin 			} else if ((map & 0x02) != 0 && ch->unit == 1) {
348bda55b6aSAlexander Motin 				ch->flags |= ATA_SATA;
349bda55b6aSAlexander Motin 				smap[0] = (map & 0x01) ? 1 : 0;
350bda55b6aSAlexander Motin 				smap[1] = (map & 0x01) ? 0 : 1;
351bda55b6aSAlexander Motin 			}
352bda55b6aSAlexander Motin 		} else if (ctlr->chip->cfg1 & INTEL_6CH2) {
353bda55b6aSAlexander Motin 			ch->flags |= ATA_SATA;
354bda55b6aSAlexander Motin 			ch->flags |= ATA_NO_SLAVE;
35553479021SAlexander Motin 			smap[0] = (ch->unit == 0) ? 0 : 1;
356bda55b6aSAlexander Motin 			smap[1] = 0;
357bda55b6aSAlexander Motin 		} else {
358bda55b6aSAlexander Motin 			map &= 0x03;
359bda55b6aSAlexander Motin 			if (map == 0x00) {
360bda55b6aSAlexander Motin 				ch->flags |= ATA_SATA;
361bda55b6aSAlexander Motin 				smap[0] = (ch->unit == 0) ? 0 : 1;
362bda55b6aSAlexander Motin 				smap[1] = (ch->unit == 0) ? 2 : 3;
363bda55b6aSAlexander Motin 			} else if (map == 0x02 && ch->unit == 0) {
364bda55b6aSAlexander Motin 				ch->flags |= ATA_SATA;
365bda55b6aSAlexander Motin 				smap[0] = 0;
366bda55b6aSAlexander Motin 				smap[1] = 2;
367bda55b6aSAlexander Motin 			} else if (map == 0x01 && ch->unit == 1) {
368bda55b6aSAlexander Motin 				ch->flags |= ATA_SATA;
369bda55b6aSAlexander Motin 				smap[0] = 1;
370bda55b6aSAlexander Motin 				smap[1] = 3;
371bda55b6aSAlexander Motin 			}
372bda55b6aSAlexander Motin 		}
373bda55b6aSAlexander Motin 		if (ch->flags & ATA_SATA) {
374bda55b6aSAlexander Motin 			if ((ctlr->chip->cfg1 & INTEL_ICH5)) {
375bda55b6aSAlexander Motin 				ch->hw.pm_read = ata_intel_sata_cscr_read;
376bda55b6aSAlexander Motin 				ch->hw.pm_write = ata_intel_sata_cscr_write;
377bda55b6aSAlexander Motin 			} else if (ctlr->r_res2) {
378f1bfc8abSAlexander Motin 				if ((ctlr->chip->cfg1 & INTEL_ICH7)) {
379f1bfc8abSAlexander Motin 					ch->hw.pm_read = ata_intel_sata_ahci_read;
380f1bfc8abSAlexander Motin 					ch->hw.pm_write = ata_intel_sata_ahci_write;
381f49c6198SAlexander Motin 				} else if (ata_intel_sata_sidpr_test(dev)) {
382bda55b6aSAlexander Motin 					ch->hw.pm_read = ata_intel_sata_sidpr_read;
383bda55b6aSAlexander Motin 					ch->hw.pm_write = ata_intel_sata_sidpr_write;
38474b8d63dSPedro F. Giffuni 				}
385bda55b6aSAlexander Motin 			}
386bda55b6aSAlexander Motin 			if (ch->hw.pm_write != NULL) {
387f49c6198SAlexander Motin 				ch->flags |= ATA_PERIODIC_POLL;
388f49c6198SAlexander Motin 				ch->hw.status = ata_intel_sata_status;
389bda55b6aSAlexander Motin 				ata_sata_scr_write(ch, 0,
390bda55b6aSAlexander Motin 				    ATA_SERROR, 0xffffffff);
391bda55b6aSAlexander Motin 				if ((ch->flags & ATA_NO_SLAVE) == 0) {
392bda55b6aSAlexander Motin 					ata_sata_scr_write(ch, 1,
393bda55b6aSAlexander Motin 					    ATA_SERROR, 0xffffffff);
394bda55b6aSAlexander Motin 				}
395bda55b6aSAlexander Motin 			}
396bda55b6aSAlexander Motin 		} else
397bda55b6aSAlexander Motin 			ctlr->setmode = ata_intel_new_setmode;
398709c835aSAlexander Motin 		if (ctlr->chip->max_dma >= ATA_SA600)
399709c835aSAlexander Motin 			ch->flags |= ATA_USE_16BIT;
4007aab51b3SAlexander Motin 	} else if (ctlr->chip->chipid != ATA_ISCH)
401066f913aSAlexander Motin 		ch->flags |= ATA_CHECKS_CABLE;
402bda55b6aSAlexander Motin 	return (0);
40313014ca0SSøren Schmidt }
40413014ca0SSøren Schmidt 
40513014ca0SSøren Schmidt static void
ata_intel_reset(device_t dev)40613014ca0SSøren Schmidt ata_intel_reset(device_t dev)
40713014ca0SSøren Schmidt {
40813014ca0SSøren Schmidt 	device_t parent = device_get_parent(dev);
40913014ca0SSøren Schmidt 	struct ata_pci_controller *ctlr = device_get_softc(parent);
41013014ca0SSøren Schmidt 	struct ata_channel *ch = device_get_softc(dev);
411c7dd7de6SAlexander Motin 	int mask, pshift, timeout, devs;
412bda55b6aSAlexander Motin 	u_char *smap;
413c7dd7de6SAlexander Motin 	uint16_t pcs;
41413014ca0SSøren Schmidt 
415bda55b6aSAlexander Motin 	/* In combined mode, skip SATA stuff for PATA channel. */
416bda55b6aSAlexander Motin 	if ((ch->flags & ATA_SATA) == 0)
417bda55b6aSAlexander Motin 		return (ata_generic_reset(dev));
418bda55b6aSAlexander Motin 
419bda55b6aSAlexander Motin 	/* Do hard-reset on respective SATA ports. */
420dd60e051SAlexander Motin 	smap = ATA_INTEL_SMAP(ctlr, ch);
421bda55b6aSAlexander Motin 	mask = 1 << smap[0];
422bda55b6aSAlexander Motin 	if ((ch->flags & ATA_NO_SLAVE) == 0)
423bda55b6aSAlexander Motin 		mask |= (1 << smap[1]);
424bda55b6aSAlexander Motin 	pci_write_config(parent, 0x92,
425bda55b6aSAlexander Motin 	    pci_read_config(parent, 0x92, 2) & ~mask, 2);
426dd7df419SAlexander Motin 	DELAY(100);
427bda55b6aSAlexander Motin 	pci_write_config(parent, 0x92,
428bda55b6aSAlexander Motin 	    pci_read_config(parent, 0x92, 2) | mask, 2);
42913014ca0SSøren Schmidt 
430bda55b6aSAlexander Motin 	/* Wait up to 1 sec for "connect well". */
431bda55b6aSAlexander Motin 	if (ctlr->chip->cfg1 & (INTEL_6CH | INTEL_6CH2))
432c7dd7de6SAlexander Motin 		pshift = 8;
433bda55b6aSAlexander Motin 	else
434c7dd7de6SAlexander Motin 		pshift = 4;
43513014ca0SSøren Schmidt 	for (timeout = 0; timeout < 100 ; timeout++) {
436c7dd7de6SAlexander Motin 		pcs = (pci_read_config(parent, 0x92, 2) >> pshift) & mask;
437c7dd7de6SAlexander Motin 		if ((pcs == mask) && (ATA_IDX_INB(ch, ATA_STATUS) != 0xff))
43813014ca0SSøren Schmidt 			break;
43913014ca0SSøren Schmidt 		ata_udelay(10000);
44013014ca0SSøren Schmidt 	}
441bda55b6aSAlexander Motin 
442c7dd7de6SAlexander Motin 	if (bootverbose)
443c7dd7de6SAlexander Motin 		device_printf(dev, "SATA reset: ports status=0x%02x\n", pcs);
444bda55b6aSAlexander Motin 	/* If any device found, do soft-reset. */
445bda55b6aSAlexander Motin 	if (ch->hw.pm_read != NULL) {
446c7dd7de6SAlexander Motin 		devs = ata_sata_phy_reset(dev, 0, 2) ? ATA_ATA_MASTER : 0;
447bda55b6aSAlexander Motin 		if ((ch->flags & ATA_NO_SLAVE) == 0)
448c7dd7de6SAlexander Motin 			devs |= ata_sata_phy_reset(dev, 1, 2) ?
449c7dd7de6SAlexander Motin 			    ATA_ATA_SLAVE : 0;
450c7dd7de6SAlexander Motin 	} else {
451c7dd7de6SAlexander Motin 		devs = (pcs & (1 << smap[0])) ? ATA_ATA_MASTER : 0;
452c7dd7de6SAlexander Motin 		if ((ch->flags & ATA_NO_SLAVE) == 0)
453c7dd7de6SAlexander Motin 			devs |= (pcs & (1 << smap[1])) ?
454c7dd7de6SAlexander Motin 			    ATA_ATA_SLAVE : 0;
455c7dd7de6SAlexander Motin 	}
456c7dd7de6SAlexander Motin 	if (devs) {
45713014ca0SSøren Schmidt 		ata_generic_reset(dev);
458c7dd7de6SAlexander Motin 		/* Reset may give fake slave when only ATAPI master present. */
459c7dd7de6SAlexander Motin 		ch->devices &= (devs | (devs * ATA_ATAPI_MASTER));
460c7dd7de6SAlexander Motin 	} else
461bda55b6aSAlexander Motin 		ch->devices = 0;
46213014ca0SSøren Schmidt }
46313014ca0SSøren Schmidt 
464066f913aSAlexander Motin static int
ata_intel_old_setmode(device_t dev,int target,int mode)465066f913aSAlexander Motin ata_intel_old_setmode(device_t dev, int target, int mode)
46613014ca0SSøren Schmidt {
467066f913aSAlexander Motin 	device_t parent = device_get_parent(dev);
468066f913aSAlexander Motin 	struct ata_pci_controller *ctlr = device_get_softc(parent);
469066f913aSAlexander Motin 
470066f913aSAlexander Motin 	mode = min(mode, ctlr->chip->max_dma);
471066f913aSAlexander Motin 	return (mode);
47213014ca0SSøren Schmidt }
47313014ca0SSøren Schmidt 
474066f913aSAlexander Motin static int
ata_intel_new_setmode(device_t dev,int target,int mode)475066f913aSAlexander Motin ata_intel_new_setmode(device_t dev, int target, int mode)
47613014ca0SSøren Schmidt {
477066f913aSAlexander Motin 	device_t parent = device_get_parent(dev);
478066f913aSAlexander Motin 	struct ata_pci_controller *ctlr = device_get_softc(parent);
479066f913aSAlexander Motin 	struct ata_channel *ch = device_get_softc(dev);
480066f913aSAlexander Motin 	int devno = (ch->unit << 1) + target;
481066f913aSAlexander Motin 	int piomode;
482066f913aSAlexander Motin 	u_int32_t reg40 = pci_read_config(parent, 0x40, 4);
483066f913aSAlexander Motin 	u_int8_t reg44 = pci_read_config(parent, 0x44, 1);
484066f913aSAlexander Motin 	u_int8_t reg48 = pci_read_config(parent, 0x48, 1);
485066f913aSAlexander Motin 	u_int16_t reg4a = pci_read_config(parent, 0x4a, 2);
486066f913aSAlexander Motin 	u_int16_t reg54 = pci_read_config(parent, 0x54, 2);
48713014ca0SSøren Schmidt 	u_int32_t mask40 = 0, new40 = 0;
48813014ca0SSøren Schmidt 	u_int8_t mask44 = 0, new44 = 0;
4895187458fSMarius Strobl 	static const uint8_t timings[] =
4905187458fSMarius Strobl 	    { 0x00, 0x00, 0x10, 0x21, 0x23, 0x00, 0x21, 0x23 };
4915187458fSMarius Strobl 	static const uint8_t utimings[] =
4925187458fSMarius Strobl 	    { 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 };
49313014ca0SSøren Schmidt 
494bda55b6aSAlexander Motin 	/* In combined mode, skip PATA stuff for SATA channel. */
495bda55b6aSAlexander Motin 	if (ch->flags & ATA_SATA)
496bda55b6aSAlexander Motin 		return (ata_sata_setmode(dev, target, mode));
497bda55b6aSAlexander Motin 
498066f913aSAlexander Motin 	mode = min(mode, ctlr->chip->max_dma);
4999a9bce34SAlexander Motin 	if (ata_dma_check_80pin && mode > ATA_UDMA2 &&
5009a9bce34SAlexander Motin 	    !(reg54 & (0x10 << devno))) {
50113014ca0SSøren Schmidt 		ata_print_cable(dev, "controller");
50213014ca0SSøren Schmidt 		mode = ATA_UDMA2;
50313014ca0SSøren Schmidt 	}
504066f913aSAlexander Motin 	/* Enable/disable UDMA and set timings. */
50513014ca0SSøren Schmidt 	if (mode >= ATA_UDMA0) {
506066f913aSAlexander Motin 	    pci_write_config(parent, 0x48, reg48 | (0x0001 << devno), 2);
507066f913aSAlexander Motin 	    pci_write_config(parent, 0x4a,
50813014ca0SSøren Schmidt 		(reg4a & ~(0x3 << (devno << 2))) |
50913014ca0SSøren Schmidt 		(utimings[mode & ATA_MODE_MASK] << (devno<<2)), 2);
510066f913aSAlexander Motin 	    piomode = ATA_PIO4;
511066f913aSAlexander Motin 	} else {
512066f913aSAlexander Motin 	    pci_write_config(parent, 0x48, reg48 & ~(0x0001 << devno), 2);
513066f913aSAlexander Motin 	    pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (devno << 2))),2);
514066f913aSAlexander Motin 	    piomode = mode;
51513014ca0SSøren Schmidt 	}
51613014ca0SSøren Schmidt 	reg54 |= 0x0400;
517066f913aSAlexander Motin 	/* Set UDMA reference clock (33/66/133MHz). */
518066f913aSAlexander Motin 	reg54 &= ~(0x1001 << devno);
51913014ca0SSøren Schmidt 	if (mode >= ATA_UDMA5)
52013014ca0SSøren Schmidt 	    reg54 |= (0x1000 << devno);
521066f913aSAlexander Motin 	else if (mode >= ATA_UDMA3)
522066f913aSAlexander Motin 	    reg54 |= (0x1 << devno);
523066f913aSAlexander Motin 	pci_write_config(parent, 0x54, reg54, 2);
524066f913aSAlexander Motin 	/* Allow PIO/WDMA timing controls. */
52513014ca0SSøren Schmidt 	reg40 &= ~0x00ff00ff;
52613014ca0SSøren Schmidt 	reg40 |= 0x40774077;
527066f913aSAlexander Motin 	/* Set PIO/WDMA timings. */
528066f913aSAlexander Motin 	if (target == 0) {
52913014ca0SSøren Schmidt 	    mask40 = 0x3300;
530066f913aSAlexander Motin 	    new40 = timings[ata_mode2idx(piomode)] << 8;
531066f913aSAlexander Motin 	} else {
53213014ca0SSøren Schmidt 	    mask44 = 0x0f;
533066f913aSAlexander Motin 	    new44 = ((timings[ata_mode2idx(piomode)] & 0x30) >> 2) |
534066f913aSAlexander Motin 		    (timings[ata_mode2idx(piomode)] & 0x03);
53513014ca0SSøren Schmidt 	}
53613014ca0SSøren Schmidt 	if (ch->unit) {
53713014ca0SSøren Schmidt 	    mask40 <<= 16;
53813014ca0SSøren Schmidt 	    new40 <<= 16;
53913014ca0SSøren Schmidt 	    mask44 <<= 4;
54013014ca0SSøren Schmidt 	    new44 <<= 4;
54113014ca0SSøren Schmidt 	}
542066f913aSAlexander Motin 	pci_write_config(parent, 0x40, (reg40 & ~mask40) | new40, 4);
543066f913aSAlexander Motin 	pci_write_config(parent, 0x44, (reg44 & ~mask44) | new44, 1);
544066f913aSAlexander Motin 	return (mode);
54513014ca0SSøren Schmidt }
54613014ca0SSøren Schmidt 
547066f913aSAlexander Motin static int
ata_intel_sch_setmode(device_t dev,int target,int mode)5487aab51b3SAlexander Motin ata_intel_sch_setmode(device_t dev, int target, int mode)
5497aab51b3SAlexander Motin {
5507aab51b3SAlexander Motin 	device_t parent = device_get_parent(dev);
5517aab51b3SAlexander Motin 	struct ata_pci_controller *ctlr = device_get_softc(parent);
5527aab51b3SAlexander Motin 	u_int8_t dtim = 0x80 + (target << 2);
5537aab51b3SAlexander Motin 	u_int32_t tim = pci_read_config(parent, dtim, 4);
5547aab51b3SAlexander Motin 	int piomode;
5557aab51b3SAlexander Motin 
5567aab51b3SAlexander Motin 	mode = min(mode, ctlr->chip->max_dma);
5577aab51b3SAlexander Motin 	if (mode >= ATA_UDMA0) {
5587aab51b3SAlexander Motin 		tim |= (0x1 << 31);
5597aab51b3SAlexander Motin 		tim &= ~(0x7 << 16);
5607aab51b3SAlexander Motin 		tim |= ((mode & ATA_MODE_MASK) << 16);
5617aab51b3SAlexander Motin 		piomode = ATA_PIO4;
5627aab51b3SAlexander Motin 	} else if (mode >= ATA_WDMA0) {
5637aab51b3SAlexander Motin 		tim &= ~(0x1 << 31);
5647aab51b3SAlexander Motin 		tim &= ~(0x3 << 8);
5657aab51b3SAlexander Motin 		tim |= ((mode & ATA_MODE_MASK) << 8);
5667aab51b3SAlexander Motin 		piomode = (mode == ATA_WDMA0) ? ATA_PIO0 :
5677aab51b3SAlexander Motin 		    (mode == ATA_WDMA1) ? ATA_PIO3 : ATA_PIO4;
5687aab51b3SAlexander Motin 	} else
5697aab51b3SAlexander Motin 		piomode = mode;
5707aab51b3SAlexander Motin 	tim &= ~(0x7);
5717aab51b3SAlexander Motin 	tim |= (piomode & 0x7);
5727aab51b3SAlexander Motin 	pci_write_config(parent, dtim, tim, 4);
5737aab51b3SAlexander Motin 	return (mode);
5747aab51b3SAlexander Motin }
5757aab51b3SAlexander Motin 
5767aab51b3SAlexander Motin static int
ata_intel_sata_getrev(device_t dev,int target)577066f913aSAlexander Motin ata_intel_sata_getrev(device_t dev, int target)
57813014ca0SSøren Schmidt {
579066f913aSAlexander Motin 	struct ata_channel *ch = device_get_softc(dev);
580bda55b6aSAlexander Motin 	uint32_t status;
58113014ca0SSøren Schmidt 
582bda55b6aSAlexander Motin 	if (ata_sata_scr_read(ch, target, ATA_SSTATUS, &status) == 0)
583bda55b6aSAlexander Motin 		return ((status & 0x0f0) >> 4);
584bda55b6aSAlexander Motin 	return (0xff);
585bda55b6aSAlexander Motin }
586bda55b6aSAlexander Motin 
587bda55b6aSAlexander Motin static int
ata_intel_sata_status(device_t dev)588bda55b6aSAlexander Motin ata_intel_sata_status(device_t dev)
589bda55b6aSAlexander Motin {
590bda55b6aSAlexander Motin 	struct ata_channel *ch = device_get_softc(dev);
591bda55b6aSAlexander Motin 
592bda55b6aSAlexander Motin 	ata_sata_phy_check_events(dev, 0);
593bda55b6aSAlexander Motin 	if ((ch->flags & ATA_NO_SLAVE) == 0)
594bda55b6aSAlexander Motin 		ata_sata_phy_check_events(dev, 1);
595bda55b6aSAlexander Motin 
596bda55b6aSAlexander Motin 	return ata_pci_status(dev);
597bda55b6aSAlexander Motin }
598bda55b6aSAlexander Motin 
599bda55b6aSAlexander Motin static int
ata_intel_sata_ahci_read(device_t dev,int port,int reg,u_int32_t * result)600f1bfc8abSAlexander Motin ata_intel_sata_ahci_read(device_t dev, int port, int reg, u_int32_t *result)
601f1bfc8abSAlexander Motin {
602f1bfc8abSAlexander Motin 	struct ata_pci_controller *ctlr;
603f1bfc8abSAlexander Motin 	struct ata_channel *ch;
604f1bfc8abSAlexander Motin 	device_t parent;
605f1bfc8abSAlexander Motin 	u_char *smap;
606f1bfc8abSAlexander Motin 	int offset;
607f1bfc8abSAlexander Motin 
608f1bfc8abSAlexander Motin 	parent = device_get_parent(dev);
609f1bfc8abSAlexander Motin 	ctlr = device_get_softc(parent);
610f1bfc8abSAlexander Motin 	ch = device_get_softc(dev);
611f1bfc8abSAlexander Motin 	port = (port == 1) ? 1 : 0;
612dd60e051SAlexander Motin 	smap = ATA_INTEL_SMAP(ctlr, ch);
613f1bfc8abSAlexander Motin 	offset = 0x100 + smap[port] * 0x80;
614f1bfc8abSAlexander Motin 	switch (reg) {
615f1bfc8abSAlexander Motin 	case ATA_SSTATUS:
616f1bfc8abSAlexander Motin 	    reg = 0x28;
617f1bfc8abSAlexander Motin 	    break;
618f1bfc8abSAlexander Motin 	case ATA_SCONTROL:
619f1bfc8abSAlexander Motin 	    reg = 0x2c;
620f1bfc8abSAlexander Motin 	    break;
621f1bfc8abSAlexander Motin 	case ATA_SERROR:
622f1bfc8abSAlexander Motin 	    reg = 0x30;
623f1bfc8abSAlexander Motin 	    break;
624f1bfc8abSAlexander Motin 	default:
625f1bfc8abSAlexander Motin 	    return (EINVAL);
626f1bfc8abSAlexander Motin 	}
627f1bfc8abSAlexander Motin 	*result = ATA_INL(ctlr->r_res2, offset + reg);
628f1bfc8abSAlexander Motin 	return (0);
629f1bfc8abSAlexander Motin }
630f1bfc8abSAlexander Motin 
631f1bfc8abSAlexander Motin static int
ata_intel_sata_cscr_read(device_t dev,int port,int reg,u_int32_t * result)632bda55b6aSAlexander Motin ata_intel_sata_cscr_read(device_t dev, int port, int reg, u_int32_t *result)
633bda55b6aSAlexander Motin {
634bda55b6aSAlexander Motin 	struct ata_pci_controller *ctlr;
635bda55b6aSAlexander Motin 	struct ata_channel *ch;
636bda55b6aSAlexander Motin 	device_t parent;
637bda55b6aSAlexander Motin 	u_char *smap;
638bda55b6aSAlexander Motin 
639bda55b6aSAlexander Motin 	parent = device_get_parent(dev);
640bda55b6aSAlexander Motin 	ctlr = device_get_softc(parent);
641bda55b6aSAlexander Motin 	ch = device_get_softc(dev);
642dd60e051SAlexander Motin 	smap = ATA_INTEL_SMAP(ctlr, ch);
643bda55b6aSAlexander Motin 	port = (port == 1) ? 1 : 0;
644bda55b6aSAlexander Motin 	switch (reg) {
645bda55b6aSAlexander Motin 	case ATA_SSTATUS:
646bda55b6aSAlexander Motin 	    reg = 0;
647bda55b6aSAlexander Motin 	    break;
648bda55b6aSAlexander Motin 	case ATA_SERROR:
649bda55b6aSAlexander Motin 	    reg = 1;
650bda55b6aSAlexander Motin 	    break;
651bda55b6aSAlexander Motin 	case ATA_SCONTROL:
652bda55b6aSAlexander Motin 	    reg = 2;
653bda55b6aSAlexander Motin 	    break;
654bda55b6aSAlexander Motin 	default:
655bda55b6aSAlexander Motin 	    return (EINVAL);
656bda55b6aSAlexander Motin 	}
657dd60e051SAlexander Motin 	ATA_INTEL_LOCK(ctlr);
658bda55b6aSAlexander Motin 	pci_write_config(parent, 0xa0,
659bda55b6aSAlexander Motin 	    0x50 + smap[port] * 0x10 + reg * 4, 4);
660bda55b6aSAlexander Motin 	*result = pci_read_config(parent, 0xa4, 4);
661dd60e051SAlexander Motin 	ATA_INTEL_UNLOCK(ctlr);
662bda55b6aSAlexander Motin 	return (0);
663bda55b6aSAlexander Motin }
664bda55b6aSAlexander Motin 
665bda55b6aSAlexander Motin static int
ata_intel_sata_sidpr_read(device_t dev,int port,int reg,u_int32_t * result)666bda55b6aSAlexander Motin ata_intel_sata_sidpr_read(device_t dev, int port, int reg, u_int32_t *result)
667bda55b6aSAlexander Motin {
668bda55b6aSAlexander Motin 	struct ata_pci_controller *ctlr;
669bda55b6aSAlexander Motin 	struct ata_channel *ch;
670bda55b6aSAlexander Motin 	device_t parent;
671bda55b6aSAlexander Motin 
672bda55b6aSAlexander Motin 	parent = device_get_parent(dev);
673bda55b6aSAlexander Motin 	ctlr = device_get_softc(parent);
674bda55b6aSAlexander Motin 	ch = device_get_softc(dev);
675bda55b6aSAlexander Motin 	port = (port == 1) ? 1 : 0;
676bda55b6aSAlexander Motin 	switch (reg) {
677bda55b6aSAlexander Motin 	case ATA_SSTATUS:
678bda55b6aSAlexander Motin 	    reg = 0;
679bda55b6aSAlexander Motin 	    break;
680bda55b6aSAlexander Motin 	case ATA_SCONTROL:
681bda55b6aSAlexander Motin 	    reg = 1;
682bda55b6aSAlexander Motin 	    break;
683bda55b6aSAlexander Motin 	case ATA_SERROR:
684bda55b6aSAlexander Motin 	    reg = 2;
685bda55b6aSAlexander Motin 	    break;
686bda55b6aSAlexander Motin 	default:
687bda55b6aSAlexander Motin 	    return (EINVAL);
688bda55b6aSAlexander Motin 	}
689dd60e051SAlexander Motin 	ATA_INTEL_LOCK(ctlr);
690bda55b6aSAlexander Motin 	ATA_IDX_OUTL(ch, ATA_IDX_ADDR, ((ch->unit * 2 + port) << 8) + reg);
691bda55b6aSAlexander Motin 	*result = ATA_IDX_INL(ch, ATA_IDX_DATA);
692dd60e051SAlexander Motin 	ATA_INTEL_UNLOCK(ctlr);
693bda55b6aSAlexander Motin 	return (0);
694bda55b6aSAlexander Motin }
695bda55b6aSAlexander Motin 
696bda55b6aSAlexander Motin static int
ata_intel_sata_ahci_write(device_t dev,int port,int reg,u_int32_t value)697f1bfc8abSAlexander Motin ata_intel_sata_ahci_write(device_t dev, int port, int reg, u_int32_t value)
698f1bfc8abSAlexander Motin {
699f1bfc8abSAlexander Motin 	struct ata_pci_controller *ctlr;
700f1bfc8abSAlexander Motin 	struct ata_channel *ch;
701f1bfc8abSAlexander Motin 	device_t parent;
702f1bfc8abSAlexander Motin 	u_char *smap;
703f1bfc8abSAlexander Motin 	int offset;
704f1bfc8abSAlexander Motin 
705f1bfc8abSAlexander Motin 	parent = device_get_parent(dev);
706f1bfc8abSAlexander Motin 	ctlr = device_get_softc(parent);
707f1bfc8abSAlexander Motin 	ch = device_get_softc(dev);
708f1bfc8abSAlexander Motin 	port = (port == 1) ? 1 : 0;
709dd60e051SAlexander Motin 	smap = ATA_INTEL_SMAP(ctlr, ch);
710f1bfc8abSAlexander Motin 	offset = 0x100 + smap[port] * 0x80;
711f1bfc8abSAlexander Motin 	switch (reg) {
712f1bfc8abSAlexander Motin 	case ATA_SSTATUS:
713f1bfc8abSAlexander Motin 	    reg = 0x28;
714f1bfc8abSAlexander Motin 	    break;
715f1bfc8abSAlexander Motin 	case ATA_SCONTROL:
716f1bfc8abSAlexander Motin 	    reg = 0x2c;
717f1bfc8abSAlexander Motin 	    break;
718f1bfc8abSAlexander Motin 	case ATA_SERROR:
719f1bfc8abSAlexander Motin 	    reg = 0x30;
720f1bfc8abSAlexander Motin 	    break;
721f1bfc8abSAlexander Motin 	default:
722f1bfc8abSAlexander Motin 	    return (EINVAL);
723f1bfc8abSAlexander Motin 	}
724f1bfc8abSAlexander Motin 	ATA_OUTL(ctlr->r_res2, offset + reg, value);
725f1bfc8abSAlexander Motin 	return (0);
726f1bfc8abSAlexander Motin }
727f1bfc8abSAlexander Motin 
728f1bfc8abSAlexander Motin static int
ata_intel_sata_cscr_write(device_t dev,int port,int reg,u_int32_t value)729bda55b6aSAlexander Motin ata_intel_sata_cscr_write(device_t dev, int port, int reg, u_int32_t value)
730bda55b6aSAlexander Motin {
731bda55b6aSAlexander Motin 	struct ata_pci_controller *ctlr;
732bda55b6aSAlexander Motin 	struct ata_channel *ch;
733bda55b6aSAlexander Motin 	device_t parent;
734bda55b6aSAlexander Motin 	u_char *smap;
735bda55b6aSAlexander Motin 
736bda55b6aSAlexander Motin 	parent = device_get_parent(dev);
737bda55b6aSAlexander Motin 	ctlr = device_get_softc(parent);
738bda55b6aSAlexander Motin 	ch = device_get_softc(dev);
739dd60e051SAlexander Motin 	smap = ATA_INTEL_SMAP(ctlr, ch);
740bda55b6aSAlexander Motin 	port = (port == 1) ? 1 : 0;
741bda55b6aSAlexander Motin 	switch (reg) {
742bda55b6aSAlexander Motin 	case ATA_SSTATUS:
743bda55b6aSAlexander Motin 	    reg = 0;
744bda55b6aSAlexander Motin 	    break;
745bda55b6aSAlexander Motin 	case ATA_SERROR:
746bda55b6aSAlexander Motin 	    reg = 1;
747bda55b6aSAlexander Motin 	    break;
748bda55b6aSAlexander Motin 	case ATA_SCONTROL:
749bda55b6aSAlexander Motin 	    reg = 2;
750bda55b6aSAlexander Motin 	    break;
751bda55b6aSAlexander Motin 	default:
752bda55b6aSAlexander Motin 	    return (EINVAL);
753bda55b6aSAlexander Motin 	}
754dd60e051SAlexander Motin 	ATA_INTEL_LOCK(ctlr);
755bda55b6aSAlexander Motin 	pci_write_config(parent, 0xa0,
756bda55b6aSAlexander Motin 	    0x50 + smap[port] * 0x10 + reg * 4, 4);
757bda55b6aSAlexander Motin 	pci_write_config(parent, 0xa4, value, 4);
758dd60e051SAlexander Motin 	ATA_INTEL_UNLOCK(ctlr);
759bda55b6aSAlexander Motin 	return (0);
760bda55b6aSAlexander Motin }
761bda55b6aSAlexander Motin 
762bda55b6aSAlexander Motin static int
ata_intel_sata_sidpr_write(device_t dev,int port,int reg,u_int32_t value)763bda55b6aSAlexander Motin ata_intel_sata_sidpr_write(device_t dev, int port, int reg, u_int32_t value)
764bda55b6aSAlexander Motin {
765bda55b6aSAlexander Motin 	struct ata_pci_controller *ctlr;
766bda55b6aSAlexander Motin 	struct ata_channel *ch;
767bda55b6aSAlexander Motin 	device_t parent;
768bda55b6aSAlexander Motin 
769bda55b6aSAlexander Motin 	parent = device_get_parent(dev);
770bda55b6aSAlexander Motin 	ctlr = device_get_softc(parent);
771bda55b6aSAlexander Motin 	ch = device_get_softc(dev);
772bda55b6aSAlexander Motin 	port = (port == 1) ? 1 : 0;
773bda55b6aSAlexander Motin 	switch (reg) {
774bda55b6aSAlexander Motin 	case ATA_SSTATUS:
775bda55b6aSAlexander Motin 	    reg = 0;
776bda55b6aSAlexander Motin 	    break;
777bda55b6aSAlexander Motin 	case ATA_SCONTROL:
778bda55b6aSAlexander Motin 	    reg = 1;
779bda55b6aSAlexander Motin 	    break;
780bda55b6aSAlexander Motin 	case ATA_SERROR:
781bda55b6aSAlexander Motin 	    reg = 2;
782bda55b6aSAlexander Motin 	    break;
783bda55b6aSAlexander Motin 	default:
784bda55b6aSAlexander Motin 	    return (EINVAL);
785bda55b6aSAlexander Motin 	}
786dd60e051SAlexander Motin 	ATA_INTEL_LOCK(ctlr);
787bda55b6aSAlexander Motin 	ATA_IDX_OUTL(ch, ATA_IDX_ADDR, ((ch->unit * 2 + port) << 8) + reg);
788bda55b6aSAlexander Motin 	ATA_IDX_OUTL(ch, ATA_IDX_DATA, value);
789dd60e051SAlexander Motin 	ATA_INTEL_UNLOCK(ctlr);
790bda55b6aSAlexander Motin 	return (0);
79113014ca0SSøren Schmidt }
79213014ca0SSøren Schmidt 
79313014ca0SSøren Schmidt static int
ata_intel_sata_sidpr_test(device_t dev)794f49c6198SAlexander Motin ata_intel_sata_sidpr_test(device_t dev)
795f49c6198SAlexander Motin {
796f49c6198SAlexander Motin 	struct ata_channel *ch = device_get_softc(dev);
797f49c6198SAlexander Motin 	int port;
798f49c6198SAlexander Motin 	uint32_t val;
799f49c6198SAlexander Motin 
800f49c6198SAlexander Motin 	port = (ch->flags & ATA_NO_SLAVE) ? 0 : 1;
801f49c6198SAlexander Motin 	for (; port >= 0; port--) {
802f49c6198SAlexander Motin 		ata_intel_sata_sidpr_read(dev, port, ATA_SCONTROL, &val);
803f49c6198SAlexander Motin 		if ((val & ATA_SC_IPM_MASK) ==
804f49c6198SAlexander Motin 		    (ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER))
805f49c6198SAlexander Motin 			return (1);
806f49c6198SAlexander Motin 		val |= ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER;
807f49c6198SAlexander Motin 		ata_intel_sata_sidpr_write(dev, port, ATA_SCONTROL, val);
808f49c6198SAlexander Motin 		ata_intel_sata_sidpr_read(dev, port, ATA_SCONTROL, &val);
809f49c6198SAlexander Motin 		if ((val & ATA_SC_IPM_MASK) ==
810f49c6198SAlexander Motin 		    (ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER))
811f49c6198SAlexander Motin 			return (1);
812f49c6198SAlexander Motin 	}
813f49c6198SAlexander Motin 	if (bootverbose)
814f49c6198SAlexander Motin 		device_printf(dev,
815f49c6198SAlexander Motin 		    "SControl registers are not functional: %08x\n", val);
816f49c6198SAlexander Motin 	return (0);
817f49c6198SAlexander Motin }
818f49c6198SAlexander Motin 
819f49c6198SAlexander Motin static int
ata_intel_31244_ch_attach(device_t dev)82004ff88ceSAlexander Motin ata_intel_31244_ch_attach(device_t dev)
82113014ca0SSøren Schmidt {
82213014ca0SSøren Schmidt     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
82313014ca0SSøren Schmidt     struct ata_channel *ch = device_get_softc(dev);
82413014ca0SSøren Schmidt     int i;
82513014ca0SSøren Schmidt     int ch_offset;
82613014ca0SSøren Schmidt 
82778d15416SAlexander Motin     ata_pci_dmainit(dev);
82878d15416SAlexander Motin 
82913014ca0SSøren Schmidt     ch_offset = 0x200 + ch->unit * 0x200;
83013014ca0SSøren Schmidt 
83113014ca0SSøren Schmidt     for (i = ATA_DATA; i < ATA_MAX_RES; i++)
83213014ca0SSøren Schmidt 	ch->r_io[i].res = ctlr->r_res2;
83313014ca0SSøren Schmidt 
83413014ca0SSøren Schmidt     /* setup ATA registers */
83513014ca0SSøren Schmidt     ch->r_io[ATA_DATA].offset = ch_offset + 0x00;
83613014ca0SSøren Schmidt     ch->r_io[ATA_FEATURE].offset = ch_offset + 0x06;
83713014ca0SSøren Schmidt     ch->r_io[ATA_COUNT].offset = ch_offset + 0x08;
83813014ca0SSøren Schmidt     ch->r_io[ATA_SECTOR].offset = ch_offset + 0x0c;
83913014ca0SSøren Schmidt     ch->r_io[ATA_CYL_LSB].offset = ch_offset + 0x10;
84013014ca0SSøren Schmidt     ch->r_io[ATA_CYL_MSB].offset = ch_offset + 0x14;
84113014ca0SSøren Schmidt     ch->r_io[ATA_DRIVE].offset = ch_offset + 0x18;
84213014ca0SSøren Schmidt     ch->r_io[ATA_COMMAND].offset = ch_offset + 0x1d;
84313014ca0SSøren Schmidt     ch->r_io[ATA_ERROR].offset = ch_offset + 0x04;
84413014ca0SSøren Schmidt     ch->r_io[ATA_STATUS].offset = ch_offset + 0x1c;
84513014ca0SSøren Schmidt     ch->r_io[ATA_ALTSTAT].offset = ch_offset + 0x28;
84613014ca0SSøren Schmidt     ch->r_io[ATA_CONTROL].offset = ch_offset + 0x29;
84713014ca0SSøren Schmidt 
84813014ca0SSøren Schmidt     /* setup DMA registers */
84913014ca0SSøren Schmidt     ch->r_io[ATA_SSTATUS].offset = ch_offset + 0x100;
85013014ca0SSøren Schmidt     ch->r_io[ATA_SERROR].offset = ch_offset + 0x104;
85113014ca0SSøren Schmidt     ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x108;
85213014ca0SSøren Schmidt 
85313014ca0SSøren Schmidt     /* setup SATA registers */
85413014ca0SSøren Schmidt     ch->r_io[ATA_BMCMD_PORT].offset = ch_offset + 0x70;
85513014ca0SSøren Schmidt     ch->r_io[ATA_BMSTAT_PORT].offset = ch_offset + 0x72;
85613014ca0SSøren Schmidt     ch->r_io[ATA_BMDTP_PORT].offset = ch_offset + 0x74;
85713014ca0SSøren Schmidt 
85813014ca0SSøren Schmidt     ch->flags |= ATA_NO_SLAVE;
859066f913aSAlexander Motin     ch->flags |= ATA_SATA;
86013014ca0SSøren Schmidt     ata_pci_hw(dev);
86113014ca0SSøren Schmidt     ch->hw.status = ata_intel_31244_status;
86213014ca0SSøren Schmidt     ch->hw.tf_write = ata_intel_31244_tf_write;
86313014ca0SSøren Schmidt 
86413014ca0SSøren Schmidt     /* enable PHY state change interrupt */
86513014ca0SSøren Schmidt     ATA_OUTL(ctlr->r_res2, 0x4,
86613014ca0SSøren Schmidt 	     ATA_INL(ctlr->r_res2, 0x04) | (0x01 << (ch->unit << 3)));
86713014ca0SSøren Schmidt     return 0;
86813014ca0SSøren Schmidt }
86913014ca0SSøren Schmidt 
87013014ca0SSøren Schmidt static int
ata_intel_31244_ch_detach(device_t dev)87178d15416SAlexander Motin ata_intel_31244_ch_detach(device_t dev)
87278d15416SAlexander Motin {
87378d15416SAlexander Motin 
87478d15416SAlexander Motin     ata_pci_dmafini(dev);
87578d15416SAlexander Motin     return (0);
87678d15416SAlexander Motin }
87778d15416SAlexander Motin 
87878d15416SAlexander Motin static int
ata_intel_31244_status(device_t dev)87913014ca0SSøren Schmidt ata_intel_31244_status(device_t dev)
88013014ca0SSøren Schmidt {
88113014ca0SSøren Schmidt     /* do we have any PHY events ? */
882bda55b6aSAlexander Motin     ata_sata_phy_check_events(dev, -1);
88313014ca0SSøren Schmidt 
88413014ca0SSøren Schmidt     /* any drive action to take care of ? */
88513014ca0SSøren Schmidt     return ata_pci_status(dev);
88613014ca0SSøren Schmidt }
88713014ca0SSøren Schmidt 
88813014ca0SSøren Schmidt static void
ata_intel_31244_tf_write(struct ata_request * request)88913014ca0SSøren Schmidt ata_intel_31244_tf_write(struct ata_request *request)
89013014ca0SSøren Schmidt {
891ebbb35baSAlexander Motin     struct ata_channel *ch = device_get_softc(request->parent);
89213014ca0SSøren Schmidt 
893ebbb35baSAlexander Motin     if (request->flags & ATA_R_48BIT) {
89413014ca0SSøren Schmidt 	ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
89513014ca0SSøren Schmidt 	ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
89613014ca0SSøren Schmidt 	ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) |
89713014ca0SSøren Schmidt 				      (request->u.ata.lba & 0x00ff));
89813014ca0SSøren Schmidt 	ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) |
89913014ca0SSøren Schmidt 				       ((request->u.ata.lba >> 8) & 0x00ff));
90013014ca0SSøren Schmidt 	ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) |
90113014ca0SSøren Schmidt 				       ((request->u.ata.lba >> 16) & 0x00ff));
902ebbb35baSAlexander Motin 	ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(request->unit));
90313014ca0SSøren Schmidt     }
90413014ca0SSøren Schmidt     else {
90513014ca0SSøren Schmidt 	ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
90613014ca0SSøren Schmidt 	ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count);
90713014ca0SSøren Schmidt 	    ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
90813014ca0SSøren Schmidt 	    ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
90913014ca0SSøren Schmidt 	    ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
91013014ca0SSøren Schmidt 	    ATA_IDX_OUTB(ch, ATA_DRIVE,
911ebbb35baSAlexander Motin 			 ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit) |
91213014ca0SSøren Schmidt 			 ((request->u.ata.lba >> 24) & 0x0f));
91313014ca0SSøren Schmidt     }
91413014ca0SSøren Schmidt }
91513014ca0SSøren Schmidt 
91613014ca0SSøren Schmidt static void
ata_intel_31244_reset(device_t dev)91713014ca0SSøren Schmidt ata_intel_31244_reset(device_t dev)
91813014ca0SSøren Schmidt {
919aecfe194SAlexander Motin     struct ata_channel *ch = device_get_softc(dev);
920aecfe194SAlexander Motin 
9219cf4fe2eSAlexander Motin     if (ata_sata_phy_reset(dev, -1, 1))
92213014ca0SSøren Schmidt 	ata_generic_reset(dev);
923aecfe194SAlexander Motin     else
924aecfe194SAlexander Motin 	ch->devices = 0;
92513014ca0SSøren Schmidt }
92613014ca0SSøren Schmidt 
92713014ca0SSøren Schmidt ATA_DECLARE_DRIVER(ata_intel);
928