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 int contig; 88 89 #ifdef DIAGNOSTIC 90 if (chan & ~VALID_DMA_MASK) 91 panic("isa_dma_init: channel out of range"); 92 #endif 93 94 /* Try malloc() first. It works better if it works. */ 95 buf = malloc(bouncebufsize, M_DEVBUF, flag); 96 if (buf != NULL) { 97 if (isa_dmarangecheck(buf, bouncebufsize, chan) != 0) { 98 free(buf, M_DEVBUF); 99 buf = NULL; 100 } 101 contig = 0; 102 } 103 104 if (buf == NULL) { 105 buf = contigmalloc(bouncebufsize, M_DEVBUF, flag, 0ul, 0xfffffful, 106 1ul, chan & 4 ? 0x20000ul : 0x10000ul); 107 contig = 1; 108 } 109 110 if (buf == NULL) 111 return (ENOMEM); 112 113 mtx_lock(&isa_dma_lock); 114 /* 115 * If a DMA channel is shared, both drivers have to call isa_dma_init 116 * since they don't know that the other driver will do it. 117 * Just return if we're already set up good. 118 * XXX: this only works if they agree on the bouncebuf size. This 119 * XXX: is typically the case since they are multiple instances of 120 * XXX: the same driver. 121 */ 122 if (dma_bouncebuf[chan] != NULL) { 123 if (contig) 124 contigfree(buf, bouncebufsize, M_DEVBUF); 125 else 126 free(buf, M_DEVBUF); 127 mtx_unlock(&isa_dma_lock); 128 return (0); 129 } 130 131 dma_bouncebufsize[chan] = bouncebufsize; 132 dma_bouncebuf[chan] = buf; 133 134 mtx_unlock(&isa_dma_lock); 135 136 return (0); 137 } 138 139 /* 140 * Register a DMA channel's usage. Usually called from a device driver 141 * in open() or during its initialization. 142 */ 143 int 144 isa_dma_acquire(int chan) 145 { 146 #ifdef DIAGNOSTIC 147 if (chan & ~VALID_DMA_MASK) 148 panic("isa_dma_acquire: channel out of range"); 149 #endif 150 151 mtx_lock(&isa_dma_lock); 152 if (dma_inuse & (1 << chan)) { 153 printf("isa_dma_acquire: channel %d already in use\n", chan); 154 mtx_unlock(&isa_dma_lock); 155 return (EBUSY); 156 } 157 dma_inuse |= (1 << chan); 158 dma_auto_mode &= ~(1 << chan); 159 mtx_unlock(&isa_dma_lock); 160 161 return (0); 162 } 163 164 /* 165 * Unregister a DMA channel's usage. Usually called from a device driver 166 * during close() or during its shutdown. 167 */ 168 void 169 isa_dma_release(int chan) 170 { 171 #ifdef DIAGNOSTIC 172 if (chan & ~VALID_DMA_MASK) 173 panic("isa_dma_release: channel out of range"); 174 175 mtx_lock(&isa_dma_lock); 176 if ((dma_inuse & (1 << chan)) == 0) 177 printf("isa_dma_release: channel %d not in use\n", chan); 178 #else 179 mtx_lock(&isa_dma_lock); 180 #endif 181 182 if (dma_busy & (1 << chan)) { 183 dma_busy &= ~(1 << chan); 184 /* 185 * XXX We should also do "dma_bounced &= (1 << chan);" 186 * because we are acting on behalf of isa_dmadone() which 187 * was not called to end the last DMA operation. This does 188 * not matter now, but it may in the future. 189 */ 190 } 191 192 dma_inuse &= ~(1 << chan); 193 dma_auto_mode &= ~(1 << chan); 194 195 mtx_unlock(&isa_dma_lock); 196 } 197 198 /* 199 * isa_dmacascade(): program 8237 DMA controller channel to accept 200 * external dma control by a board. 201 */ 202 void 203 isa_dmacascade(int chan) 204 { 205 #ifdef DIAGNOSTIC 206 if (chan & ~VALID_DMA_MASK) 207 panic("isa_dmacascade: channel out of range"); 208 #endif 209 210 mtx_lock(&isa_dma_lock); 211 /* set dma channel mode, and set dma channel mode */ 212 if ((chan & 4) == 0) { 213 outb(DMA1_MODE, DMA37MD_CASCADE | chan); 214 outb(DMA1_SMSK, chan); 215 } else { 216 outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3)); 217 outb(DMA2_SMSK, chan & 3); 218 } 219 mtx_unlock(&isa_dma_lock); 220 } 221 222 /* 223 * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment 224 * problems by using a bounce buffer. 225 */ 226 void 227 isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) 228 { 229 vm_paddr_t phys; 230 int waport; 231 caddr_t newaddr; 232 int dma_range_checked; 233 234 dma_range_checked = isa_dmarangecheck(addr, nbytes, chan); 235 236 #ifdef DIAGNOSTIC 237 if (chan & ~VALID_DMA_MASK) 238 panic("isa_dmastart: channel out of range"); 239 240 if ((chan < 4 && nbytes > (1<<16)) 241 || (chan >= 4 && (nbytes > (1<<17) || (uintptr_t)addr & 1))) 242 panic("isa_dmastart: impossible request"); 243 244 mtx_lock(&isa_dma_lock); 245 if ((dma_inuse & (1 << chan)) == 0) 246 printf("isa_dmastart: channel %d not acquired\n", chan); 247 #else 248 mtx_lock(&isa_dma_lock); 249 #endif 250 251 #if 0 252 /* 253 * XXX This should be checked, but drivers like ad1848 only call 254 * isa_dmastart() once because they use Auto DMA mode. If we 255 * leave this in, drivers that do this will print this continuously. 256 */ 257 if (dma_busy & (1 << chan)) 258 printf("isa_dmastart: channel %d busy\n", chan); 259 #endif 260 261 dma_busy |= (1 << chan); 262 263 if (dma_range_checked) { 264 if (dma_bouncebuf[chan] == NULL 265 || dma_bouncebufsize[chan] < nbytes) 266 panic("isa_dmastart: bad bounce buffer"); 267 dma_bounced |= (1 << chan); 268 newaddr = dma_bouncebuf[chan]; 269 270 /* copy bounce buffer on write */ 271 if (!(flags & ISADMA_READ)) 272 bcopy(addr, newaddr, nbytes); 273 addr = newaddr; 274 } 275 276 /* translate to physical */ 277 phys = pmap_extract(kernel_pmap, (vm_offset_t)addr); 278 279 if (flags & ISADMA_RAW) { 280 dma_auto_mode |= (1 << chan); 281 } else { 282 dma_auto_mode &= ~(1 << chan); 283 } 284 285 if ((chan & 4) == 0) { 286 /* 287 * Program one of DMA channels 0..3. These are 288 * byte mode channels. 289 */ 290 /* set dma channel mode, and reset address ff */ 291 292 /* If ISADMA_RAW flag is set, then use autoinitialise mode */ 293 if (flags & ISADMA_RAW) { 294 if (flags & ISADMA_READ) 295 outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan); 296 else 297 outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan); 298 } 299 else 300 if (flags & ISADMA_READ) 301 outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan); 302 else 303 outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan); 304 outb(DMA1_FFC, 0); 305 306 /* send start address */ 307 waport = DMA1_CHN(chan); 308 outb(waport, phys); 309 outb(waport, phys>>8); 310 outb(dmapageport[chan], phys>>16); 311 312 /* send count */ 313 outb(waport + 1, --nbytes); 314 outb(waport + 1, nbytes>>8); 315 316 /* unmask channel */ 317 outb(DMA1_SMSK, chan); 318 } else { 319 /* 320 * Program one of DMA channels 4..7. These are 321 * word mode channels. 322 */ 323 /* set dma channel mode, and reset address ff */ 324 325 /* If ISADMA_RAW flag is set, then use autoinitialise mode */ 326 if (flags & ISADMA_RAW) { 327 if (flags & ISADMA_READ) 328 outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3)); 329 else 330 outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3)); 331 } 332 else 333 if (flags & ISADMA_READ) 334 outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3)); 335 else 336 outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3)); 337 outb(DMA2_FFC, 0); 338 339 /* send start address */ 340 waport = DMA2_CHN(chan - 4); 341 outb(waport, phys>>1); 342 outb(waport, phys>>9); 343 outb(dmapageport[chan], phys>>16); 344 345 /* send count */ 346 nbytes >>= 1; 347 outb(waport + 2, --nbytes); 348 outb(waport + 2, nbytes>>8); 349 350 /* unmask channel */ 351 outb(DMA2_SMSK, chan & 3); 352 } 353 mtx_unlock(&isa_dma_lock); 354 } 355 356 void 357 isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) 358 { 359 #ifdef DIAGNOSTIC 360 if (chan & ~VALID_DMA_MASK) 361 panic("isa_dmadone: channel out of range"); 362 363 if ((dma_inuse & (1 << chan)) == 0) 364 printf("isa_dmadone: channel %d not acquired\n", chan); 365 #endif 366 367 mtx_lock(&isa_dma_lock); 368 if (((dma_busy & (1 << chan)) == 0) && 369 (dma_auto_mode & (1 << chan)) == 0 ) 370 printf("isa_dmadone: channel %d not busy\n", chan); 371 372 if ((dma_auto_mode & (1 << chan)) == 0) 373 outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4); 374 375 if (dma_bounced & (1 << chan)) { 376 /* copy bounce buffer on read */ 377 if (flags & ISADMA_READ) 378 bcopy(dma_bouncebuf[chan], addr, nbytes); 379 380 dma_bounced &= ~(1 << chan); 381 } 382 dma_busy &= ~(1 << chan); 383 mtx_unlock(&isa_dma_lock); 384 } 385 386 /* 387 * Check for problems with the address range of a DMA transfer 388 * (non-contiguous physical pages, outside of bus address space, 389 * crossing DMA page boundaries). 390 * Return true if special handling needed. 391 */ 392 393 static int 394 isa_dmarangecheck(caddr_t va, u_int length, int chan) 395 { 396 vm_paddr_t phys, priorpage = 0; 397 vm_offset_t endva; 398 u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); 399 400 endva = (vm_offset_t)round_page((vm_offset_t)va + length); 401 for (; va < (caddr_t) endva ; va += PAGE_SIZE) { 402 phys = trunc_page(pmap_extract(kernel_pmap, (vm_offset_t)va)); 403 if (phys == 0) 404 panic("isa_dmacheck: no physical page present"); 405 if (phys >= ISARAM_END) 406 return (1); 407 if (priorpage) { 408 if (priorpage + PAGE_SIZE != phys) 409 return (1); 410 /* check if crossing a DMA page boundary */ 411 if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk) 412 return (1); 413 } 414 priorpage = phys; 415 } 416 return (0); 417 } 418 419 /* 420 * Query the progress of a transfer on a DMA channel. 421 * 422 * To avoid having to interrupt a transfer in progress, we sample 423 * each of the high and low databytes twice, and apply the following 424 * logic to determine the correct count. 425 * 426 * Reads are performed with interrupts disabled, thus it is to be 427 * expected that the time between reads is very small. At most 428 * one rollover in the low count byte can be expected within the 429 * four reads that are performed. 430 * 431 * There are three gaps in which a rollover can occur : 432 * 433 * - read low1 434 * gap1 435 * - read high1 436 * gap2 437 * - read low2 438 * gap3 439 * - read high2 440 * 441 * If a rollover occurs in gap1 or gap2, the low2 value will be 442 * greater than the low1 value. In this case, low2 and high2 are a 443 * corresponding pair. 444 * 445 * In any other case, low1 and high1 can be considered to be correct. 446 * 447 * The function returns the number of bytes remaining in the transfer, 448 * or -1 if the channel requested is not active. 449 * 450 */ 451 static int 452 isa_dmastatus_locked(int chan) 453 { 454 u_long cnt = 0; 455 int ffport, waport; 456 u_long low1, high1, low2, high2; 457 458 mtx_assert(&isa_dma_lock, MA_OWNED); 459 460 /* channel active? */ 461 if ((dma_inuse & (1 << chan)) == 0) { 462 printf("isa_dmastatus: channel %d not active\n", chan); 463 return(-1); 464 } 465 /* channel busy? */ 466 467 if (((dma_busy & (1 << chan)) == 0) && 468 (dma_auto_mode & (1 << chan)) == 0 ) { 469 printf("chan %d not busy\n", chan); 470 return -2 ; 471 } 472 if (chan < 4) { /* low DMA controller */ 473 ffport = DMA1_FFC; 474 waport = DMA1_CHN(chan) + 1; 475 } else { /* high DMA controller */ 476 ffport = DMA2_FFC; 477 waport = DMA2_CHN(chan - 4) + 2; 478 } 479 480 disable_intr(); /* no interrupts Mr Jones! */ 481 outb(ffport, 0); /* clear register LSB flipflop */ 482 low1 = inb(waport); 483 high1 = inb(waport); 484 outb(ffport, 0); /* clear again */ 485 low2 = inb(waport); 486 high2 = inb(waport); 487 enable_intr(); /* enable interrupts again */ 488 489 /* 490 * Now decide if a wrap has tried to skew our results. 491 * Note that after TC, the count will read 0xffff, while we want 492 * to return zero, so we add and then mask to compensate. 493 */ 494 if (low1 >= low2) { 495 cnt = (low1 + (high1 << 8) + 1) & 0xffff; 496 } else { 497 cnt = (low2 + (high2 << 8) + 1) & 0xffff; 498 } 499 500 if (chan >= 4) /* high channels move words */ 501 cnt *= 2; 502 return(cnt); 503 } 504 505 int 506 isa_dmastatus(int chan) 507 { 508 int status; 509 510 mtx_lock(&isa_dma_lock); 511 status = isa_dmastatus_locked(chan); 512 mtx_unlock(&isa_dma_lock); 513 514 return (status); 515 } 516 517 /* 518 * Reached terminal count yet ? 519 */ 520 int 521 isa_dmatc(int chan) 522 { 523 524 if (chan < 4) 525 return(inb(DMA1_STATUS) & (1 << chan)); 526 else 527 return(inb(DMA2_STATUS) & (1 << (chan & 3))); 528 } 529 530 /* 531 * Stop a DMA transfer currently in progress. 532 */ 533 int 534 isa_dmastop(int chan) 535 { 536 int status; 537 538 mtx_lock(&isa_dma_lock); 539 if ((dma_inuse & (1 << chan)) == 0) 540 printf("isa_dmastop: channel %d not acquired\n", chan); 541 542 if (((dma_busy & (1 << chan)) == 0) && 543 ((dma_auto_mode & (1 << chan)) == 0)) { 544 printf("chan %d not busy\n", chan); 545 mtx_unlock(&isa_dma_lock); 546 return -2 ; 547 } 548 549 if ((chan & 4) == 0) { 550 outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */); 551 } else { 552 outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */); 553 } 554 555 status = isa_dmastatus_locked(chan); 556 557 mtx_unlock(&isa_dma_lock); 558 559 return (status); 560 } 561 562 /* 563 * Attach to the ISA PnP descriptor for the AT DMA controller 564 */ 565 static struct isa_pnp_id atdma_ids[] = { 566 { 0x0002d041 /* PNP0200 */, "AT DMA controller" }, 567 { 0 } 568 }; 569 570 static int 571 atdma_probe(device_t dev) 572 { 573 int result; 574 575 if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, atdma_ids)) <= 0) 576 device_quiet(dev); 577 return(result); 578 } 579 580 static int 581 atdma_attach(device_t dev) 582 { 583 return(0); 584 } 585 586 static device_method_t atdma_methods[] = { 587 /* Device interface */ 588 DEVMETHOD(device_probe, atdma_probe), 589 DEVMETHOD(device_attach, atdma_attach), 590 DEVMETHOD(device_detach, bus_generic_detach), 591 DEVMETHOD(device_shutdown, bus_generic_shutdown), 592 DEVMETHOD(device_suspend, bus_generic_suspend), 593 DEVMETHOD(device_resume, bus_generic_resume), 594 { 0, 0 } 595 }; 596 597 static driver_t atdma_driver = { 598 "atdma", 599 atdma_methods, 600 1, /* no softc */ 601 }; 602 603 DRIVER_MODULE(atdma, isa, atdma_driver, 0, 0); 604 DRIVER_MODULE(atdma, acpi, atdma_driver, 0, 0); 605 ISA_PNP_INFO(atdma_ids); 606