isa.c revision 28755
1/*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 37 * $Id: isa.c,v 1.101 1997/08/21 05:08:07 fsmp Exp $ 38 */ 39 40/* 41 * code to manage AT bus 42 * 43 * 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com): 44 * Fixed uninitialized variable problem and added code to deal 45 * with DMA page boundaries in isa_dmarangecheck(). Fixed word 46 * mode DMA count compution and reorganized DMA setup code in 47 * isa_dmastart() 48 */ 49 50#include <sys/param.h> 51#include <sys/systm.h> 52#include <sys/buf.h> 53#include <sys/malloc.h> 54#include <machine/ipl.h> 55#include <machine/md_var.h> 56#ifdef APIC_IO 57#include <machine/smp.h> 58#endif /* APIC_IO */ 59#include <vm/vm.h> 60#include <vm/vm_param.h> 61#include <vm/pmap.h> 62#include <i386/isa/isa_device.h> 63#include <i386/isa/intr_machdep.h> 64#include <i386/isa/isa.h> 65#include <i386/isa/ic/i8237.h> 66 67#include <sys/interrupt.h> 68 69/* 70** Register definitions for DMA controller 1 (channels 0..3): 71*/ 72#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */ 73#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */ 74#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */ 75#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */ 76 77/* 78** Register definitions for DMA controller 2 (channels 4..7): 79*/ 80#define DMA2_CHN(c) (IO_DMA2 + 2*(2*(c))) /* addr reg for channel c */ 81#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */ 82#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */ 83#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */ 84 85static void config_isadev __P((struct isa_device *isdp, u_int *mp)); 86static void config_isadev_c __P((struct isa_device *isdp, u_int *mp, 87 int reconfig)); 88static void conflict __P((struct isa_device *dvp, struct isa_device *tmpdvp, 89 int item, char const *whatnot, char const *reason, 90 char const *format)); 91static int haveseen __P((struct isa_device *dvp, struct isa_device *tmpdvp, 92 u_int checkbits)); 93static int isa_dmarangecheck __P((caddr_t va, u_int length, int chan)); 94 95/* 96 * print a conflict message 97 */ 98static void 99conflict(dvp, tmpdvp, item, whatnot, reason, format) 100 struct isa_device *dvp; 101 struct isa_device *tmpdvp; 102 int item; 103 char const *whatnot; 104 char const *reason; 105 char const *format; 106{ 107 printf("%s%d not %sed due to %s conflict with %s%d at ", 108 dvp->id_driver->name, dvp->id_unit, whatnot, reason, 109 tmpdvp->id_driver->name, tmpdvp->id_unit); 110 printf(format, item); 111 printf("\n"); 112} 113 114/* 115 * Check to see if things are already in use, like IRQ's, I/O addresses 116 * and Memory addresses. 117 */ 118static int 119haveseen(dvp, tmpdvp, checkbits) 120 struct isa_device *dvp; 121 struct isa_device *tmpdvp; 122 u_int checkbits; 123{ 124 /* 125 * Ignore all conflicts except IRQ ones if conflicts are allowed. 126 */ 127 if (dvp->id_conflicts) 128 checkbits &= ~(CC_DRQ | CC_IOADDR | CC_MEMADDR); 129 /* 130 * Only check against devices that have already been found. 131 */ 132 if (tmpdvp->id_alive) { 133 char const *whatnot; 134 135 whatnot = checkbits & CC_ATTACH ? "attach" : "prob"; 136 /* 137 * Check for I/O address conflict. We can only check the 138 * starting address of the device against the range of the 139 * device that has already been probed since we do not 140 * know how many I/O addresses this device uses. 141 */ 142 if (checkbits & CC_IOADDR && tmpdvp->id_alive != -1) { 143 if ((dvp->id_iobase >= tmpdvp->id_iobase) && 144 (dvp->id_iobase <= 145 (tmpdvp->id_iobase + tmpdvp->id_alive - 1))) { 146 conflict(dvp, tmpdvp, dvp->id_iobase, whatnot, 147 "I/O address", "0x%x"); 148 return 1; 149 } 150 } 151 /* 152 * Check for Memory address conflict. We can check for 153 * range overlap, but it will not catch all cases since the 154 * driver may adjust the msize paramater during probe, for 155 * now we just check that the starting address does not 156 * fall within any allocated region. 157 * XXX could add a second check after the probe for overlap, 158 * since at that time we would know the full range. 159 * XXX KERNBASE is a hack, we should have vaddr in the table! 160 */ 161 if (checkbits & CC_MEMADDR && tmpdvp->id_maddr) { 162 if ((KERNBASE + dvp->id_maddr >= tmpdvp->id_maddr) && 163 (KERNBASE + dvp->id_maddr <= 164 (tmpdvp->id_maddr + tmpdvp->id_msize - 1))) { 165 conflict(dvp, tmpdvp, (int)dvp->id_maddr, 166 whatnot, "maddr", "0x%x"); 167 return 1; 168 } 169 } 170 /* 171 * Check for IRQ conflicts. 172 */ 173 if (checkbits & CC_IRQ && tmpdvp->id_irq) { 174 if (tmpdvp->id_irq == dvp->id_irq) { 175 conflict(dvp, tmpdvp, ffs(dvp->id_irq) - 1, 176 whatnot, "irq", "%d"); 177 return 1; 178 } 179 } 180 /* 181 * Check for DRQ conflicts. 182 */ 183 if (checkbits & CC_DRQ && tmpdvp->id_drq != -1) { 184 if (tmpdvp->id_drq == dvp->id_drq) { 185 conflict(dvp, tmpdvp, dvp->id_drq, whatnot, 186 "drq", "%d"); 187 return 1; 188 } 189 } 190 } 191 return 0; 192} 193 194#ifdef RESOURCE_CHECK 195#include <sys/drvresource.h> 196 197static int 198checkone (struct isa_device *dvp, int type, addr_t low, addr_t high, 199 char *resname, char *resfmt, int attaching) 200{ 201 int result = 0; 202 if (bootverbose) { 203 if (low == high) 204 printf("\tcheck %s: 0x%x\n", resname, low); 205 else 206 printf("\tcheck %s: 0x%x to 0x%x\n", 207 resname, low, high); 208 } 209 if (resource_check(type, RESF_NONE, low, high) != NULL) { 210 char *whatnot = attaching ? "attach" : "prob"; 211 static struct isa_device dummydev; 212 static struct isa_driver dummydrv; 213 struct isa_device *tmpdvp = &dummydev; 214 215 dummydev.id_driver = &dummydrv; 216 dummydev.id_unit = 0; 217 dummydrv.name = "pci"; 218 conflict(dvp, tmpdvp, low, whatnot, resname, resfmt); 219 result = 1; 220 } else if (attaching) { 221 if (low == high) 222 printf("\tregister %s: 0x%x\n", resname, low); 223 else 224 printf("\tregister %s: 0x%x to 0x%x\n", 225 resname, low, high); 226 resource_claim(dvp, type, RESF_NONE, low, high); 227 } 228 return (result); 229} 230 231static int 232check_pciconflict(struct isa_device *dvp, int checkbits) 233{ 234 int result = 0; 235 int attaching = (checkbits & CC_ATTACH) != 0; 236 237 if (checkbits & CC_MEMADDR) { 238 long maddr = dvp->id_maddr; 239 long msize = dvp->id_msize; 240 if (msize > 0) { 241 if (checkone(dvp, REST_MEM, maddr, maddr + msize - 1, 242 "maddr", "0x%x", attaching) != 0) { 243 result = 1; 244 attaching = 0; 245 } 246 } 247 } 248 if (checkbits & CC_IOADDR) { 249 unsigned iobase = dvp->id_iobase; 250 unsigned iosize = dvp->id_alive; 251 if (iosize == -1) 252 iosize = 1; /* XXX can't do much about this ... */ 253 if (iosize > 0) { 254 if (checkone(dvp, REST_PORT, iobase, iobase + iosize -1, 255 "I/O address", "0x%x", attaching) != 0) { 256 result = 1; 257 attaching = 0; 258 } 259 } 260 } 261 if (checkbits & CC_IRQ) { 262 int irq = ffs(dvp->id_irq) - 1; 263 if (irq >= 0) { 264 if (checkone(dvp, REST_INT, irq, irq, 265 "irq", "%d", attaching) != 0) { 266 result = 1; 267 attaching = 0; 268 } 269 } 270 } 271 if (checkbits & CC_DRQ) { 272 int drq = dvp->id_drq; 273 if (drq >= 0) { 274 if (checkone(dvp, REST_DMA, drq, drq, 275 "drq", "%d", attaching) != 0) { 276 result = 1; 277 attaching = 0; 278 } 279 } 280 } 281 if (result != 0) 282 resource_free (dvp); 283 return (result); 284} 285#endif /* RESOURCE_CHECK */ 286 287/* 288 * Search through all the isa_devtab_* tables looking for anything that 289 * conflicts with the current device. 290 */ 291int 292haveseen_isadev(dvp, checkbits) 293 struct isa_device *dvp; 294 u_int checkbits; 295{ 296 struct isa_device *tmpdvp; 297 int status = 0; 298 299 for (tmpdvp = isa_devtab_tty; tmpdvp->id_driver; tmpdvp++) { 300 status |= haveseen(dvp, tmpdvp, checkbits); 301 if (status) 302 return status; 303 } 304 for (tmpdvp = isa_devtab_bio; tmpdvp->id_driver; tmpdvp++) { 305 status |= haveseen(dvp, tmpdvp, checkbits); 306 if (status) 307 return status; 308 } 309 for (tmpdvp = isa_devtab_net; tmpdvp->id_driver; tmpdvp++) { 310 status |= haveseen(dvp, tmpdvp, checkbits); 311 if (status) 312 return status; 313 } 314 for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) { 315 status |= haveseen(dvp, tmpdvp, checkbits); 316 if (status) 317 return status; 318 } 319#ifdef RESOURCE_CHECK 320 if (!dvp->id_conflicts) { 321 status = check_pciconflict(dvp, checkbits); 322 } else if (bootverbose) 323 printf("\tnot checking for resource conflicts ...\n"); 324 } 325#endif /* RESOURCE_CHECK */ 326 return(status); 327} 328 329/* 330 * Configure all ISA devices 331 */ 332void 333isa_configure() { 334 struct isa_device *dvp; 335 336 splhigh(); 337 printf("Probing for devices on the ISA bus:\n"); 338 /* First probe all the sensitive probes */ 339 for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) 340 if (dvp->id_driver->sensitive_hw) 341 config_isadev(dvp, &tty_imask); 342 for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) 343 if (dvp->id_driver->sensitive_hw) 344 config_isadev(dvp, &bio_imask); 345 for (dvp = isa_devtab_net; dvp->id_driver; dvp++) 346 if (dvp->id_driver->sensitive_hw) 347 config_isadev(dvp, &net_imask); 348 for (dvp = isa_devtab_null; dvp->id_driver; dvp++) 349 if (dvp->id_driver->sensitive_hw) 350 config_isadev(dvp, (u_int *)NULL); 351 352 /* Then all the bad ones */ 353 for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) 354 if (!dvp->id_driver->sensitive_hw) 355 config_isadev(dvp, &tty_imask); 356 for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) 357 if (!dvp->id_driver->sensitive_hw) 358 config_isadev(dvp, &bio_imask); 359 for (dvp = isa_devtab_net; dvp->id_driver; dvp++) 360 if (!dvp->id_driver->sensitive_hw) 361 config_isadev(dvp, &net_imask); 362 for (dvp = isa_devtab_null; dvp->id_driver; dvp++) 363 if (!dvp->id_driver->sensitive_hw) 364 config_isadev(dvp, (u_int *)NULL); 365 366 bio_imask |= SWI_CLOCK_MASK; 367 net_imask |= SWI_NET_MASK; 368 tty_imask |= SWI_TTY_MASK; 369 370/* 371 * XXX we should really add the tty device to net_imask when the line is 372 * switched to SLIPDISC, and then remove it when it is switched away from 373 * SLIPDISC. No need to block out ALL ttys during a splimp when only one 374 * of them is running slip. 375 * 376 * XXX actually, blocking all ttys during a splimp doesn't matter so much 377 * with sio because the serial interrupt layer doesn't use tty_imask. Only 378 * non-serial ttys suffer. It's more stupid that ALL 'net's are blocked 379 * during spltty. 380 */ 381#include "sl.h" 382#if NSL > 0 383 net_imask |= tty_imask; 384 tty_imask = net_imask; 385#endif 386 387 /* bio_imask |= tty_imask ; can some tty devices use buffers? */ 388 389 if (bootverbose) 390 printf("imasks: bio %x, tty %x, net %x\n", 391 bio_imask, tty_imask, net_imask); 392 393 /* 394 * Finish initializing intr_mask[]. Note that the partly 395 * constructed masks aren't actually used since we're at splhigh. 396 * For fully dynamic initialization, register_intr() and 397 * icu_unset() will have to adjust the masks for _all_ 398 * interrupts and for tty_imask, etc. 399 */ 400 for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) 401 register_imask(dvp, tty_imask); 402 for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) 403 register_imask(dvp, bio_imask); 404 for (dvp = isa_devtab_net; dvp->id_driver; dvp++) 405 register_imask(dvp, net_imask); 406 for (dvp = isa_devtab_null; dvp->id_driver; dvp++) 407 register_imask(dvp, SWI_CLOCK_MASK); 408 spl0(); 409} 410 411/* 412 * Configure an ISA device. 413 */ 414 415 416static void 417config_isadev(isdp, mp) 418 struct isa_device *isdp; 419 u_int *mp; 420{ 421 config_isadev_c(isdp, mp, 0); 422} 423 424void 425reconfig_isadev(isdp, mp) 426 struct isa_device *isdp; 427 u_int *mp; 428{ 429 config_isadev_c(isdp, mp, 1); 430} 431 432static void 433config_isadev_c(isdp, mp, reconfig) 434 struct isa_device *isdp; 435 u_int *mp; 436 int reconfig; 437{ 438 u_int checkbits; 439 int id_alive; 440 int last_alive; 441 struct isa_driver *dp = isdp->id_driver; 442 443 if (!isdp->id_enabled) { 444 printf("%s%d: disabled, not probed.\n", 445 dp->name, isdp->id_unit); 446 return; 447 } 448 checkbits = CC_DRQ | CC_IOADDR | CC_MEMADDR; 449 if (!reconfig && haveseen_isadev(isdp, checkbits)) 450 return; 451 if (!reconfig && isdp->id_maddr) { 452 isdp->id_maddr -= ISA_HOLE_START; 453 isdp->id_maddr += atdevbase; 454 } 455 if (reconfig) { 456 last_alive = isdp->id_alive; 457 isdp->id_reconfig = 1; 458 } 459 else { 460 last_alive = 0; 461 isdp->id_reconfig = 0; 462 } 463 id_alive = (*dp->probe)(isdp); 464 if (id_alive) { 465 /* 466 * Only print the I/O address range if id_alive != -1 467 * Right now this is a temporary fix just for the new 468 * NPX code so that if it finds a 486 that can use trap 469 * 16 it will not report I/O addresses. 470 * Rod Grimes 04/26/94 471 */ 472 if (!isdp->id_reconfig) { 473 printf("%s%d", dp->name, isdp->id_unit); 474 if (id_alive != -1) { 475 if (isdp->id_iobase == -1) 476 printf(" at ?"); 477 else { 478 printf(" at 0x%x", isdp->id_iobase); 479 if (isdp->id_iobase + id_alive - 1 != 480 isdp->id_iobase) { 481 printf("-0x%x", 482 isdp->id_iobase + id_alive - 1); 483 } 484 } 485 } 486 if (isdp->id_irq) 487 printf(" irq %d", ffs(isdp->id_irq) - 1); 488 if (isdp->id_drq != -1) 489 printf(" drq %d", isdp->id_drq); 490 if (isdp->id_maddr) 491 printf(" maddr 0x%lx", kvtop(isdp->id_maddr)); 492 if (isdp->id_msize) 493 printf(" msize %d", isdp->id_msize); 494 if (isdp->id_flags) 495 printf(" flags 0x%x", isdp->id_flags); 496 if (isdp->id_iobase && !(isdp->id_iobase & 0xf300)) { 497 printf(" on motherboard"); 498 } else if (isdp->id_iobase >= 0x1000 && 499 !(isdp->id_iobase & 0x300)) { 500 printf (" on eisa slot %d", 501 isdp->id_iobase >> 12); 502 } else { 503 printf (" on isa"); 504 } 505 printf("\n"); 506 /* 507 * Check for conflicts again. The driver may have 508 * changed *dvp. We should weaken the early check 509 * since the driver may have been able to change 510 * *dvp to avoid conflicts if given a chance. We 511 * already skip the early check for IRQs and force 512 * a check for IRQs in the next group of checks. 513 */ 514 checkbits |= CC_IRQ; 515 if (haveseen_isadev(isdp, checkbits)) 516 return; 517 isdp->id_alive = id_alive; 518 } 519 (*dp->attach)(isdp); 520 if (isdp->id_irq) { 521#ifdef APIC_IO 522 /* 523 * Some motherboards use upper IRQs for traditional 524 * ISA INTerrupt sources. In particular we have 525 * seen the secondary IDE connected to IRQ20. 526 * This code detects and fixes this situation. 527 */ 528 u_int apic_mask; 529 int rirq; 530 531 apic_mask = isa_apic_mask(isdp->id_irq); 532 if (apic_mask != isdp->id_irq) { 533 rirq = ffs(isdp->id_irq) - 1; 534 isdp->id_irq = apic_mask; 535 undirect_isa_irq(rirq); /* free for ISA */ 536 } 537#endif /* APIC_IO */ 538 register_intr(ffs(isdp->id_irq) - 1, isdp->id_id, 539 isdp->id_ri_flags, isdp->id_intr, 540 mp, isdp->id_unit); 541 } 542 } else { 543 if (isdp->id_reconfig) { 544 (*dp->attach)(isdp); /* reconfiguration attach */ 545 } 546 if (!last_alive) { 547 if (!isdp->id_reconfig) { 548 printf("%s%d not found", 549 dp->name, isdp->id_unit); 550 if (isdp->id_iobase != -1) 551 printf(" at 0x%x", isdp->id_iobase); 552 printf("\n"); 553 } 554 } 555 else { 556#if 0 557 /* This code has not been tested.... */ 558 if (isdp->id_irq) { 559 icu_unset(ffs(isdp->id_irq) - 1, 560 isdp->id_intr); 561 if (mp) 562 INTRUNMASK(*mp, isdp->id_irq); 563 } 564#else 565 printf ("icu_unset() not supported here ...\n"); 566#endif 567 } 568 } 569} 570 571static caddr_t dma_bouncebuf[8]; 572static u_int dma_bouncebufsize[8]; 573static u_int8_t dma_bounced = 0; 574static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */ 575static u_int8_t dma_inuse = 0; /* User for acquire/release */ 576 577#define VALID_DMA_MASK (7) 578 579/* high byte of address is stored in this port for i-th dma channel */ 580static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; 581 582/* 583 * Setup a DMA channel's bounce buffer. 584 */ 585void 586isa_dmainit(chan, bouncebufsize) 587 int chan; 588 u_int bouncebufsize; 589{ 590 void *buf; 591 592#ifdef DIAGNOSTIC 593 if (chan & ~VALID_DMA_MASK) 594 panic("isa_dmainit: channel out of range"); 595 596 if (dma_bouncebuf[chan] != NULL) 597 panic("isa_dmainit: impossible request"); 598#endif 599 600 dma_bouncebufsize[chan] = bouncebufsize; 601 602 /* Try malloc() first. It works better if it works. */ 603 buf = malloc(bouncebufsize, M_DEVBUF, M_NOWAIT); 604 if (buf != NULL) { 605 if (isa_dmarangecheck(buf, bouncebufsize, chan) == 0) { 606 dma_bouncebuf[chan] = buf; 607 return; 608 } 609 free(buf, M_DEVBUF); 610 } 611 buf = contigmalloc(bouncebufsize, M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful, 612 1ul, chan & 4 ? 0x20000ul : 0x10000ul); 613 if (buf == NULL) 614 printf("isa_dmainit(%d, %d) failed\n", chan, bouncebufsize); 615 else 616 dma_bouncebuf[chan] = buf; 617} 618 619/* 620 * Register a DMA channel's usage. Usually called from a device driver 621 * in open() or during it's initialization. 622 */ 623int 624isa_dma_acquire(chan) 625 int chan; 626{ 627#ifdef DIAGNOSTIC 628 if (chan & ~VALID_DMA_MASK) 629 panic("isa_dma_acquire: channel out of range"); 630#endif 631 632 if (dma_inuse & (1 << chan)) { 633 printf("isa_dma_acquire: channel %d already in use\n", chan); 634 return (EBUSY); 635 } 636 dma_inuse |= (1 << chan); 637 638 return (0); 639} 640 641/* 642 * Unregister a DMA channel's usage. Usually called from a device driver 643 * during close() or during it's shutdown. 644 */ 645void 646isa_dma_release(chan) 647 int chan; 648{ 649#ifdef DIAGNOSTIC 650 if (chan & ~VALID_DMA_MASK) 651 panic("isa_dma_release: channel out of range"); 652 653 if ((dma_inuse & (1 << chan)) == 0) 654 printf("isa_dma_release: channel %d not in use\n", chan); 655#endif 656 657 if (dma_busy & (1 << chan)) { 658 dma_busy &= ~(1 << chan); 659 /* 660 * XXX We should also do "dma_bounced &= (1 << chan);" 661 * because we are acting on behalf of isa_dmadone() which 662 * was not called to end the last DMA operation. This does 663 * not matter now, but it may in the future. 664 */ 665 } 666 667 dma_inuse &= ~(1 << chan); 668} 669 670/* 671 * isa_dmacascade(): program 8237 DMA controller channel to accept 672 * external dma control by a board. 673 */ 674void isa_dmacascade(chan) 675 int chan; 676{ 677#ifdef DIAGNOSTIC 678 if (chan & ~VALID_DMA_MASK) 679 panic("isa_dmacascade: channel out of range"); 680#endif 681 682 /* set dma channel mode, and set dma channel mode */ 683 if ((chan & 4) == 0) { 684 outb(DMA1_MODE, DMA37MD_CASCADE | chan); 685 outb(DMA1_SMSK, chan); 686 } else { 687 outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3)); 688 outb(DMA2_SMSK, chan & 3); 689 } 690} 691 692/* 693 * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment 694 * problems by using a bounce buffer. 695 */ 696void isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) 697{ 698 vm_offset_t phys; 699 int waport; 700 caddr_t newaddr; 701 702#ifdef DIAGNOSTIC 703 if (chan & ~VALID_DMA_MASK) 704 panic("isa_dmastart: channel out of range"); 705 706 if ((chan < 4 && nbytes > (1<<16)) 707 || (chan >= 4 && (nbytes > (1<<17) || (u_int)addr & 1))) 708 panic("isa_dmastart: impossible request"); 709 710 if ((dma_inuse & (1 << chan)) == 0) 711 printf("isa_dmastart: channel %d not acquired\n", chan); 712#endif 713 714#if 0 715 /* 716 * XXX This should be checked, but drivers like ad1848 only call 717 * isa_dmastart() once because they use Auto DMA mode. If we 718 * leave this in, drivers that do this will print this continuously. 719 */ 720 if (dma_busy & (1 << chan)) 721 printf("isa_dmastart: channel %d busy\n", chan); 722#endif 723 724 dma_busy |= (1 << chan); 725 726 if (isa_dmarangecheck(addr, nbytes, chan)) { 727 if (dma_bouncebuf[chan] == NULL 728 || dma_bouncebufsize[chan] < nbytes) 729 panic("isa_dmastart: bad bounce buffer"); 730 dma_bounced |= (1 << chan); 731 newaddr = dma_bouncebuf[chan]; 732 733 /* copy bounce buffer on write */ 734 if (!(flags & B_READ)) 735 bcopy(addr, newaddr, nbytes); 736 addr = newaddr; 737 } 738 739 /* translate to physical */ 740 phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr); 741 742 if ((chan & 4) == 0) { 743 /* 744 * Program one of DMA channels 0..3. These are 745 * byte mode channels. 746 */ 747 /* set dma channel mode, and reset address ff */ 748 749 /* If B_RAW flag is set, then use autoinitialise mode */ 750 if (flags & B_RAW) { 751 if (flags & B_READ) 752 outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan); 753 else 754 outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan); 755 } 756 else 757 if (flags & B_READ) 758 outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan); 759 else 760 outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan); 761 outb(DMA1_FFC, 0); 762 763 /* send start address */ 764 waport = DMA1_CHN(chan); 765 outb(waport, phys); 766 outb(waport, phys>>8); 767 outb(dmapageport[chan], phys>>16); 768 769 /* send count */ 770 outb(waport + 1, --nbytes); 771 outb(waport + 1, nbytes>>8); 772 773 /* unmask channel */ 774 outb(DMA1_SMSK, chan); 775 } else { 776 /* 777 * Program one of DMA channels 4..7. These are 778 * word mode channels. 779 */ 780 /* set dma channel mode, and reset address ff */ 781 782 /* If B_RAW flag is set, then use autoinitialise mode */ 783 if (flags & B_RAW) { 784 if (flags & B_READ) 785 outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3)); 786 else 787 outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3)); 788 } 789 else 790 if (flags & B_READ) 791 outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3)); 792 else 793 outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3)); 794 outb(DMA2_FFC, 0); 795 796 /* send start address */ 797 waport = DMA2_CHN(chan - 4); 798 outb(waport, phys>>1); 799 outb(waport, phys>>9); 800 outb(dmapageport[chan], phys>>16); 801 802 /* send count */ 803 nbytes >>= 1; 804 outb(waport + 2, --nbytes); 805 outb(waport + 2, nbytes>>8); 806 807 /* unmask channel */ 808 outb(DMA2_SMSK, chan & 3); 809 } 810} 811 812void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) 813{ 814#ifdef DIAGNOSTIC 815 if (chan & ~VALID_DMA_MASK) 816 panic("isa_dmadone: channel out of range"); 817 818 if ((dma_inuse & (1 << chan)) == 0) 819 printf("isa_dmadone: channel %d not acquired\n", chan); 820#endif 821 822#if 0 823 /* 824 * XXX This should be checked, but drivers like ad1848 only call 825 * isa_dmastart() once because they use Auto DMA mode. If we 826 * leave this in, drivers that do this will print this continuously. 827 */ 828 if ((dma_busy & (1 << chan)) == 0) 829 printf("isa_dmadone: channel %d not busy\n", chan); 830#endif 831 832 if (dma_bounced & (1 << chan)) { 833 /* copy bounce buffer on read */ 834 if (flags & B_READ) 835 bcopy(dma_bouncebuf[chan], addr, nbytes); 836 837 dma_bounced &= ~(1 << chan); 838 } 839 dma_busy &= ~(1 << chan); 840} 841 842/* 843 * Check for problems with the address range of a DMA transfer 844 * (non-contiguous physical pages, outside of bus address space, 845 * crossing DMA page boundaries). 846 * Return true if special handling needed. 847 */ 848 849static int 850isa_dmarangecheck(caddr_t va, u_int length, int chan) { 851 vm_offset_t phys, priorpage = 0, endva; 852 u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); 853 854 endva = (vm_offset_t)round_page(va + length); 855 for (; va < (caddr_t) endva ; va += PAGE_SIZE) { 856 phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va)); 857#define ISARAM_END RAM_END 858 if (phys == 0) 859 panic("isa_dmacheck: no physical page present"); 860 if (phys >= ISARAM_END) 861 return (1); 862 if (priorpage) { 863 if (priorpage + PAGE_SIZE != phys) 864 return (1); 865 /* check if crossing a DMA page boundary */ 866 if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk) 867 return (1); 868 } 869 priorpage = phys; 870 } 871 return (0); 872} 873 874/* 875 * Query the progress of a transfer on a DMA channel. 876 * 877 * To avoid having to interrupt a transfer in progress, we sample 878 * each of the high and low databytes twice, and apply the following 879 * logic to determine the correct count. 880 * 881 * Reads are performed with interrupts disabled, thus it is to be 882 * expected that the time between reads is very small. At most 883 * one rollover in the low count byte can be expected within the 884 * four reads that are performed. 885 * 886 * There are three gaps in which a rollover can occur : 887 * 888 * - read low1 889 * gap1 890 * - read high1 891 * gap2 892 * - read low2 893 * gap3 894 * - read high2 895 * 896 * If a rollover occurs in gap1 or gap2, the low2 value will be 897 * greater than the low1 value. In this case, low2 and high2 are a 898 * corresponding pair. 899 * 900 * In any other case, low1 and high1 can be considered to be correct. 901 * 902 * The function returns the number of bytes remaining in the transfer, 903 * or -1 if the channel requested is not active. 904 * 905 */ 906int 907isa_dmastatus(int chan) 908{ 909 u_long cnt = 0; 910 int ffport, waport; 911 u_long low1, high1, low2, high2; 912 u_long ef; 913 914 /* channel active? */ 915 if ((dma_inuse & (1 << chan)) == 0) { 916 printf("isa_dmastatus: channel %d not active\n", chan); 917 return(-1); 918 } 919 920 /* still busy? */ 921 if ((dma_busy & (1 << chan)) == 0) { 922 return(0); 923 } 924 925 if (chan < 4) { /* low DMA controller */ 926 ffport = DMA1_FFC; 927 waport = DMA1_CHN(chan) + 1; 928 } else { /* high DMA controller */ 929 ffport = DMA2_FFC; 930 waport = DMA2_CHN(chan - 4) + 2; 931 } 932 933 disable_intr(); /* no interrupts Mr Jones! */ 934 outb(ffport, 0); /* clear register LSB flipflop */ 935 low1 = inb(waport); 936 high1 = inb(waport); 937 outb(ffport, 0); /* clear again */ 938 low2 = inb(waport); 939 high2 = inb(waport); 940 enable_intr(); /* enable interrupts again */ 941 942 /* 943 * Now decide if a wrap has tried to skew our results. 944 * Note that after TC, the count will read 0xffff, while we want 945 * to return zero, so we add and then mask to compensate. 946 */ 947 if (low1 >= low2) { 948 cnt = (low1 + (high1 << 8) + 1) & 0xffff; 949 } else { 950 cnt = (low2 + (high2 << 8) + 1) & 0xffff; 951 } 952 953 if (chan >= 4) /* high channels move words */ 954 cnt *= 2; 955 return(cnt); 956} 957 958/* 959 * Find the highest priority enabled display device. Since we can't 960 * distinguish display devices from ttys, depend on display devices 961 * being sensitive and before sensitive non-display devices (if any) 962 * in isa_devtab_tty. 963 * 964 * XXX we should add capability flags IAMDISPLAY and ISUPPORTCONSOLES. 965 */ 966struct isa_device * 967find_display() 968{ 969 struct isa_device *dvp; 970 971 for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) 972 if (dvp->id_driver->sensitive_hw && dvp->id_enabled) 973 return (dvp); 974 return (NULL); 975} 976 977/* 978 * find an ISA device in a given isa_devtab_* table, given 979 * the table to search, the expected id_driver entry, and the unit number. 980 * 981 * this function is defined in isa_device.h, and this location is debatable; 982 * i put it there because it's useless w/o, and directly operates on 983 * the other stuff in that file. 984 * 985 */ 986 987struct isa_device *find_isadev(table, driverp, unit) 988 struct isa_device *table; 989 struct isa_driver *driverp; 990 int unit; 991{ 992 if (driverp == NULL) /* sanity check */ 993 return (NULL); 994 995 while ((table->id_driver != driverp) || (table->id_unit != unit)) { 996 if (table->id_driver == 0) 997 return NULL; 998 999 table++; 1000 } 1001 1002 return (table); 1003} 1004