xref: /dragonfly/sys/dev/disk/nata/chipsets/ata-intel.c (revision c1d8f36a)
1a1917f14Szrj /*-
2a1917f14Szrj  * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
3a1917f14Szrj  * All rights reserved.
4a1917f14Szrj  *
5a1917f14Szrj  * Redistribution and use in source and binary forms, with or without
6a1917f14Szrj  * modification, are permitted provided that the following conditions
7a1917f14Szrj  * are met:
8a1917f14Szrj  * 1. Redistributions of source code must retain the above copyright
9a1917f14Szrj  *    notice, this list of conditions and the following disclaimer,
10a1917f14Szrj  *    without modification, immediately at the beginning of the file.
11a1917f14Szrj  * 2. Redistributions in binary form must reproduce the above copyright
12a1917f14Szrj  *    notice, this list of conditions and the following disclaimer in the
13a1917f14Szrj  *    documentation and/or other materials provided with the distribution.
14a1917f14Szrj  *
15a1917f14Szrj  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16a1917f14Szrj  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17a1917f14Szrj  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18a1917f14Szrj  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19a1917f14Szrj  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20a1917f14Szrj  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21a1917f14Szrj  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22a1917f14Szrj  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23a1917f14Szrj  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24a1917f14Szrj  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25a1917f14Szrj  */
26a1917f14Szrj 
27a1917f14Szrj /* local prototypes */
28a1917f14Szrj static int ata_intel_chipinit(device_t dev);
29a1917f14Szrj static int ata_intel_allocate(device_t dev);
30a1917f14Szrj static void ata_intel_reset(device_t dev);
31a1917f14Szrj static void ata_intel_old_setmode(device_t dev, int mode);
32a1917f14Szrj static void ata_intel_new_setmode(device_t dev, int mode);
33a1917f14Szrj static void ata_intel_sata_setmode(device_t dev, int mode);
34a1917f14Szrj static int ata_intel_31244_allocate(device_t dev);
35a1917f14Szrj static int ata_intel_31244_status(device_t dev);
3637c16061Szrj static void ata_intel_31244_tf_write(struct ata_request *request);
37a1917f14Szrj static void ata_intel_31244_reset(device_t dev);
38a1917f14Szrj 
39853eb30dSzrj /* misc defines */
40853eb30dSzrj #define INTEL_AHCI	1
41853eb30dSzrj 
42a1917f14Szrj /*
43a1917f14Szrj  * Intel chipset support functions
44a1917f14Szrj  */
45a1917f14Szrj int
ata_intel_ident(device_t dev)46a1917f14Szrj ata_intel_ident(device_t dev)
47a1917f14Szrj {
48a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(dev);
4959503772Szrj     static const struct ata_chip_id ids[] =
50560012aaSzrj     {{ ATA_I82371FB,     0,          0, 2, ATA_WDMA2, "PIIX" },
51560012aaSzrj      { ATA_I82371SB,     0,          0, 2, ATA_WDMA2, "PIIX3" },
52560012aaSzrj      { ATA_I82371AB,     0,          0, 2, ATA_UDMA2, "PIIX4" },
53560012aaSzrj      { ATA_I82443MX,     0,          0, 2, ATA_UDMA2, "PIIX4" },
54560012aaSzrj      { ATA_I82451NX,     0,          0, 2, ATA_UDMA2, "PIIX4" },
55560012aaSzrj      { ATA_I82801AB,     0,          0, 2, ATA_UDMA2, "ICH0" },
56560012aaSzrj      { ATA_I82801AA,     0,          0, 2, ATA_UDMA4, "ICH" },
57560012aaSzrj      { ATA_I82372FB,     0,          0, 2, ATA_UDMA4, "ICH" },
58560012aaSzrj      { ATA_I82801BA,     0,          0, 2, ATA_UDMA5, "ICH2" },
59560012aaSzrj      { ATA_I82801BA_1,   0,          0, 2, ATA_UDMA5, "ICH2" },
60560012aaSzrj      { ATA_I82801CA,     0,          0, 2, ATA_UDMA5, "ICH3" },
61560012aaSzrj      { ATA_I82801CA_1,   0,          0, 2, ATA_UDMA5, "ICH3" },
62560012aaSzrj      { ATA_I82801DB,     0,          0, 2, ATA_UDMA5, "ICH4" },
63560012aaSzrj      { ATA_I82801DB_1,   0,          0, 2, ATA_UDMA5, "ICH4" },
64560012aaSzrj      { ATA_I82801EB,     0,          0, 2, ATA_UDMA5, "ICH5" },
65560012aaSzrj      { ATA_I82801EB_S1,  0,          0, 2, ATA_SA150, "ICH5" },
66560012aaSzrj      { ATA_I82801EB_R1,  0,          0, 2, ATA_SA150, "ICH5" },
67560012aaSzrj      { ATA_I6300ESB,     0,          0, 2, ATA_UDMA5, "6300ESB" },
68560012aaSzrj      { ATA_I6300ESB_S1,  0,          0, 2, ATA_SA150, "6300ESB" },
69560012aaSzrj      { ATA_I6300ESB_R1,  0,          0, 2, ATA_SA150, "6300ESB" },
70560012aaSzrj      { ATA_I82801FB,     0,          0, 2, ATA_UDMA5, "ICH6" },
71853eb30dSzrj      { ATA_I82801FB_S1,  0, INTEL_AHCI, 0, ATA_SA150, "ICH6" },
72853eb30dSzrj      { ATA_I82801FB_R1,  0, INTEL_AHCI, 0, ATA_SA150, "ICH6" },
73853eb30dSzrj      { ATA_I82801FBM,    0, INTEL_AHCI, 0, ATA_SA150, "ICH6M" },
74560012aaSzrj      { ATA_I82801GB,     0,          0, 1, ATA_UDMA5, "ICH7" },
75853eb30dSzrj      { ATA_I82801GB_S1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH7" },
76853eb30dSzrj      { ATA_I82801GB_R1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH7" },
77853eb30dSzrj      { ATA_I82801GB_AH,  0, INTEL_AHCI, 0, ATA_SA300, "ICH7" },
78560012aaSzrj      { ATA_I82801GBM_S1, 0, INTEL_AHCI, 0, ATA_SA150, "ICH7M" },
79560012aaSzrj      { ATA_I82801GBM_R1, 0, INTEL_AHCI, 0, ATA_SA150, "ICH7M" },
80560012aaSzrj      { ATA_I82801GBM_AH, 0, INTEL_AHCI, 0, ATA_SA150, "ICH7M" },
81560012aaSzrj      { ATA_I63XXESB2,    0,          0, 1, ATA_UDMA5, "63XXESB2" },
82853eb30dSzrj      { ATA_I63XXESB2_S1, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" },
83853eb30dSzrj      { ATA_I63XXESB2_S2, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" },
84853eb30dSzrj      { ATA_I63XXESB2_R1, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" },
85853eb30dSzrj      { ATA_I63XXESB2_R2, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" },
86853eb30dSzrj      { ATA_I82801HB_S1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH8" },
87853eb30dSzrj      { ATA_I82801HB_S2,  0, INTEL_AHCI, 0, ATA_SA300, "ICH8" },
88853eb30dSzrj      { ATA_I82801HB_R1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH8" },
89853eb30dSzrj      { ATA_I82801HB_AH4, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" },
90853eb30dSzrj      { ATA_I82801HB_AH6, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" },
91*c1d8f36aSzrj      { ATA_I82801HBM,    0,          0, 1, ATA_UDMA5, "ICH8M" },
92*c1d8f36aSzrj      { ATA_I82801HBM_S1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8M" },
93853eb30dSzrj      { ATA_I82801HBM_S2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8M" },
94853eb30dSzrj      { ATA_I82801HBM_S3, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8M" },
95853eb30dSzrj      { ATA_I82801IB_S1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
96853eb30dSzrj      { ATA_I82801IB_S2,  0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
97853eb30dSzrj      { ATA_I82801IB_AH2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
98853eb30dSzrj      { ATA_I82801IB_AH4, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
99853eb30dSzrj      { ATA_I82801IB_AH6, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
100*c1d8f36aSzrj      { ATA_I82801IB_R1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
101*c1d8f36aSzrj      { ATA_I82801JIB_S1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
102*c1d8f36aSzrj      { ATA_I82801JIB_AH, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
103*c1d8f36aSzrj      { ATA_I82801JIB_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
104*c1d8f36aSzrj      { ATA_I82801JIB_S2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
105*c1d8f36aSzrj      { ATA_I82801JD_S1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
106*c1d8f36aSzrj      { ATA_I82801JD_AH,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
107*c1d8f36aSzrj      { ATA_I82801JD_R1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
108*c1d8f36aSzrj      { ATA_I82801JD_S2,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
109*c1d8f36aSzrj      { ATA_I82801JI_S1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
110*c1d8f36aSzrj      { ATA_I82801JI_AH,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
111*c1d8f36aSzrj      { ATA_I82801JI_R1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
112*c1d8f36aSzrj      { ATA_I82801JI_S2,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
113*c1d8f36aSzrj      { ATA_I31244,       0,          0, 2, ATA_SA150, "31244" },
114a1917f14Szrj      { 0, 0, 0, 0, 0, 0}};
115a1917f14Szrj 
11659503772Szrj     if (pci_get_vendor(dev) != ATA_INTEL_ID)
117a1917f14Szrj 	return ENXIO;
118a1917f14Szrj 
11959503772Szrj     if (!(ctlr->chip = ata_match_chip(dev, ids)))
12059503772Szrj 	return ENXIO;
12159503772Szrj 
12259503772Szrj     ata_set_desc(dev);
123a1917f14Szrj     ctlr->chipinit = ata_intel_chipinit;
124a1917f14Szrj     return 0;
125a1917f14Szrj }
126a1917f14Szrj 
127a1917f14Szrj static int
ata_intel_chipinit(device_t dev)128a1917f14Szrj ata_intel_chipinit(device_t dev)
129a1917f14Szrj {
130a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(dev);
131a1917f14Szrj 
13243156ad7Szrj     if (ata_setup_interrupt(dev, ata_generic_intr))
133a1917f14Szrj 	return ENXIO;
134a1917f14Szrj 
135a1917f14Szrj     /* good old PIIX needs special treatment (not implemented) */
136a1917f14Szrj     if (ctlr->chip->chipid == ATA_I82371FB) {
137a1917f14Szrj 	ctlr->setmode = ata_intel_old_setmode;
138a1917f14Szrj     }
139a1917f14Szrj 
140a1917f14Szrj     /* the intel 31244 needs special care if in DPA mode */
141a1917f14Szrj     else if (ctlr->chip->chipid == ATA_I31244) {
142a1917f14Szrj 	if (pci_get_subclass(dev) != PCIS_STORAGE_IDE) {
143a1917f14Szrj 	    ctlr->r_type2 = SYS_RES_MEMORY;
144a1917f14Szrj 	    ctlr->r_rid2 = PCIR_BAR(0);
145a1917f14Szrj 	    if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
146a1917f14Szrj 							&ctlr->r_rid2,
147a1917f14Szrj 							RF_ACTIVE))) {
148a1917f14Szrj 		ata_teardown_interrupt(dev);
149a1917f14Szrj 		return ENXIO;
150a1917f14Szrj 	    }
151a1917f14Szrj 	    ctlr->channels = 4;
152a1917f14Szrj 	    ctlr->allocate = ata_intel_31244_allocate;
153a1917f14Szrj 	    ctlr->reset = ata_intel_31244_reset;
154a1917f14Szrj 	}
155a1917f14Szrj 	ctlr->setmode = ata_sata_setmode;
156a1917f14Szrj     }
157a1917f14Szrj 
158a1917f14Szrj     /* non SATA intel chips goes here */
159a1917f14Szrj     else if (ctlr->chip->max_dma < ATA_SA150) {
160*c1d8f36aSzrj 	ctlr->channels = ctlr->chip->cfg2;
161a1917f14Szrj 	ctlr->allocate = ata_intel_allocate;
162a1917f14Szrj 	ctlr->setmode = ata_intel_new_setmode;
163a1917f14Szrj     }
164a1917f14Szrj 
165a1917f14Szrj     /* SATA parts can be either compat or AHCI */
166a1917f14Szrj     else {
167a1917f14Szrj 	/* force all ports active "the legacy way" */
168a1917f14Szrj 	pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f, 2);
169a1917f14Szrj 
170a1917f14Szrj 	ctlr->allocate = ata_intel_allocate;
171a1917f14Szrj 	ctlr->reset = ata_intel_reset;
172a1917f14Szrj 
173a1917f14Szrj 	/*
17413b0cf9eSzrj 	 * if we have AHCI capability and AHCI or RAID mode enabled
17513b0cf9eSzrj 	 * in BIOS we try for AHCI mode
176a1917f14Szrj 	 */
177853eb30dSzrj 	if ((ctlr->chip->cfg1 == INTEL_AHCI) &&
178a1917f14Szrj 	    (pci_read_config(dev, 0x90, 1) & 0xc0) &&
179a1917f14Szrj 	    (ata_ahci_chipinit(dev) != ENXIO))
180a1917f14Szrj 	    return 0;
181a1917f14Szrj 
182a1917f14Szrj 	/* if BAR(5) is IO it should point to SATA interface registers */
183a1917f14Szrj 	ctlr->r_type2 = SYS_RES_IOPORT;
184a1917f14Szrj 	ctlr->r_rid2 = PCIR_BAR(5);
185a1917f14Szrj 	if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
186a1917f14Szrj 						   &ctlr->r_rid2, RF_ACTIVE)))
187a1917f14Szrj 	    ctlr->setmode = ata_intel_sata_setmode;
188a1917f14Szrj 	else
189a1917f14Szrj 	    ctlr->setmode = ata_sata_setmode;
190a1917f14Szrj 
191a1917f14Szrj 	/* enable PCI interrupt */
192a1917f14Szrj 	pci_write_config(dev, PCIR_COMMAND,
193a1917f14Szrj 			 pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
194a1917f14Szrj     }
195a1917f14Szrj     return 0;
196a1917f14Szrj }
197a1917f14Szrj 
198a1917f14Szrj static int
ata_intel_allocate(device_t dev)199a1917f14Szrj ata_intel_allocate(device_t dev)
200a1917f14Szrj {
201a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
202a1917f14Szrj     struct ata_channel *ch = device_get_softc(dev);
203a1917f14Szrj 
204a1917f14Szrj     /* setup the usual register normal pci style */
205a1917f14Szrj     if (ata_pci_allocate(dev))
206a1917f14Szrj 	return ENXIO;
207a1917f14Szrj 
208a1917f14Szrj     /* if r_res2 is valid it points to SATA interface registers */
209a1917f14Szrj     if (ctlr->r_res2) {
210a1917f14Szrj 	ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;
211a1917f14Szrj 	ch->r_io[ATA_IDX_ADDR].offset = 0x00;
212a1917f14Szrj 	ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2;
213a1917f14Szrj 	ch->r_io[ATA_IDX_DATA].offset = 0x04;
214a1917f14Szrj     }
215a1917f14Szrj 
216a1917f14Szrj     ch->flags |= ATA_ALWAYS_DMASTAT;
217a1917f14Szrj     return 0;
218a1917f14Szrj }
219a1917f14Szrj 
220a1917f14Szrj static void
ata_intel_reset(device_t dev)221a1917f14Szrj ata_intel_reset(device_t dev)
222a1917f14Szrj {
223a1917f14Szrj     device_t parent = device_get_parent(dev);
224a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(parent);
225a1917f14Szrj     struct ata_channel *ch = device_get_softc(dev);
226a1917f14Szrj     int mask, timeout;
227a1917f14Szrj 
228a1917f14Szrj     /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
229a1917f14Szrj     if (ctlr->chip->cfg1) {
230a1917f14Szrj 	mask = (0x0005 << ch->unit);
231a1917f14Szrj     }
232a1917f14Szrj     else {
233a1917f14Szrj 	/* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
234a1917f14Szrj 	if (pci_read_config(parent, 0x90, 1) & 0x04)
235a1917f14Szrj 	    mask = 0x0003;
236a1917f14Szrj 	else {
237a1917f14Szrj 	    mask = (0x0001 << ch->unit);
238a1917f14Szrj 	    /* XXX SOS should be in intel_allocate if we grow it */
239a1917f14Szrj 	    ch->flags |= ATA_NO_SLAVE;
240a1917f14Szrj 	}
241a1917f14Szrj     }
242a1917f14Szrj     pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) & ~mask, 2);
243a1917f14Szrj     DELAY(10);
244a1917f14Szrj     pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) | mask, 2);
245a1917f14Szrj 
246a1917f14Szrj     /* wait up to 1 sec for "connect well" */
247a1917f14Szrj     for (timeout = 0; timeout < 100 ; timeout++) {
248a1917f14Szrj 	if (((pci_read_config(parent, 0x92, 2) & (mask << 4)) == (mask << 4)) &&
249a1917f14Szrj 	    (ATA_IDX_INB(ch, ATA_STATUS) != 0xff))
250a1917f14Szrj 	    break;
251a1917f14Szrj 	ata_udelay(10000);
252a1917f14Szrj     }
253a1917f14Szrj     ata_generic_reset(dev);
254a1917f14Szrj }
255a1917f14Szrj 
256a1917f14Szrj static void
ata_intel_old_setmode(device_t dev,int mode)257a1917f14Szrj ata_intel_old_setmode(device_t dev, int mode)
258a1917f14Szrj {
259a1917f14Szrj     /* NOT YET */
260a1917f14Szrj }
261a1917f14Szrj 
262a1917f14Szrj static void
ata_intel_new_setmode(device_t dev,int mode)263a1917f14Szrj ata_intel_new_setmode(device_t dev, int mode)
264a1917f14Szrj {
265a1917f14Szrj     device_t gparent = GRANDPARENT(dev);
266a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(gparent);
267a1917f14Szrj     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
268a1917f14Szrj     struct ata_device *atadev = device_get_softc(dev);
2692458a87aSzrj     int devno = (ch->unit << 1) + atadev->unit;
270a1917f14Szrj     u_int32_t reg40 = pci_read_config(gparent, 0x40, 4);
271a1917f14Szrj     u_int8_t reg44 = pci_read_config(gparent, 0x44, 1);
272a1917f14Szrj     u_int8_t reg48 = pci_read_config(gparent, 0x48, 1);
273a1917f14Szrj     u_int16_t reg4a = pci_read_config(gparent, 0x4a, 2);
274a1917f14Szrj     u_int16_t reg54 = pci_read_config(gparent, 0x54, 2);
275a1917f14Szrj     u_int32_t mask40 = 0, new40 = 0;
276a1917f14Szrj     u_int8_t mask44 = 0, new44 = 0;
277a1917f14Szrj     int error;
27859503772Szrj 	static const uint8_t timings[] =
279*c1d8f36aSzrj 			 { 0x00, 0x00, 0x10, 0x21, 0x23, 0x00, 0x21, 0x23,
280a1917f14Szrj 			   0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23 };
281a1917f14Szrj 			/* PIO0  PIO1  PIO2  PIO3  PIO4  WDMA0 WDMA1 WDMA2 */
282a1917f14Szrj 			/* UDMA0 UDMA1 UDMA2 UDMA3 UDMA4 UDMA5 UDMA6 */
283*c1d8f36aSzrj 	static const uint8_t utimings[] =
284*c1d8f36aSzrj 			 { 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 };
285a1917f14Szrj 
286a1917f14Szrj     mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);
287a1917f14Szrj 
288a1917f14Szrj     if ( mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) {
289a1917f14Szrj 	ata_print_cable(dev, "controller");
290a1917f14Szrj 	mode = ATA_UDMA2;
291a1917f14Szrj     }
292a1917f14Szrj 
293a1917f14Szrj     error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
294a1917f14Szrj 
295a1917f14Szrj     if (bootverbose)
296a1917f14Szrj 	device_printf(dev, "%ssetting %s on %s chip\n",
297a1917f14Szrj 		      (error) ? "FAILURE " : "",
298a1917f14Szrj 		      ata_mode2str(mode), ctlr->chip->text);
299954c7881Szrj     if (!error) {
300a1917f14Szrj 	if (mode >= ATA_UDMA0) {
301*c1d8f36aSzrj 	    pci_write_config(gparent, 0x48, reg48 | (0x0001 << devno), 2);
302*c1d8f36aSzrj 	    pci_write_config(gparent, 0x4a,
303*c1d8f36aSzrj 			     (reg4a & ~(0x3 << (devno << 2))) |
304*c1d8f36aSzrj 			     (utimings[mode & ATA_MODE_MASK] << (devno<<2)), 2);
305a1917f14Szrj 	}
306*c1d8f36aSzrj 	else {
307*c1d8f36aSzrj 	    pci_write_config(gparent, 0x48, reg48 & ~(0x0001 << devno), 2);
308*c1d8f36aSzrj 	    pci_write_config(gparent, 0x4a, (reg4a & ~(0x3 << (devno << 2))),2);
309*c1d8f36aSzrj 	}
310a1917f14Szrj 	reg54 |= 0x0400;	/* set vendor specific bit */
311*c1d8f36aSzrj 	if (mode >= ATA_UDMA3)
312*c1d8f36aSzrj 	    reg54 |= (0x1 << devno);
313*c1d8f36aSzrj 	else
314*c1d8f36aSzrj 	    reg54 &= ~(0x1 << devno);
315a1917f14Szrj 	if (mode >= ATA_UDMA5)
316a1917f14Szrj 	    reg54 |= (0x1000 << devno);
317*c1d8f36aSzrj 	else
318*c1d8f36aSzrj 	    reg54 &= ~(0x1000 << devno);
319a1917f14Szrj 
320a1917f14Szrj 	pci_write_config(gparent, 0x54, reg54, 2);
321a1917f14Szrj 
322*c1d8f36aSzrj 	reg40 &= ~0x00ff00ff;
323*c1d8f36aSzrj 	reg40 |= 0x40774077;
324*c1d8f36aSzrj 
325954c7881Szrj 	/* Modify reg40 according to the table */
326a1917f14Szrj 	if (atadev->unit == ATA_MASTER) {
327a1917f14Szrj 	    mask40 = 0x3300;
328a1917f14Szrj 	    new40 = timings[ata_mode2idx(mode)] << 8;
329a1917f14Szrj 	}
330a1917f14Szrj 	else {
331a1917f14Szrj 	    mask44 = 0x0f;
332a1917f14Szrj 	    new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) |
333a1917f14Szrj 		    (timings[ata_mode2idx(mode)] & 0x03);
334a1917f14Szrj 	}
335a1917f14Szrj 
336954c7881Szrj 	/* Primary or Secondary controller */
337a1917f14Szrj 	if (ch->unit) {
338a1917f14Szrj 	    mask40 <<= 16;
339a1917f14Szrj 	    new40 <<= 16;
340a1917f14Szrj 	    mask44 <<= 4;
341a1917f14Szrj 	    new44 <<= 4;
342a1917f14Szrj 	}
343a1917f14Szrj 	pci_write_config(gparent, 0x40, (reg40 & ~mask40) | new40, 4);
344a1917f14Szrj 	pci_write_config(gparent, 0x44, (reg44 & ~mask44) | new44, 1);
345a1917f14Szrj 
346a1917f14Szrj 	atadev->mode = mode;
347a1917f14Szrj     }
348954c7881Szrj }
349a1917f14Szrj 
350a1917f14Szrj static void
ata_intel_sata_setmode(device_t dev,int mode)351a1917f14Szrj ata_intel_sata_setmode(device_t dev, int mode)
352a1917f14Szrj {
353a1917f14Szrj     struct ata_device *atadev = device_get_softc(dev);
354a1917f14Szrj 
355a1917f14Szrj     if (atadev->param.satacapabilities != 0x0000 &&
356a1917f14Szrj 	atadev->param.satacapabilities != 0xffff) {
357a1917f14Szrj 
358a1917f14Szrj 	struct ata_channel *ch = device_get_softc(device_get_parent(dev));
3592458a87aSzrj 	int devno = (ch->unit << 1) + atadev->unit;
360a1917f14Szrj 
361a1917f14Szrj 	/* on some drives we need to set the transfer mode */
362a1917f14Szrj 	ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
363a1917f14Szrj 		       ata_limit_mode(dev, mode, ATA_UDMA6));
364a1917f14Szrj 
365a1917f14Szrj 	/* set ATA_SSTATUS register offset */
366a1917f14Szrj 	ATA_IDX_OUTL(ch, ATA_IDX_ADDR, devno * 0x100);
367a1917f14Szrj 
368a1917f14Szrj 	/* query SATA STATUS for the speed */
369a1917f14Szrj 	if ((ATA_IDX_INL(ch, ATA_IDX_DATA) & ATA_SS_CONWELL_MASK) ==
370a1917f14Szrj 	    ATA_SS_CONWELL_GEN2)
371a1917f14Szrj 	    atadev->mode = ATA_SA300;
372a1917f14Szrj 	else
373a1917f14Szrj 	    atadev->mode = ATA_SA150;
374a1917f14Szrj     }
375a1917f14Szrj     else {
376a1917f14Szrj 	mode = ata_limit_mode(dev, mode, ATA_UDMA5);
377a1917f14Szrj 	if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode))
378a1917f14Szrj 	    atadev->mode = mode;
379a1917f14Szrj     }
380a1917f14Szrj }
381a1917f14Szrj 
382a1917f14Szrj static int
ata_intel_31244_allocate(device_t dev)383a1917f14Szrj ata_intel_31244_allocate(device_t dev)
384a1917f14Szrj {
385a1917f14Szrj     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
386a1917f14Szrj     struct ata_channel *ch = device_get_softc(dev);
387a1917f14Szrj     int i;
388a1917f14Szrj     int ch_offset;
389a1917f14Szrj 
390a1917f14Szrj     ch_offset = 0x200 + ch->unit * 0x200;
391a1917f14Szrj 
392a1917f14Szrj     for (i = ATA_DATA; i < ATA_MAX_RES; i++)
393a1917f14Szrj 	ch->r_io[i].res = ctlr->r_res2;
394a1917f14Szrj 
395a1917f14Szrj     /* setup ATA registers */
396a1917f14Szrj     ch->r_io[ATA_DATA].offset = ch_offset + 0x00;
397a1917f14Szrj     ch->r_io[ATA_FEATURE].offset = ch_offset + 0x06;
398a1917f14Szrj     ch->r_io[ATA_COUNT].offset = ch_offset + 0x08;
399a1917f14Szrj     ch->r_io[ATA_SECTOR].offset = ch_offset + 0x0c;
400a1917f14Szrj     ch->r_io[ATA_CYL_LSB].offset = ch_offset + 0x10;
401a1917f14Szrj     ch->r_io[ATA_CYL_MSB].offset = ch_offset + 0x14;
402a1917f14Szrj     ch->r_io[ATA_DRIVE].offset = ch_offset + 0x18;
403a1917f14Szrj     ch->r_io[ATA_COMMAND].offset = ch_offset + 0x1d;
404a1917f14Szrj     ch->r_io[ATA_ERROR].offset = ch_offset + 0x04;
405a1917f14Szrj     ch->r_io[ATA_STATUS].offset = ch_offset + 0x1c;
406a1917f14Szrj     ch->r_io[ATA_ALTSTAT].offset = ch_offset + 0x28;
407a1917f14Szrj     ch->r_io[ATA_CONTROL].offset = ch_offset + 0x29;
408a1917f14Szrj 
409a1917f14Szrj     /* setup DMA registers */
410a1917f14Szrj     ch->r_io[ATA_SSTATUS].offset = ch_offset + 0x100;
411a1917f14Szrj     ch->r_io[ATA_SERROR].offset = ch_offset + 0x104;
412a1917f14Szrj     ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x108;
413a1917f14Szrj 
414a1917f14Szrj     /* setup SATA registers */
415a1917f14Szrj     ch->r_io[ATA_BMCMD_PORT].offset = ch_offset + 0x70;
416a1917f14Szrj     ch->r_io[ATA_BMSTAT_PORT].offset = ch_offset + 0x72;
417a1917f14Szrj     ch->r_io[ATA_BMDTP_PORT].offset = ch_offset + 0x74;
418a1917f14Szrj 
419a1917f14Szrj     ch->flags |= ATA_NO_SLAVE;
420a1917f14Szrj     ata_pci_hw(dev);
421a1917f14Szrj     ch->hw.status = ata_intel_31244_status;
42237c16061Szrj     ch->hw.tf_write = ata_intel_31244_tf_write;
423a1917f14Szrj 
424a1917f14Szrj     /* enable PHY state change interrupt */
425a1917f14Szrj     ATA_OUTL(ctlr->r_res2, 0x4,
426a1917f14Szrj 	     ATA_INL(ctlr->r_res2, 0x04) | (0x01 << (ch->unit << 3)));
427a1917f14Szrj     return 0;
428a1917f14Szrj }
429a1917f14Szrj 
430a1917f14Szrj static int
ata_intel_31244_status(device_t dev)431a1917f14Szrj ata_intel_31244_status(device_t dev)
432a1917f14Szrj {
433a1917f14Szrj     /* do we have any PHY events ? */
434a1917f14Szrj     ata_sata_phy_check_events(dev);
435a1917f14Szrj 
436a1917f14Szrj     /* any drive action to take care of ? */
437a1917f14Szrj     return ata_pci_status(dev);
438a1917f14Szrj }
439a1917f14Szrj 
44037c16061Szrj static void
ata_intel_31244_tf_write(struct ata_request * request)44137c16061Szrj ata_intel_31244_tf_write(struct ata_request *request)
442a1917f14Szrj {
443a1917f14Szrj     struct ata_channel *ch = device_get_softc(device_get_parent(request->dev));
444a1917f14Szrj     struct ata_device *atadev = device_get_softc(request->dev);
445a1917f14Szrj 
446c04da965Szrj     if (atadev->flags & ATA_D_48BIT_ACTIVE) {
447a1917f14Szrj 	ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
448a1917f14Szrj 	ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
449c04da965Szrj 	ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) |
450c04da965Szrj 				      (request->u.ata.lba & 0x00ff));
451c04da965Szrj 	ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) |
452c04da965Szrj 				       ((request->u.ata.lba >> 8) & 0x00ff));
453c04da965Szrj 	ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) |
454c04da965Szrj 				       ((request->u.ata.lba >> 16) & 0x00ff));
4552458a87aSzrj 	ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit));
456a1917f14Szrj     }
457c04da965Szrj     else {
45837c16061Szrj 	ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
45937c16061Szrj 	ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count);
46037c16061Szrj 	if (atadev->flags & ATA_D_USE_CHS) {
46137c16061Szrj 	    int heads, sectors;
46237c16061Szrj 
46337c16061Szrj 	    if (atadev->param.atavalid & ATA_FLAG_54_58) {
46437c16061Szrj 		heads = atadev->param.current_heads;
46537c16061Szrj 		sectors = atadev->param.current_sectors;
46637c16061Szrj 	    }
46737c16061Szrj 	    else {
46837c16061Szrj 		heads = atadev->param.heads;
46937c16061Szrj 		sectors = atadev->param.sectors;
47037c16061Szrj 	    }
47137c16061Szrj 	    ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
47237c16061Szrj 	    ATA_IDX_OUTB(ch, ATA_CYL_LSB,
47337c16061Szrj 			 (request->u.ata.lba / (sectors * heads)));
47437c16061Szrj 	    ATA_IDX_OUTB(ch, ATA_CYL_MSB,
47537c16061Szrj 			 (request->u.ata.lba / (sectors * heads)) >> 8);
4762458a87aSzrj 	    ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) |
47737c16061Szrj 			 (((request->u.ata.lba% (sectors * heads)) /
47837c16061Szrj 			   sectors) & 0xf));
47937c16061Szrj 	}
48037c16061Szrj 	else {
48137c16061Szrj 	    ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
48237c16061Szrj 	    ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
48337c16061Szrj 	    ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
48437c16061Szrj 	    ATA_IDX_OUTB(ch, ATA_DRIVE,
4852458a87aSzrj 			 ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) |
48637c16061Szrj 			 ((request->u.ata.lba >> 24) & 0x0f));
48737c16061Szrj 	}
488c04da965Szrj     }
489c04da965Szrj }
490a1917f14Szrj 
491a1917f14Szrj static void
ata_intel_31244_reset(device_t dev)492a1917f14Szrj ata_intel_31244_reset(device_t dev)
493a1917f14Szrj {
494a1917f14Szrj     if (ata_sata_phy_reset(dev))
495a1917f14Szrj 	ata_generic_reset(dev);
496a1917f14Szrj }
497