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