2 * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
36 #include <sys/endian.h>
37 #include <sys/malloc.h>
39 #include <sys/mutex.h>
41 #include <sys/taskqueue.h>
43 #include <machine/stdarg.h>
44 #include <machine/resource.h>
45 #include <machine/bus.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>
54 * SATA support functions
57 ata_sata_phy_event(void *context, int dummy)
59 struct ata_connect_task *tp = (struct ata_connect_task *)context;
60 struct ata_channel *ch = device_get_softc(tp->dev);
64 mtx_lock(&Giant); /* newbus suckage it needs Giant */
65 if (tp->action == ATA_C_ATTACH) {
67 device_printf(tp->dev, "CONNECTED\n");
69 ata_identify(tp->dev);
71 if (tp->action == ATA_C_DETACH) {
72 if (!device_get_children(tp->dev, &children, &nchildren)) {
73 for (i = 0; i < nchildren; i++)
75 device_delete_child(tp->dev, children[i]);
76 free(children, M_TEMP);
78 mtx_lock(&ch->state_mtx);
80 mtx_unlock(&ch->state_mtx);
82 device_printf(tp->dev, "DISCONNECTED\n");
84 mtx_unlock(&Giant); /* suckage code dealt with, release Giant */
89 ata_sata_phy_check_events(device_t dev)
91 struct ata_channel *ch = device_get_softc(dev);
92 u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR);
94 /* clear error bits/interrupt */
95 ATA_IDX_OUTL(ch, ATA_SERROR, error);
97 /* do we have any events flagged ? */
99 struct ata_connect_task *tp;
100 u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS);
102 /* if we have a connection event deal with it */
103 if ((error & ATA_SE_PHY_CHANGED) &&
104 (tp = (struct ata_connect_task *)
105 malloc(sizeof(struct ata_connect_task),
106 M_ATA, M_NOWAIT | M_ZERO))) {
108 if (((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) ||
109 ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)) {
111 device_printf(dev, "CONNECT requested\n");
112 tp->action = ATA_C_ATTACH;
116 device_printf(dev, "DISCONNECT requested\n");
117 tp->action = ATA_C_DETACH;
120 TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
121 taskqueue_enqueue(taskqueue_thread, &tp->task);
127 ata_sata_connect(struct ata_channel *ch)
132 /* wait up to 1 second for "connect well" */
133 for (timeout = 0; timeout < 100 ; timeout++) {
134 status = ATA_IDX_INL(ch, ATA_SSTATUS);
135 if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
136 (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)
140 if (timeout >= 100) {
142 device_printf(ch->dev, "SATA connect status=%08x\n", status);
146 device_printf(ch->dev, "SATA connect time=%dms\n", timeout * 10);
148 /* clear SATA error register */
149 ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
155 ata_sata_phy_reset(device_t dev)
157 struct ata_channel *ch = device_get_softc(dev);
160 if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE)
161 return ata_sata_connect(ch);
163 for (retry = 0; retry < 10; retry++) {
164 for (loop = 0; loop < 10; loop++) {
165 ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_RESET);
167 if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) ==
172 for (loop = 0; loop < 10; loop++) {
173 ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_IDLE |
174 ATA_SC_IPM_DIS_PARTIAL |
175 ATA_SC_IPM_DIS_SLUMBER);
177 if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0)
178 return ata_sata_connect(ch);
185 ata_sata_setmode(device_t dev, int mode)
187 struct ata_device *atadev = device_get_softc(dev);
190 * if we detect that the device isn't a real SATA device we limit
191 * the transfer mode to UDMA5/ATA100.
192 * this works around the problems some devices has with the
193 * Marvell 88SX8030 SATA->PATA converters and UDMA6/ATA133.
195 if (atadev->param.satacapabilities != 0x0000 &&
196 atadev->param.satacapabilities != 0xffff) {
197 struct ata_channel *ch = device_get_softc(device_get_parent(dev));
199 /* on some drives we need to set the transfer mode */
200 ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
201 ata_limit_mode(dev, mode, ATA_UDMA6));
203 /* query SATA STATUS for the speed */
204 if (ch->r_io[ATA_SSTATUS].res &&
205 ((ATA_IDX_INL(ch, ATA_SSTATUS) & ATA_SS_CONWELL_MASK) ==
206 ATA_SS_CONWELL_GEN2))
207 atadev->mode = ATA_SA300;
209 atadev->mode = ATA_SA150;
212 mode = ata_limit_mode(dev, mode, ATA_UDMA5);
213 if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode))
219 ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis)
221 struct ata_device *atadev = device_get_softc(request->dev);
223 if (request->flags & ATA_R_ATAPI) {
224 fis[0] = 0x27; /* host to device */
225 fis[1] = 0x80 | (atadev->unit & 0x0f);
226 fis[2] = ATA_PACKET_CMD;
227 if (request->flags & (ATA_R_READ | ATA_R_WRITE))
230 fis[5] = request->transfersize;
231 fis[6] = request->transfersize >> 8;
234 fis[15] = ATA_A_4BIT;
238 ata_modify_if_48bit(request);
239 fis[0] = 0x27; /* host to device */
240 fis[1] = 0x80 | (atadev->unit & 0x0f);
241 fis[2] = request->u.ata.command;
242 fis[3] = request->u.ata.feature;
243 fis[4] = request->u.ata.lba;
244 fis[5] = request->u.ata.lba >> 8;
245 fis[6] = request->u.ata.lba >> 16;
247 if (!(atadev->flags & ATA_D_48BIT_ACTIVE))
248 fis[7] |= (ATA_D_IBM | (request->u.ata.lba >> 24 & 0x0f));
249 fis[8] = request->u.ata.lba >> 24;
250 fis[9] = request->u.ata.lba >> 32;
251 fis[10] = request->u.ata.lba >> 40;
252 fis[11] = request->u.ata.feature >> 8;
253 fis[12] = request->u.ata.count;
254 fis[13] = request->u.ata.count >> 8;
255 fis[15] = ATA_A_4BIT;
262 ata_pm_identify(device_t dev)
264 struct ata_channel *ch = device_get_softc(dev);
265 u_int32_t pm_chipid, pm_revision, pm_ports;
268 /* get PM vendor & product data */
269 if (ch->hw.pm_read(dev, ATA_PM, 0, &pm_chipid)) {
270 device_printf(dev, "error getting PM vendor data\n");
274 /* get PM revision data */
275 if (ch->hw.pm_read(dev, ATA_PM, 1, &pm_revision)) {
276 device_printf(dev, "error getting PM revison data\n");
280 /* get number of HW ports on the PM */
281 if (ch->hw.pm_read(dev, ATA_PM, 2, &pm_ports)) {
282 device_printf(dev, "error getting PM port info\n");
285 pm_ports &= 0x0000000f;
287 /* chip specific quirks */
290 /* Some of these bogusly reports 6 ports */
292 device_printf(dev, "SiI 3726 r%x Portmultiplier with %d ports\n",
293 pm_revision, pm_ports);
297 device_printf(dev, "Portmultiplier (id=%08x rev=%x) with %d ports\n",
298 pm_chipid, pm_revision, pm_ports);
301 /* realloc space for needed DMA slots */
302 ch->dma.dma_slots = pm_ports;
304 /* reset all ports and register if anything connected */
305 for (port=0; port < pm_ports; port++) {
306 u_int32_t signature, status;
309 if (ch->hw.pm_write(dev, port, 2, ATA_SC_DET_RESET)) {
310 device_printf(dev, "p%d: writing ATA_SC_DET_RESET failed\n", port);
316 if (ch->hw.pm_write(dev, port, 2, ATA_SC_DET_IDLE)) {
317 device_printf(dev, "p%d: writing ATA_SC_DET_idle failed\n", port);
323 /* wait up to 1 second for "connect well" */
324 for (timeout = 0; timeout < 100 ; timeout++) {
325 ch->hw.pm_read(dev, port, 0, &status);
326 if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
327 (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)
331 if (timeout >= 100) {
333 device_printf(dev, "p%d: connect status=%08x\n", port, status);
337 device_printf(dev, "p%d: connect time %dms\n", port, timeout * 10);
339 /* clear SERROR register */
340 ch->hw.pm_write(dev, port, 1, 0xffffffff);
342 signature = ch->hw.softreset(dev, port);
345 device_printf(dev, "p%d: SIGNATURE=%08x\n", port, signature);
347 /* figure out whats there */
350 ch->devices |= (ATA_ATA_MASTER << port);
353 ch->devices |= (ATA_ATAPI_MASTER << port);