1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1991 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * William Jolitz. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 /* 37 * code to manage AT bus 38 * 39 * 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com): 40 * Fixed uninitialized variable problem and added code to deal 41 * with DMA page boundaries in isa_dmarangecheck(). Fixed word 42 * mode DMA count compution and reorganized DMA setup code in 43 * isa_dmastart() 44 */ 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/bus.h> 49 #include <sys/kernel.h> 50 #include <sys/malloc.h> 51 #include <sys/lock.h> 52 #include <sys/proc.h> 53 #include <sys/mutex.h> 54 #include <sys/module.h> 55 #include <vm/vm.h> 56 #include <vm/vm_param.h> 57 #include <vm/pmap.h> 58 #include <isa/isareg.h> 59 #include <isa/isavar.h> 60 #include <isa/isa_dmareg.h> 61 62 #define ISARAM_END 0x1000000 63 64 static int isa_dmarangecheck(caddr_t va, u_int length, int chan); 65 66 static caddr_t dma_bouncebuf[8]; 67 static u_int dma_bouncebufsize[8]; 68 static u_int8_t dma_bounced = 0; 69 static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */ 70 static u_int8_t dma_inuse = 0; /* User for acquire/release */ 71 static u_int8_t dma_auto_mode = 0; 72 static struct mtx isa_dma_lock; 73 MTX_SYSINIT(isa_dma_lock, &isa_dma_lock, "isa DMA lock", MTX_DEF); 74 75 #define VALID_DMA_MASK (7) 76 77 /* high byte of address is stored in this port for i-th dma channel */ 78 static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; 79 80 /* 81 * Setup a DMA channel's bounce buffer. 82 */ 83 int 84 isa_dma_init(int chan, u_int bouncebufsize, int flag) 85 { 86 void *buf; 87 88 #ifdef DIAGNOSTIC 89 if (chan & ~VALID_DMA_MASK) 90 panic("isa_dma_init: channel out of range"); 91 #endif 92 93 /* Try malloc() first. It works better if it works. */ 94 buf = malloc(bouncebufsize, M_DEVBUF, flag); 95 if (buf != NULL) { 96 if (isa_dmarangecheck(buf, bouncebufsize, chan) != 0) { 97 free(buf, M_DEVBUF); 98 buf = NULL; 99 } 100 } 101 102 if (buf == NULL) { 103 buf = contigmalloc(bouncebufsize, M_DEVBUF, flag, 0ul, 0xfffffful, 104 1ul, chan & 4 ? 0x20000ul : 0x10000ul); 105 } 106 107 if (buf == NULL) 108 return (ENOMEM); 109 110 mtx_lock(&isa_dma_lock); 111 /* 112 * If a DMA channel is shared, both drivers have to call isa_dma_init 113 * since they don't know that the other driver will do it. 114 * Just return if we're already set up good. 115 * XXX: this only works if they agree on the bouncebuf size. This 116 * XXX: is typically the case since they are multiple instances of 117 * XXX: the same driver. 118 */ 119 if (dma_bouncebuf[chan] != NULL) { 120 free(buf, M_DEVBUF); 121 mtx_unlock(&isa_dma_lock); 122 return (0); 123 } 124 125 dma_bouncebufsize[chan] = bouncebufsize; 126 dma_bouncebuf[chan] = buf; 127 128 mtx_unlock(&isa_dma_lock); 129 130 return (0); 131 } 132 133 /* 134 * Register a DMA channel's usage. Usually called from a device driver 135 * in open() or during its initialization. 136 */ 137 int 138 isa_dma_acquire(int chan) 139 { 140 #ifdef DIAGNOSTIC 141 if (chan & ~VALID_DMA_MASK) 142 panic("isa_dma_acquire: channel out of range"); 143 #endif 144 145 mtx_lock(&isa_dma_lock); 146 if (dma_inuse & (1 << chan)) { 147 printf("isa_dma_acquire: channel %d already in use\n", chan); 148 mtx_unlock(&isa_dma_lock); 149 return (EBUSY); 150 } 151 dma_inuse |= (1 << chan); 152 dma_auto_mode &= ~(1 << chan); 153 mtx_unlock(&isa_dma_lock); 154 155 return (0); 156 } 157 158 /* 159 * Unregister a DMA channel's usage. Usually called from a device driver 160 * during close() or during its shutdown. 161 */ 162 void 163 isa_dma_release(int chan) 164 { 165 #ifdef DIAGNOSTIC 166 if (chan & ~VALID_DMA_MASK) 167 panic("isa_dma_release: channel out of range"); 168 169 mtx_lock(&isa_dma_lock); 170 if ((dma_inuse & (1 << chan)) == 0) 171 printf("isa_dma_release: channel %d not in use\n", chan); 172 #else 173 mtx_lock(&isa_dma_lock); 174 #endif 175 176 if (dma_busy & (1 << chan)) { 177 dma_busy &= ~(1 << chan); 178 /* 179 * XXX We should also do "dma_bounced &= (1 << chan);" 180 * because we are acting on behalf of isa_dmadone() which 181 * was not called to end the last DMA operation. This does 182 * not matter now, but it may in the future. 183 */ 184 } 185 186 dma_inuse &= ~(1 << chan); 187 dma_auto_mode &= ~(1 << chan); 188 189 mtx_unlock(&isa_dma_lock); 190 } 191 192 /* 193 * isa_dmacascade(): program 8237 DMA controller channel to accept 194 * external dma control by a board. 195 */ 196 void 197 isa_dmacascade(int chan) 198 { 199 #ifdef DIAGNOSTIC 200 if (chan & ~VALID_DMA_MASK) 201 panic("isa_dmacascade: channel out of range"); 202 #endif 203 204 mtx_lock(&isa_dma_lock); 205 /* set dma channel mode, and set dma channel mode */ 206 if ((chan & 4) == 0) { 207 outb(DMA1_MODE, DMA37MD_CASCADE | chan); 208 outb(DMA1_SMSK, chan); 209 } else { 210 outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3)); 211 outb(DMA2_SMSK, chan & 3); 212 } 213 mtx_unlock(&isa_dma_lock); 214 } 215 216 /* 217 * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment 218 * problems by using a bounce buffer. 219 */ 220 void 221 isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) 222 { 223 vm_paddr_t phys; 224 int waport; 225 caddr_t newaddr; 226 int dma_range_checked; 227 228 dma_range_checked = isa_dmarangecheck(addr, nbytes, chan); 229 230 #ifdef DIAGNOSTIC 231 if (chan & ~VALID_DMA_MASK) 232 panic("isa_dmastart: channel out of range"); 233 234 if ((chan < 4 && nbytes > (1<<16)) 235 || (chan >= 4 && (nbytes > (1<<17) || (uintptr_t)addr & 1))) 236 panic("isa_dmastart: impossible request"); 237 238 mtx_lock(&isa_dma_lock); 239 if ((dma_inuse & (1 << chan)) == 0) 240 printf("isa_dmastart: channel %d not acquired\n", chan); 241 #else 242 mtx_lock(&isa_dma_lock); 243 #endif 244 245 #if 0 246 /* 247 * XXX This should be checked, but drivers like ad1848 only call 248 * isa_dmastart() once because they use Auto DMA mode. If we 249 * leave this in, drivers that do this will print this continuously. 250 */ 251 if (dma_busy & (1 << chan)) 252 printf("isa_dmastart: channel %d busy\n", chan); 253 #endif 254 255 dma_busy |= (1 << chan); 256 257 if (dma_range_checked) { 258 if (dma_bouncebuf[chan] == NULL 259 || dma_bouncebufsize[chan] < nbytes) 260 panic("isa_dmastart: bad bounce buffer"); 261 dma_bounced |= (1 << chan); 262 newaddr = dma_bouncebuf[chan]; 263 264 /* copy bounce buffer on write */ 265 if (!(flags & ISADMA_READ)) 266 bcopy(addr, newaddr, nbytes); 267 addr = newaddr; 268 } 269 270 /* translate to physical */ 271 phys = pmap_extract(kernel_pmap, (vm_offset_t)addr); 272 273 if (flags & ISADMA_RAW) { 274 dma_auto_mode |= (1 << chan); 275 } else { 276 dma_auto_mode &= ~(1 << chan); 277 } 278 279 if ((chan & 4) == 0) { 280 /* 281 * Program one of DMA channels 0..3. These are 282 * byte mode channels. 283 */ 284 /* set dma channel mode, and reset address ff */ 285 286 /* If ISADMA_RAW flag is set, then use autoinitialise mode */ 287 if (flags & ISADMA_RAW) { 288 if (flags & ISADMA_READ) 289 outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan); 290 else 291 outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan); 292 } 293 else 294 if (flags & ISADMA_READ) 295 outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan); 296 else 297 outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan); 298 outb(DMA1_FFC, 0); 299 300 /* send start address */ 301 waport = DMA1_CHN(chan); 302 outb(waport, phys); 303 outb(waport, phys>>8); 304 outb(dmapageport[chan], phys>>16); 305 306 /* send count */ 307 outb(waport + 1, --nbytes); 308 outb(waport + 1, nbytes>>8); 309 310 /* unmask channel */ 311 outb(DMA1_SMSK, chan); 312 } else { 313 /* 314 * Program one of DMA channels 4..7. These are 315 * word mode channels. 316 */ 317 /* set dma channel mode, and reset address ff */ 318 319 /* If ISADMA_RAW flag is set, then use autoinitialise mode */ 320 if (flags & ISADMA_RAW) { 321 if (flags & ISADMA_READ) 322 outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3)); 323 else 324 outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3)); 325 } 326 else 327 if (flags & ISADMA_READ) 328 outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3)); 329 else 330 outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3)); 331 outb(DMA2_FFC, 0); 332 333 /* send start address */ 334 waport = DMA2_CHN(chan - 4); 335 outb(waport, phys>>1); 336 outb(waport, phys>>9); 337 outb(dmapageport[chan], phys>>16); 338 339 /* send count */ 340 nbytes >>= 1; 341 outb(waport + 2, --nbytes); 342 outb(waport + 2, nbytes>>8); 343 344 /* unmask channel */ 345 outb(DMA2_SMSK, chan & 3); 346 } 347 mtx_unlock(&isa_dma_lock); 348 } 349 350 void 351 isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) 352 { 353 #ifdef DIAGNOSTIC 354 if (chan & ~VALID_DMA_MASK) 355 panic("isa_dmadone: channel out of range"); 356 357 if ((dma_inuse & (1 << chan)) == 0) 358 printf("isa_dmadone: channel %d not acquired\n", chan); 359 #endif 360 361 mtx_lock(&isa_dma_lock); 362 if (((dma_busy & (1 << chan)) == 0) && 363 (dma_auto_mode & (1 << chan)) == 0 ) 364 printf("isa_dmadone: channel %d not busy\n", chan); 365 366 if ((dma_auto_mode & (1 << chan)) == 0) 367 outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4); 368 369 if (dma_bounced & (1 << chan)) { 370 /* copy bounce buffer on read */ 371 if (flags & ISADMA_READ) 372 bcopy(dma_bouncebuf[chan], addr, nbytes); 373 374 dma_bounced &= ~(1 << chan); 375 } 376 dma_busy &= ~(1 << chan); 377 mtx_unlock(&isa_dma_lock); 378 } 379 380 /* 381 * Check for problems with the address range of a DMA transfer 382 * (non-contiguous physical pages, outside of bus address space, 383 * crossing DMA page boundaries). 384 * Return true if special handling needed. 385 */ 386 387 static int 388 isa_dmarangecheck(caddr_t va, u_int length, int chan) 389 { 390 vm_paddr_t phys, priorpage = 0; 391 vm_offset_t endva; 392 u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); 393 394 endva = (vm_offset_t)round_page((vm_offset_t)va + length); 395 for (; va < (caddr_t) endva ; va += PAGE_SIZE) { 396 phys = trunc_page(pmap_extract(kernel_pmap, (vm_offset_t)va)); 397 if (phys == 0) 398 panic("isa_dmacheck: no physical page present"); 399 if (phys >= ISARAM_END) 400 return (1); 401 if (priorpage) { 402 if (priorpage + PAGE_SIZE != phys) 403 return (1); 404 /* check if crossing a DMA page boundary */ 405 if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk) 406 return (1); 407 } 408 priorpage = phys; 409 } 410 return (0); 411 } 412 413 /* 414 * Query the progress of a transfer on a DMA channel. 415 * 416 * To avoid having to interrupt a transfer in progress, we sample 417 * each of the high and low databytes twice, and apply the following 418 * logic to determine the correct count. 419 * 420 * Reads are performed with interrupts disabled, thus it is to be 421 * expected that the time between reads is very small. At most 422 * one rollover in the low count byte can be expected within the 423 * four reads that are performed. 424 * 425 * There are three gaps in which a rollover can occur : 426 * 427 * - read low1 428 * gap1 429 * - read high1 430 * gap2 431 * - read low2 432 * gap3 433 * - read high2 434 * 435 * If a rollover occurs in gap1 or gap2, the low2 value will be 436 * greater than the low1 value. In this case, low2 and high2 are a 437 * corresponding pair. 438 * 439 * In any other case, low1 and high1 can be considered to be correct. 440 * 441 * The function returns the number of bytes remaining in the transfer, 442 * or -1 if the channel requested is not active. 443 * 444 */ 445 static int 446 isa_dmastatus_locked(int chan) 447 { 448 u_long cnt = 0; 449 int ffport, waport; 450 u_long low1, high1, low2, high2; 451 452 mtx_assert(&isa_dma_lock, MA_OWNED); 453 454 /* channel active? */ 455 if ((dma_inuse & (1 << chan)) == 0) { 456 printf("isa_dmastatus: channel %d not active\n", chan); 457 return(-1); 458 } 459 /* channel busy? */ 460 461 if (((dma_busy & (1 << chan)) == 0) && 462 (dma_auto_mode & (1 << chan)) == 0 ) { 463 printf("chan %d not busy\n", chan); 464 return -2 ; 465 } 466 if (chan < 4) { /* low DMA controller */ 467 ffport = DMA1_FFC; 468 waport = DMA1_CHN(chan) + 1; 469 } else { /* high DMA controller */ 470 ffport = DMA2_FFC; 471 waport = DMA2_CHN(chan - 4) + 2; 472 } 473 474 disable_intr(); /* no interrupts Mr Jones! */ 475 outb(ffport, 0); /* clear register LSB flipflop */ 476 low1 = inb(waport); 477 high1 = inb(waport); 478 outb(ffport, 0); /* clear again */ 479 low2 = inb(waport); 480 high2 = inb(waport); 481 enable_intr(); /* enable interrupts again */ 482 483 /* 484 * Now decide if a wrap has tried to skew our results. 485 * Note that after TC, the count will read 0xffff, while we want 486 * to return zero, so we add and then mask to compensate. 487 */ 488 if (low1 >= low2) { 489 cnt = (low1 + (high1 << 8) + 1) & 0xffff; 490 } else { 491 cnt = (low2 + (high2 << 8) + 1) & 0xffff; 492 } 493 494 if (chan >= 4) /* high channels move words */ 495 cnt *= 2; 496 return(cnt); 497 } 498 499 int 500 isa_dmastatus(int chan) 501 { 502 int status; 503 504 mtx_lock(&isa_dma_lock); 505 status = isa_dmastatus_locked(chan); 506 mtx_unlock(&isa_dma_lock); 507 508 return (status); 509 } 510 511 /* 512 * Reached terminal count yet ? 513 */ 514 int 515 isa_dmatc(int chan) 516 { 517 518 if (chan < 4) 519 return(inb(DMA1_STATUS) & (1 << chan)); 520 else 521 return(inb(DMA2_STATUS) & (1 << (chan & 3))); 522 } 523 524 /* 525 * Stop a DMA transfer currently in progress. 526 */ 527 int 528 isa_dmastop(int chan) 529 { 530 int status; 531 532 mtx_lock(&isa_dma_lock); 533 if ((dma_inuse & (1 << chan)) == 0) 534 printf("isa_dmastop: channel %d not acquired\n", chan); 535 536 if (((dma_busy & (1 << chan)) == 0) && 537 ((dma_auto_mode & (1 << chan)) == 0)) { 538 printf("chan %d not busy\n", chan); 539 mtx_unlock(&isa_dma_lock); 540 return -2 ; 541 } 542 543 if ((chan & 4) == 0) { 544 outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */); 545 } else { 546 outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */); 547 } 548 549 status = isa_dmastatus_locked(chan); 550 551 mtx_unlock(&isa_dma_lock); 552 553 return (status); 554 } 555 556 /* 557 * Attach to the ISA PnP descriptor for the AT DMA controller 558 */ 559 static struct isa_pnp_id atdma_ids[] = { 560 { 0x0002d041 /* PNP0200 */, "AT DMA controller" }, 561 { 0 } 562 }; 563 564 static int 565 atdma_probe(device_t dev) 566 { 567 int result; 568 569 if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, atdma_ids)) <= 0) 570 device_quiet(dev); 571 return(result); 572 } 573 574 static int 575 atdma_attach(device_t dev) 576 { 577 return(0); 578 } 579 580 static device_method_t atdma_methods[] = { 581 /* Device interface */ 582 DEVMETHOD(device_probe, atdma_probe), 583 DEVMETHOD(device_attach, atdma_attach), 584 { 0, 0 } 585 }; 586 587 static driver_t atdma_driver = { 588 "atdma", 589 atdma_methods, 590 1, /* no softc */ 591 }; 592 593 DRIVER_MODULE(atdma, isa, atdma_driver, 0, 0); 594 DRIVER_MODULE(atdma, acpi, atdma_driver, 0, 0); 595 ISA_PNP_INFO(atdma_ids); 596