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 "opt_ata.h" 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/bus.h> 32 #include <sys/malloc.h> 33 #include <sys/lock.h> 34 #include <sys/taskqueue.h> 35 36 #include <sys/mplock2.h> /* for {get,rel}_mplock() */ 37 38 #include "ata-all.h" 39 #include "ata-pci.h" 40 #include "ata_if.h" 41 42 /* 43 * SATA support functions 44 */ 45 void 46 ata_sata_phy_event(void *context, int dummy) 47 { 48 struct ata_connect_task *tp = (struct ata_connect_task *)context; 49 struct ata_channel *ch = device_get_softc(tp->dev); 50 device_t *children; 51 int nchildren, i; 52 53 get_mplock(); 54 if (tp->action == ATA_C_ATTACH) { 55 if (bootverbose) 56 device_printf(tp->dev, "CONNECTED\n"); 57 ATA_RESET(tp->dev); 58 ata_identify(tp->dev); 59 } 60 if (tp->action == ATA_C_DETACH) { 61 if (!device_get_children(tp->dev, &children, &nchildren)) { 62 for (i = 0; i < nchildren; i++) 63 if (children[i]) 64 device_delete_child(tp->dev, children[i]); 65 kfree(children, M_TEMP); 66 } 67 lockmgr(&ch->state_mtx, LK_EXCLUSIVE); 68 ch->state = ATA_IDLE; 69 lockmgr(&ch->state_mtx, LK_RELEASE); 70 if (bootverbose) 71 device_printf(tp->dev, "DISCONNECTED\n"); 72 } 73 rel_mplock(); 74 kfree(tp, M_ATA); 75 } 76 77 void 78 ata_sata_phy_check_events(device_t dev) 79 { 80 struct ata_channel *ch = device_get_softc(dev); 81 u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR); 82 83 /* clear error bits/interrupt */ 84 ATA_IDX_OUTL(ch, ATA_SERROR, error); 85 86 /* do we have any events flagged ? */ 87 if (error) { 88 struct ata_connect_task *tp; 89 u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS); 90 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))) { 96 97 if (((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) || 98 ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)) { 99 if (bootverbose) 100 device_printf(ch->dev, "CONNECT requested\n"); 101 tp->action = ATA_C_ATTACH; 102 } 103 else { 104 if (bootverbose) 105 device_printf(ch->dev, "DISCONNECT requested\n"); 106 tp->action = ATA_C_DETACH; 107 } 108 tp->dev = ch->dev; 109 TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp); 110 taskqueue_enqueue(taskqueue_thread[mycpuid], &tp->task); 111 } 112 } 113 } 114 115 static int 116 ata_sata_connect(struct ata_channel *ch) 117 { 118 u_int32_t status; 119 int timeout; 120 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) 126 break; 127 ata_udelay(10000); 128 } 129 if (timeout >= 100) { 130 if (bootverbose) 131 device_printf(ch->dev, "SATA connect status=%08x\n", status); 132 return 0; 133 } 134 if (bootverbose) 135 device_printf(ch->dev, "SATA connect time=%dms\n", timeout * 10); 136 137 /* clear SATA error register */ 138 ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); 139 140 return 1; 141 } 142 143 int 144 ata_sata_phy_reset(device_t dev) 145 { 146 struct ata_channel *ch = device_get_softc(dev); 147 int loop, retry; 148 149 if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE) 150 return ata_sata_connect(ch); 151 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); 155 ata_udelay(100); 156 if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 157 ATA_SC_DET_RESET) 158 break; 159 } 160 ata_udelay(5000); 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); 165 ata_udelay(100); 166 if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0) 167 return ata_sata_connect(ch); 168 } 169 } 170 return 0; 171 } 172 173 void 174 ata_sata_setmode(device_t dev, int mode) 175 { 176 struct ata_device *atadev = device_get_softc(dev); 177 178 /* 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. 183 */ 184 if (atadev->param.satacapabilities != 0x0000 && 185 atadev->param.satacapabilities != 0xffff) { 186 struct ata_channel *ch = device_get_softc(device_get_parent(dev)); 187 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)); 191 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; 197 else 198 atadev->mode = ATA_SA150; 199 } 200 else { 201 mode = ata_limit_mode(dev, mode, ATA_UDMA5); 202 if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) 203 atadev->mode = mode; 204 } 205 } 206 207 int 208 ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis) 209 { 210 struct ata_device *atadev = device_get_softc(request->dev); 211 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)) 217 fis[3] = ATA_F_DMA; 218 else { 219 fis[5] = request->transfersize; 220 fis[6] = request->transfersize >> 8; 221 } 222 fis[7] = ATA_D_LBA; 223 fis[15] = ATA_A_4BIT; 224 return 20; 225 } 226 else { 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; 235 fis[7] = ATA_D_LBA; 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; 245 return 20; 246 } 247 return 0; 248 } 249