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.
29 #include <sys/param.h>
30 #include <sys/systm.h>
32 #include <sys/malloc.h>
34 #include <sys/taskqueue.h>
36 #include <sys/mplock2.h> /* for {get,rel}_mplock() */
43 * SATA support functions
46 ata_sata_phy_event(void *context, int dummy)
48 struct ata_connect_task *tp = (struct ata_connect_task *)context;
49 struct ata_channel *ch = device_get_softc(tp->dev);
54 if (tp->action == ATA_C_ATTACH) {
56 device_printf(tp->dev, "CONNECTED\n");
58 ata_identify(tp->dev);
60 if (tp->action == ATA_C_DETACH) {
61 if (!device_get_children(tp->dev, &children, &nchildren)) {
62 for (i = 0; i < nchildren; i++)
64 device_delete_child(tp->dev, children[i]);
65 kfree(children, M_TEMP);
67 lockmgr(&ch->state_mtx, LK_EXCLUSIVE);
69 lockmgr(&ch->state_mtx, LK_RELEASE);
71 device_printf(tp->dev, "DISCONNECTED\n");
78 ata_sata_phy_check_events(device_t dev)
80 struct ata_channel *ch = device_get_softc(dev);
81 u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR);
83 /* clear error bits/interrupt */
84 ATA_IDX_OUTL(ch, ATA_SERROR, error);
86 /* do we have any events flagged ? */
88 struct ata_connect_task *tp;
89 u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS);
91 /* if we have a connection event deal with it */
92 if ((error & ATA_SE_PHY_CHANGED) &&
93 (tp = (struct ata_connect_task *)
94 kmalloc(sizeof(struct ata_connect_task),
95 M_ATA, M_INTWAIT | M_ZERO))) {
97 if (((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) ||
98 ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)) {
100 device_printf(ch->dev, "CONNECT requested\n");
101 tp->action = ATA_C_ATTACH;
105 device_printf(ch->dev, "DISCONNECT requested\n");
106 tp->action = ATA_C_DETACH;
109 TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
110 taskqueue_enqueue(taskqueue_thread[mycpuid], &tp->task);
116 ata_sata_connect(struct ata_channel *ch)
121 /* wait up to 1 second for "connect well" */
122 for (timeout = 0; timeout < 100 ; timeout++) {
123 status = ATA_IDX_INL(ch, ATA_SSTATUS);
124 if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
125 (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)
129 if (timeout >= 100) {
131 device_printf(ch->dev, "SATA connect status=%08x\n", status);
135 device_printf(ch->dev, "SATA connect time=%dms\n", timeout * 10);
137 /* clear SATA error register */
138 ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
144 ata_sata_phy_reset(device_t dev)
146 struct ata_channel *ch = device_get_softc(dev);
149 if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE)
150 return ata_sata_connect(ch);
152 for (retry = 0; retry < 10; retry++) {
153 for (loop = 0; loop < 10; loop++) {
154 ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_RESET);
156 if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) ==
161 for (loop = 0; loop < 10; loop++) {
162 ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_IDLE |
163 ATA_SC_IPM_DIS_PARTIAL |
164 ATA_SC_IPM_DIS_SLUMBER);
166 if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0)
167 return ata_sata_connect(ch);
174 ata_sata_setmode(device_t dev, int mode)
176 struct ata_device *atadev = device_get_softc(dev);
179 * if we detect that the device isn't a real SATA device we limit
180 * the transfer mode to UDMA5/ATA100.
181 * this works around the problems some devices has with the
182 * Marvell 88SX8030 SATA->PATA converters and UDMA6/ATA133.
184 if (atadev->param.satacapabilities != 0x0000 &&
185 atadev->param.satacapabilities != 0xffff) {
186 struct ata_channel *ch = device_get_softc(device_get_parent(dev));
188 /* on some drives we need to set the transfer mode */
189 ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
190 ata_limit_mode(dev, mode, ATA_UDMA6));
192 /* query SATA STATUS for the speed */
193 if (ch->r_io[ATA_SSTATUS].res &&
194 ((ATA_IDX_INL(ch, ATA_SSTATUS) & ATA_SS_CONWELL_MASK) ==
195 ATA_SS_CONWELL_GEN2))
196 atadev->mode = ATA_SA300;
198 atadev->mode = ATA_SA150;
201 mode = ata_limit_mode(dev, mode, ATA_UDMA5);
202 if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode))
208 ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis)
210 struct ata_device *atadev = device_get_softc(request->dev);
212 if (request->flags & ATA_R_ATAPI) {
213 fis[0] = 0x27; /* host to device */
214 fis[1] = 0x80 | (atadev->unit & 0x0f);
215 fis[2] = ATA_PACKET_CMD;
216 if (request->flags & (ATA_R_READ | ATA_R_WRITE))
219 fis[5] = request->transfersize;
220 fis[6] = request->transfersize >> 8;
223 fis[15] = ATA_A_4BIT;
227 ata_modify_if_48bit(request);
228 fis[0] = 0x27; /* host to device */
229 fis[1] = 0x80 | (atadev->unit & 0x0f);
230 fis[2] = request->u.ata.command;
231 fis[3] = request->u.ata.feature;
232 fis[4] = request->u.ata.lba;
233 fis[5] = request->u.ata.lba >> 8;
234 fis[6] = request->u.ata.lba >> 16;
236 if (!(atadev->flags & ATA_D_48BIT_ACTIVE))
237 fis[7] |= (ATA_D_IBM | (request->u.ata.lba >> 24 & 0x0f));
238 fis[8] = request->u.ata.lba >> 24;
239 fis[9] = request->u.ata.lba >> 32;
240 fis[10] = request->u.ata.lba >> 40;
241 fis[11] = request->u.ata.feature >> 8;
242 fis[12] = request->u.ata.count;
243 fis[13] = request->u.ata.count >> 8;
244 fis[15] = ATA_A_4BIT;