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