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