ata-dma.c revision 47529
1/*- 2 * Copyright (c) 1998,1999 S�ren Schmidt 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 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: ata-dma.c,v 1.7 1999/05/17 15:58:45 sos Exp $ 29 */ 30 31#include "ata.h" 32#include "pci.h" 33#if NATA > 0 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> 37#include <sys/buf.h> 38#include <sys/malloc.h> 39#include <sys/bus.h> 40#include <vm/vm.h> 41#include <vm/pmap.h> 42#if NPCI > 0 43#include <pci/pcivar.h> 44#include <pci/pcireg.h> 45#endif 46#include <dev/ata/ata-all.h> 47 48#ifdef __alpha__ 49#undef vtophys 50#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va) 51#endif 52 53/* misc defines */ 54#define MIN(a,b) ((a)>(b)?(b):(a)) 55 56#if NPCI > 0 57 58int32_t 59ata_dmainit(struct ata_softc *scp, int32_t device, 60 int32_t apiomode, int32_t wdmamode, int32_t udmamode) 61{ 62 int32_t type, devno, error; 63 void *dmatab; 64 65 if (!scp->bmaddr) 66 return -1; 67#ifdef ATA_DEBUGDMA 68 printf("ata%d: dmainit: ioaddr=0x%x altioaddr=0x%x, bmaddr=0x%x\n", 69 scp->lun, scp->ioaddr, scp->altioaddr, scp->bmaddr); 70#endif 71 72 if (!(dmatab = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT))) 73 return -1; 74 75 if (((uintptr_t)dmatab >> PAGE_SHIFT) ^ 76 (((uintptr_t)dmatab + PAGE_SIZE - 1) >> PAGE_SHIFT)) { 77 printf("ata_dmainit: dmatab crosses page boundary, no DMA\n"); 78 free(dmatab, M_DEVBUF); 79 return -1; 80 } 81 scp->dmatab[device ? 1 : 0] = dmatab; 82 83 type = pci_get_devid(scp->dev); 84 85 switch(type) { 86 87 case 0x71118086: /* Intel PIIX4 */ 88 if (udmamode >= 2) { 89 int32_t mask48, new48; 90 91 printf("ata%d: %s: setting up UDMA2 mode on PIIX4 chip ", 92 scp->lun, (device) ? "slave" : "master"); 93 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 94 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 95 if (error) { 96 printf("failed\n"); 97 break; 98 } 99 printf("OK\n"); 100 devno = (scp->unit << 1) + (device ? 1 : 0); 101 mask48 = (1 << devno) + (3 << (16 + (devno << 2))); 102 new48 = (1 << devno) + (2 << (16 + (devno << 2))); 103 pci_write_config(scp->dev, 0x48, 104 (pci_read_config(scp->dev, 0x48, 4) & 105 ~mask48) | new48, 4); 106 return 0; 107 } 108 /* FALLTHROUGH */ 109 110 case 0x70108086: /* Intel PIIX3 */ 111 if (wdmamode >= 2 && apiomode >= 4) { 112 int32_t mask40, new40, mask44, new44; 113 114 /* if SITRE not set doit for both channels */ 115 if (!((pci_read_config(scp->dev, 0x40, 4)>>(scp->unit<<8))&0x4000)){ 116 new40 = pci_read_config(scp->dev, 0x40, 4); 117 new44 = pci_read_config(scp->dev, 0x44, 4); 118 if (!(new40 & 0x00004000)) { 119 new44 &= ~0x0000000f; 120 new44 |= ((new40&0x00003000)>>10)|((new40&0x00000300)>>8); 121 } 122 if (!(new40 & 0x40000000)) { 123 new44 &= ~0x000000f0; 124 new44 |= ((new40&0x30000000)>>22)|((new40&0x03000000)>>20); 125 } 126 new40 |= 0x40004000; 127 pci_write_config(scp->dev, 0x40, new40, 4); 128 pci_write_config(scp->dev, 0x44, new44, 4); 129 } 130 printf("ata%d: %s: setting up WDMA2 mode on PIIX3/4 chip ", 131 scp->lun, (device) ? "slave" : "master"); 132 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 133 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 134 if (error) { 135 printf("failed\n"); 136 break; 137 } 138 printf("OK\n"); 139 if (device == ATA_MASTER) { 140 mask40 = 0x0000330f; 141 new40 = 0x00002307; 142 mask44 = 0; 143 new44 = 0; 144 } else { 145 mask40 = 0x000000f0; 146 new40 = 0x00000070; 147 mask44 = 0x0000000f; 148 new44 = 0x0000000b; 149 } 150 if (scp->unit) { 151 mask40 <<= 16; 152 new40 <<= 16; 153 mask44 <<= 4; 154 new44 <<= 4; 155 } 156 pci_write_config(scp->dev, 0x40, 157 (pci_read_config(scp->dev, 0x40, 4) & 158 ~mask40) | new40, 4); 159 pci_write_config(scp->dev, 0x44, 160 (pci_read_config(scp->dev, 0x44, 4) & 161 ~mask44) | new44, 4); 162 return 0; 163 } 164 break; 165 166 case 0x12308086: /* Intel PIIX */ 167 /* probably not worth the trouble */ 168 break; 169 170 case 0x4d33105a: /* Promise Ultra/33 / FastTrack controllers */ 171 devno = (scp->unit << 1) + (device ? 1 : 0); 172 if (udmamode >=2) { 173 printf("ata%d: %s: setting up UDMA2 mode on Promise chip ", 174 scp->lun, (device) ? "slave" : "master"); 175 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 176 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 177 if (error) { 178 printf("failed\n"); 179 break; 180 } 181 printf("OK\n"); 182 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004127f3, 4); 183 return 0; 184 } 185 else if (wdmamode >= 2 && apiomode >= 4) { 186 printf("ata%d: %s: setting up WDMA2 mode on Promise chip ", 187 scp->lun, (device) ? "slave" : "master"); 188 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 189 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 190 if (error) { 191 printf("failed\n"); 192 break; 193 } 194 printf("OK\n"); 195 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004367f3, 4); 196 return 0; 197 } 198 else { 199 printf("ata%d: %s: setting up PIO mode on Promise chip OK\n", 200 scp->lun, (device) ? "slave" : "master"); 201 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004fe924, 4); 202 } 203 break; 204 205 case 0x522910b9: /* AcerLabs Aladdin IV/V */ 206 if (udmamode >=2) { 207 int32_t word54 = pci_read_config(scp->dev, 0x54, 4); 208 209 printf("ata%d: %s: setting up UDMA2 mode on Aladdin chip ", 210 scp->lun, (device) ? "slave" : "master"); 211 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 212 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 213 if (error) { 214 printf("failed\n"); 215 break; 216 } 217 printf("OK\n"); 218 word54 |= 0x5555; 219 word54 |= (0x0000000A << (16 + (scp->unit << 3) + (device << 2))); 220 pci_write_config(scp->dev, 0x54, word54, 4); 221 return 0; 222 223 } 224 else if (wdmamode >= 2 && apiomode >= 4) { 225 printf("ata%d: %s: setting up WDMA2 mode on Aladdin chip ", 226 scp->lun, (device) ? "slave" : "master"); 227 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 228 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 229 if (error) { 230 printf("failed\n"); 231 break; 232 } 233 printf("OK\n"); 234 return 0; 235 } 236 break; 237 238 default: /* well, we have no support for this, but try anyways */ 239 if ((wdmamode >= 2 && apiomode >= 4) || udmamode >= 2) { 240 printf("ata%d: %s: setting up generic WDMA2 mode ", 241 scp->lun, (device) ? "slave" : "master"); 242 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 243 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 244 if (error) { 245 printf("failed\n"); 246 break; 247 } 248 printf("OK\n"); 249 return 0; 250 } 251 } 252 free(dmatab, M_DEVBUF); 253 return -1; 254} 255 256int32_t 257ata_dmasetup(struct ata_softc *scp, int32_t device, 258 int8_t *data, int32_t count, int32_t flags) 259{ 260 struct ata_dmaentry *dmatab; 261 u_int32_t dma_count, dma_base; 262 int32_t i = 0; 263 264#ifdef ATA_DEBUGDMA 265 printf("ata%d: dmasetup\n", scp->lun); 266#endif 267 if (((uintptr_t)data & 1) || (count & 1)) 268 return -1; 269 270 if (!count) { 271 printf("ata%d: zero length DMA transfer attempt on %s\n", 272 scp->lun, (device ? "slave" : "master")); 273 return -1; 274 } 275 276 dmatab = scp->dmatab[device ? 1 : 0]; 277 dma_base = vtophys(data); 278 dma_count = MIN(count, (PAGE_SIZE - ((uintptr_t)data & PAGE_MASK))); 279 data += dma_count; 280 count -= dma_count; 281 282 while (count) { 283 dmatab[i].base = dma_base; 284 dmatab[i].count = (dma_count & 0xffff); 285 i++; 286 if (i >= ATA_DMA_ENTRIES) { 287 printf("ata%d: too many segments in DMA table for %s\n", 288 scp->lun, (device ? "slave" : "master")); 289 return -1; 290 } 291 dma_base = vtophys(data); 292 dma_count = MIN(count, PAGE_SIZE); 293 data += MIN(count, PAGE_SIZE); 294 count -= MIN(count, PAGE_SIZE); 295 } 296#ifdef ATA_DEBUGDMA 297printf("ata_dmasetup: base=%08x count%08x\n", 298 dma_base, dma_count); 299#endif 300 dmatab[i].base = dma_base; 301 dmatab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT; 302 303 outl(scp->bmaddr + ATA_BMDTP_PORT, vtophys(dmatab)); 304#ifdef ATA_DEBUGDMA 305printf("dmatab=%08x %08x\n", vtophys(dmatab), inl(scp->bmaddr+ATA_BMDTP_PORT)); 306#endif 307 outb(scp->bmaddr + ATA_BMCMD_PORT, flags ? ATA_BMCMD_WRITE_READ:0); 308 outb(scp->bmaddr + ATA_BMSTAT_PORT, (inb(scp->bmaddr + ATA_BMSTAT_PORT) | 309 (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); 310 return 0; 311} 312 313void 314ata_dmastart(struct ata_softc *scp, int32_t device) 315{ 316#ifdef ATA_DEBUGDMA 317 printf("ata%d: dmastart\n", scp->lun); 318#endif 319 outb(scp->bmaddr + ATA_BMCMD_PORT, 320 inb(scp->bmaddr + ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP); 321} 322 323int32_t 324ata_dmadone(struct ata_softc *scp, int32_t device) 325{ 326#ifdef ATA_DEBUGDMA 327 printf("ata%d: dmadone\n", scp->lun); 328#endif 329 outb(scp->bmaddr + ATA_BMCMD_PORT, 330 inb(scp->bmaddr + ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); 331 return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 332} 333 334int32_t 335ata_dmastatus(struct ata_softc *scp, int32_t device) 336{ 337#ifdef ATA_DEBUGDMA 338 printf("ata%d: dmastatus\n", scp->lun); 339#endif 340 return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 341} 342 343#else /* NPCI > 0 */ 344 345int32_t 346ata_dmainit(struct ata_softc *scp, int32_t device, 347 int32_t piomode, int32_t wdmamode, int32_t udmamode) 348{ 349 return -1; 350} 351 352int32_t 353ata_dmasetup(struct ata_softc *scp, int32_t device, 354 int8_t *data, int32_t count, int32_t flags) 355{ 356 return -1; 357} 358 359void 360ata_dmastart(struct ata_softc *scp, int32_t device) 361{ 362} 363 364int32_t 365ata_dmadone(struct ata_softc *scp, int32_t device) 366{ 367 return -1; 368} 369 370int32_t 371ata_dmastatus(struct ata_softc *scp, int32_t device) 372{ 373 return -1; 374} 375 376#endif /* NPCI > 0 */ 377#endif /* NATA > 0 */ 378