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