ata-dma.c revision 45798
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.5 1999/04/16 21:21:53 peter 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#include <pci/pcivar.h> 43#include <pci/pcireg.h> 44#include <dev/ata/ata-all.h> 45 46#ifdef __alpha__ 47#undef vtophys 48#define vtophys(va) (pmap_kextract(((vm_offset_t) (va))) + 1*1024*1024*1024) 49#endif 50 51/* misc defines */ 52#define MIN(a,b) ((a)>(b)?(b):(a)) 53 54#if NPCI > 0 55 56int32_t 57ata_dmainit(struct ata_softc *scp, int32_t device, 58 int32_t apiomode, int32_t wdmamode, int32_t udmamode) 59{ 60 int32_t type, devno, error; 61 void *dmatab; 62 63 if (!scp->bmaddr) 64 return -1; 65#ifdef ATA_DEBUGDMA 66 printf("ata%d: dmainit: ioaddr=0x%x altioaddr=0x%x, bmaddr=0x%x\n", 67 scp->lun, scp->ioaddr, scp->altioaddr, scp->bmaddr); 68#endif 69 70 if (!(dmatab = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT))) 71 return -1; 72 73 if (((uintptr_t)dmatab >> PAGE_SHIFT) ^ 74 (((uintptr_t)dmatab + PAGE_SIZE - 1) >> PAGE_SHIFT)) { 75 printf("ata_dmainit: dmatab crosses page boundary, no DMA\n"); 76 free(dmatab, M_DEVBUF); 77 return -1; 78 } 79 scp->dmatab[device ? 1 : 0] = dmatab; 80 81 type = pci_get_devid(scp->dev); 82 83 switch(type) { 84 85 case 0x71118086: /* Intel PIIX4 */ 86 if (udmamode >= 2) { 87 int32_t mask48, new48; 88 89 printf("ata%d: %s: settting up UDMA2 mode on PIIX4 chip ", 90 scp->lun, (device) ? "slave" : "master"); 91 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 92 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 93 if (error) { 94 printf("failed\n"); 95 break; 96 } 97 printf("OK\n"); 98 devno = (scp->unit << 1) + (device ? 1 : 0); 99 mask48 = (1 << devno) + (3 << (16 + (devno << 2))); 100 new48 = (1 << devno) + (2 << (16 + (devno << 2))); 101 pci_write_config(scp->dev, 0x48, 102 (pci_read_config(scp->dev, 0x48, 4) & 103 ~mask48) | new48, 4); 104 return 0; 105 } 106 /* FALLTHROUGH */ 107 108 case 0x70108086: /* Intel PIIX3 */ 109 if (wdmamode >= 2 && apiomode >= 4) { 110 int32_t mask40, new40, mask44, new44; 111 112 /* if SITRE not set doit for both channels */ 113 if (!((pci_read_config(scp->dev, 0x40, 4)>>(scp->unit<<8))&0x4000)){ 114 new40 = pci_read_config(scp->dev, 0x40, 4); 115 new44 = pci_read_config(scp->dev, 0x44, 4); 116 if (!(new40 & 0x00004000)) { 117 new44 &= ~0x0000000f; 118 new44 |= ((new40&0x00003000)>>10)|((new40&0x00000300)>>8); 119 } 120 if (!(new40 & 0x40000000)) { 121 new44 &= ~0x000000f0; 122 new44 |= ((new40&0x30000000)>>22)|((new40&0x03000000)>>20); 123 } 124 new40 |= 0x40004000; 125 pci_write_config(scp->dev, 0x40, new40, 4); 126 pci_write_config(scp->dev, 0x44, new44, 4); 127 } 128 printf("ata%d: %s: settting up WDMA2 mode on PIIX3/4 chip ", 129 scp->lun, (device) ? "slave" : "master"); 130 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 131 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 132 if (error) { 133 printf("failed\n"); 134 break; 135 } 136 printf("OK\n"); 137 if (device == ATA_MASTER) { 138 mask40 = 0x0000330f; 139 new40 = 0x00002307; 140 mask44 = 0; 141 new44 = 0; 142 } else { 143 mask40 = 0x000000f0; 144 new40 = 0x00000070; 145 mask44 = 0x0000000f; 146 new44 = 0x0000000b; 147 } 148 if (scp->unit) { 149 mask40 <<= 16; 150 new40 <<= 16; 151 mask44 <<= 4; 152 new44 <<= 4; 153 } 154 pci_write_config(scp->dev, 0x40, 155 (pci_read_config(scp->dev, 0x40, 4) & 156 ~mask40) | new40, 4); 157 pci_write_config(scp->dev, 0x44, 158 (pci_read_config(scp->dev, 0x44, 4) & 159 ~mask44) | new44, 4); 160 return 0; 161 } 162 break; 163 164 case 0x12308086: /* Intel PIIX */ 165 /* probably not worth the trouble */ 166 break; 167 168 case 0x4d33105a: /* Promise Ultra/33 / FastTrack controllers */ 169 devno = (scp->unit << 1) + (device ? 1 : 0); 170 if (udmamode >=2) { 171 printf("ata%d: %s: settting up UDMA2 mode on Promise chip ", 172 scp->lun, (device) ? "slave" : "master"); 173 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 174 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 175 if (error) { 176 printf("failed\n"); 177 break; 178 } 179 printf("OK\n"); 180 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004127f3, 4); 181 return 0; 182 } 183 else if (wdmamode >= 2 && apiomode >= 4) { 184 printf("ata%d: %s: settting up WDMA2 mode on Promise chip ", 185 scp->lun, (device) ? "slave" : "master"); 186 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 187 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 188 if (error) { 189 printf("failed\n"); 190 break; 191 } 192 printf("OK\n"); 193 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004367f3, 4); 194 return 0; 195 } 196 else { 197 printf("ata%d: %s: settting up PIO mode on Promise chip OK\n", 198 scp->lun, (device) ? "slave" : "master"); 199 pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004fe924, 4); 200 } 201 break; 202 203 case 0x522910b9: /* AcerLabs Aladdin IV/V */ 204 if (udmamode >=2) { 205 int32_t word54 = pci_read_config(scp->dev, 0x54, 4); 206 207 printf("ata%d: %s: settting up UDMA2 mode on Aladdin chip ", 208 scp->lun, (device) ? "slave" : "master"); 209 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 210 ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 211 if (error) { 212 printf("failed\n"); 213 break; 214 } 215 printf("OK\n"); 216 word54 |= 0x5555; 217 word54 |= (0x0000000A << (16 + (scp->unit << 3) + (device << 2))); 218 pci_write_config(scp->dev, 0x54, word54, 4); 219 return 0; 220 221 } 222 else if (wdmamode >= 2 && apiomode >= 4) { 223 printf("ata%d: %s: settting up WDMA2 mode on Aladdin chip ", 224 scp->lun, (device) ? "slave" : "master"); 225 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 226 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 227 if (error) { 228 printf("failed\n"); 229 break; 230 } 231 printf("OK\n"); 232 return 0; 233 } 234 break; 235 236 default: /* well, we have no support for this, but try anyways */ 237 if ((wdmamode >= 2 && apiomode >= 4) || udmamode >= 2) { 238 printf("ata%d: %s: settting up generic WDMA2 mode ", 239 scp->lun, (device) ? "slave" : "master"); 240 error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, 241 ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); 242 if (error) { 243 printf("failed\n"); 244 break; 245 } 246 printf("OK\n"); 247 return 0; 248 } 249 } 250 free(dmatab, M_DEVBUF); 251 return -1; 252} 253 254int32_t 255ata_dmasetup(struct ata_softc *scp, int32_t device, 256 int8_t *data, int32_t count, int32_t flags) 257{ 258 struct ata_dmaentry *dmatab; 259 u_int32_t dma_count, dma_base; 260 int32_t i = 0; 261 262#ifdef ATA_DEBUGDMA 263 printf("ata%d: dmasetup\n", scp->lun); 264#endif 265 if (((uintptr_t)data & 1) || (count & 1)) 266 return -1; 267 268 if (!count) { 269 printf("ata%d: zero length DMA transfer attempt on %s\n", 270 scp->lun, (device ? "slave" : "master")); 271 return -1; 272 } 273 274 dmatab = scp->dmatab[device ? 1 : 0]; 275 dma_base = vtophys(data); 276 dma_count = MIN(count, (PAGE_SIZE - ((uintptr_t)data & PAGE_MASK))); 277 data += dma_count; 278 count -= dma_count; 279 280 while (count) { 281 dmatab[i].base = dma_base; 282 dmatab[i].count = (dma_count & 0xffff); 283 i++; 284 if (i >= ATA_DMA_ENTRIES) { 285 printf("ata%d: too many segments in DMA table for %s\n", 286 scp->lun, (device ? "slave" : "master")); 287 return -1; 288 } 289 dma_base = vtophys(data); 290 dma_count = MIN(count, PAGE_SIZE); 291 data += MIN(count, PAGE_SIZE); 292 count -= MIN(count, PAGE_SIZE); 293 } 294#ifdef ATA_DEBUGDMA 295printf("ata_dmasetup: base=%08x count%08x\n", 296 dma_base, dma_count); 297#endif 298 dmatab[i].base = dma_base; 299 dmatab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT; 300 301 outl(scp->bmaddr + ATA_BMDTP_PORT, vtophys(dmatab)); 302#ifdef ATA_DEBUGDMA 303printf("dmatab=%08x %08x\n", vtophys(dmatab), inl(scp->bmaddr+ATA_BMDTP_PORT)); 304#endif 305 outb(scp->bmaddr + ATA_BMCMD_PORT, flags ? ATA_BMCMD_WRITE_READ:0); 306 outb(scp->bmaddr + ATA_BMSTAT_PORT, (inb(scp->bmaddr + ATA_BMSTAT_PORT) | 307 (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); 308 return 0; 309} 310 311void 312ata_dmastart(struct ata_softc *scp, int32_t device) 313{ 314#ifdef ATA_DEBUGDMA 315 printf("ata%d: dmastart\n", scp->lun); 316#endif 317 outb(scp->bmaddr + ATA_BMCMD_PORT, 318 inb(scp->bmaddr + ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP); 319} 320 321int32_t 322ata_dmadone(struct ata_softc *scp, int32_t device) 323{ 324#ifdef ATA_DEBUGDMA 325 printf("ata%d: dmadone\n", scp->lun); 326#endif 327 outb(scp->bmaddr + ATA_BMCMD_PORT, 328 inb(scp->bmaddr + ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); 329 return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 330} 331 332int32_t 333ata_dmastatus(struct ata_softc *scp, int32_t device) 334{ 335#ifdef ATA_DEBUGDMA 336 printf("ata%d: dmastatus\n", scp->lun); 337#endif 338 return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 339} 340 341#else /* NPCI > 0 */ 342 343int32_t 344ata_dmainit(struct ata_softc *scp, int32_t device, 345 int32_t piomode, int32_t wdmamode, int32_t udmamode) 346{ 347 return -1; 348} 349 350int32_t 351ata_dmasetup(struct ata_softc *scp, int32_t device, 352 int8_t *data, int32_t count, int32_t flags) 353{ 354 return -1; 355} 356 357void 358ata_dmastart(struct ata_softc *scp, int32_t device) 359{ 360} 361 362int32_t 363ata_dmadone(struct ata_softc *scp, int32_t device) 364{ 365 return -1; 366} 367 368int32_t 369ata_dmastatus(struct ata_softc *scp, int32_t device) 370{ 371 return -1; 372} 373 374#endif /* NPCI > 0 */ 375#endif /* NATA > 0 */ 376