xref: /freebsd/sys/dev/ata/ata-sata.c (revision 39beb93c3f8bdbf72a61fda42300b5ebed7390c8)
1 /*-
2  * Copyright (c) 1998 - 2008 S�ren Schmidt <sos@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification, immediately at the beginning of the file.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include "opt_ata.h"
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/ata.h>
35 #include <sys/bus.h>
36 #include <sys/endian.h>
37 #include <sys/malloc.h>
38 #include <sys/lock.h>
39 #include <sys/mutex.h>
40 #include <sys/sema.h>
41 #include <sys/taskqueue.h>
42 #include <vm/uma.h>
43 #include <machine/stdarg.h>
44 #include <machine/resource.h>
45 #include <machine/bus.h>
46 #include <sys/rman.h>
47 #include <dev/pci/pcivar.h>
48 #include <dev/pci/pcireg.h>
49 #include <dev/ata/ata-all.h>
50 #include <dev/ata/ata-pci.h>
51 #include <ata_if.h>
52 
53 void
54 ata_sata_phy_check_events(device_t dev)
55 {
56     struct ata_channel *ch = device_get_softc(dev);
57     u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR);
58 
59     /* clear error bits/interrupt */
60     ATA_IDX_OUTL(ch, ATA_SERROR, error);
61 
62     /* if we have a connection event deal with it */
63     if (error & ATA_SE_PHY_CHANGED) {
64 	if (bootverbose) {
65 	    u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS);
66 	    if (((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) ||
67 		((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)) {
68 		    device_printf(dev, "CONNECT requested\n");
69 	    } else
70 		    device_printf(dev, "DISCONNECT requested\n");
71 	}
72 	taskqueue_enqueue(taskqueue_thread, &ch->conntask);
73     }
74 }
75 
76 static int
77 ata_sata_connect(struct ata_channel *ch)
78 {
79     u_int32_t status;
80     int timeout;
81 
82     /* wait up to 1 second for "connect well" */
83     for (timeout = 0; timeout < 100 ; timeout++) {
84 	status = ATA_IDX_INL(ch, ATA_SSTATUS);
85 	if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
86 	    (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)
87 	    break;
88 	ata_udelay(10000);
89     }
90     if (timeout >= 100) {
91 	if (bootverbose)
92 	    device_printf(ch->dev, "SATA connect status=%08x\n", status);
93 	return 0;
94     }
95     if (bootverbose)
96 	device_printf(ch->dev, "SATA connect time=%dms\n", timeout * 10);
97 
98     /* clear SATA error register */
99     ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
100 
101     return 1;
102 }
103 
104 int
105 ata_sata_phy_reset(device_t dev)
106 {
107     struct ata_channel *ch = device_get_softc(dev);
108     int loop, retry;
109 
110     if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE)
111 	return ata_sata_connect(ch);
112 
113     for (retry = 0; retry < 10; retry++) {
114 	for (loop = 0; loop < 10; loop++) {
115 	    ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_RESET);
116 	    ata_udelay(100);
117 	    if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) ==
118 		ATA_SC_DET_RESET)
119 		break;
120 	}
121 	ata_udelay(5000);
122 	for (loop = 0; loop < 10; loop++) {
123 	    ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_IDLE |
124 					   ATA_SC_IPM_DIS_PARTIAL |
125 					   ATA_SC_IPM_DIS_SLUMBER);
126 	    ata_udelay(100);
127 	    if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0)
128 		return ata_sata_connect(ch);
129 	}
130     }
131     return 0;
132 }
133 
134 void
135 ata_sata_setmode(device_t dev, int mode)
136 {
137     struct ata_device *atadev = device_get_softc(dev);
138 
139     /*
140      * if we detect that the device isn't a real SATA device we limit
141      * the transfer mode to UDMA5/ATA100.
142      * this works around the problems some devices has with the
143      * Marvell 88SX8030 SATA->PATA converters and UDMA6/ATA133.
144      */
145     if (atadev->param.satacapabilities != 0x0000 &&
146 	atadev->param.satacapabilities != 0xffff) {
147 	struct ata_channel *ch = device_get_softc(device_get_parent(dev));
148 
149 	/* on some drives we need to set the transfer mode */
150 	ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
151 		       ata_limit_mode(dev, mode, ATA_UDMA6));
152 
153 	/* query SATA STATUS for the speed */
154         if (ch->r_io[ATA_SSTATUS].res &&
155 	   ((ATA_IDX_INL(ch, ATA_SSTATUS) & ATA_SS_CONWELL_MASK) ==
156 	    ATA_SS_CONWELL_GEN2))
157 	    atadev->mode = ATA_SA300;
158 	else
159 	    atadev->mode = ATA_SA150;
160     }
161     else {
162 	mode = ata_limit_mode(dev, mode, ATA_UDMA5);
163 	if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode))
164 	    atadev->mode = mode;
165     }
166 }
167 
168 int
169 ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis)
170 {
171     struct ata_device *atadev = device_get_softc(request->dev);
172 
173     if (request->flags & ATA_R_ATAPI) {
174 	fis[0] = 0x27;  		/* host to device */
175 	fis[1] = 0x80 | (atadev->unit & 0x0f);
176 	fis[2] = ATA_PACKET_CMD;
177 	if (request->flags & (ATA_R_READ | ATA_R_WRITE))
178 	    fis[3] = ATA_F_DMA;
179 	else {
180 	    fis[5] = request->transfersize;
181 	    fis[6] = request->transfersize >> 8;
182 	}
183 	fis[7] = ATA_D_LBA;
184 	fis[15] = ATA_A_4BIT;
185 	return 20;
186     }
187     else {
188 	ata_modify_if_48bit(request);
189 	fis[0] = 0x27;			/* host to device */
190 	fis[1] = 0x80 | (atadev->unit & 0x0f);
191 	fis[2] = request->u.ata.command;
192 	fis[3] = request->u.ata.feature;
193 	fis[4] = request->u.ata.lba;
194 	fis[5] = request->u.ata.lba >> 8;
195 	fis[6] = request->u.ata.lba >> 16;
196 	fis[7] = ATA_D_LBA;
197 	if (!(atadev->flags & ATA_D_48BIT_ACTIVE))
198 	    fis[7] |= (ATA_D_IBM | (request->u.ata.lba >> 24 & 0x0f));
199 	fis[8] = request->u.ata.lba >> 24;
200 	fis[9] = request->u.ata.lba >> 32;
201 	fis[10] = request->u.ata.lba >> 40;
202 	fis[11] = request->u.ata.feature >> 8;
203 	fis[12] = request->u.ata.count;
204 	fis[13] = request->u.ata.count >> 8;
205 	fis[15] = ATA_A_4BIT;
206 	return 20;
207     }
208     return 0;
209 }
210 
211 void
212 ata_pm_identify(device_t dev)
213 {
214     struct ata_channel *ch = device_get_softc(dev);
215     u_int32_t pm_chipid, pm_revision, pm_ports;
216     int port;
217 
218     /* get PM vendor & product data */
219     if (ch->hw.pm_read(dev, ATA_PM, 0, &pm_chipid)) {
220 	device_printf(dev, "error getting PM vendor data\n");
221 	return;
222     }
223 
224     /* get PM revision data */
225     if (ch->hw.pm_read(dev, ATA_PM, 1, &pm_revision)) {
226 	device_printf(dev, "error getting PM revison data\n");
227 	return;
228     }
229 
230     /* get number of HW ports on the PM */
231     if (ch->hw.pm_read(dev, ATA_PM, 2, &pm_ports)) {
232 	device_printf(dev, "error getting PM port info\n");
233 	return;
234     }
235     pm_ports &= 0x0000000f;
236 
237     /* chip specific quirks */
238     switch (pm_chipid) {
239     case 0x37261095:
240 	/* Some of these bogusly reports 6 ports */
241 	pm_ports = 5;
242 	device_printf(dev, "SiI 3726 r%x Portmultiplier with %d ports\n",
243 		      pm_revision, pm_ports);
244 	break;
245 
246     default:
247 	device_printf(dev, "Portmultiplier (id=%08x rev=%x) with %d ports\n",
248 		      pm_chipid, pm_revision, pm_ports);
249     }
250 
251     /* realloc space for needed DMA slots */
252     ch->dma.dma_slots = pm_ports;
253 
254     /* reset all ports and register if anything connected */
255     for (port=0; port < pm_ports; port++) {
256 	u_int32_t signature, status;
257 	int timeout;
258 
259 	if (ch->hw.pm_write(dev, port, 2, ATA_SC_DET_RESET)) {
260 	    device_printf(dev, "p%d: writing ATA_SC_DET_RESET failed\n", port);
261 	    continue;
262 	}
263 
264 	ata_udelay(5000);
265 
266 	if (ch->hw.pm_write(dev, port, 2, ATA_SC_DET_IDLE)) {
267 	    device_printf(dev, "p%d: writing ATA_SC_DET_idle failed\n", port);
268 	    continue;
269 	}
270 
271 	ata_udelay(5000);
272 
273 	/* wait up to 1 second for "connect well" */
274 	for (timeout = 0; timeout < 100 ; timeout++) {
275 	    ch->hw.pm_read(dev, port, 0, &status);
276 	    if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
277 		(status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)
278 		break;
279 	    ata_udelay(10000);
280 	}
281 	if (timeout >= 100) {
282 	    if (bootverbose)
283 		device_printf(dev, "p%d: connect status=%08x\n", port, status);
284 	    continue;
285 	}
286 	if (bootverbose)
287 	    device_printf(dev, "p%d: connect time %dms\n", port, timeout * 10);
288 
289 	/* clear SERROR register */
290 	ch->hw.pm_write(dev, port, 1, 0xffffffff);
291 
292 	signature = ch->hw.softreset(dev, port);
293 
294 	if (bootverbose)
295 	    device_printf(dev, "p%d: SIGNATURE=%08x\n", port, signature);
296 
297 	/* figure out whats there */
298 	switch (signature >> 16) {
299 	case 0x0000:
300 	    ch->devices |= (ATA_ATA_MASTER << port);
301 	    continue;
302 	case 0xeb14:
303 	    ch->devices |= (ATA_ATAPI_MASTER << port);
304 	    continue;
305 	}
306     }
307 }
308