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