1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ 29 /* All Rights Reserved */ 30 31 /* Copyright (c) 1988, 1989 Intel Corp. */ 32 /* All Rights Reserved */ 33 34 /* 35 * Set features for each architecture. List of features: 36 * ADDR_32: Address is 32 bits 37 * COUNT_24: Count is 24 bits 38 * DMA_4CSCD: DMA channel 4 is used for cascade of channels 0-3) 39 * DMA_INTR: DMA interrupt is available (always with DMA_BUF_CHAIN) 40 * DMA_BUF_CHAIN: DMA buffer chaining is available (always with DMA_INTR) 41 * MEM_TO_MEM: Memory to memory transfers available 42 * NO_PROG_WIDTH: Channel data width is NOT programmable 43 * SCATER_GATHER Scatter-gather DMA is available (code not implemented) 44 * ISA_MODE Standard ISA modes available 45 * EISA_EXT_MODE: EISA extension modes available 46 */ 47 48 /* 49 * Address is 24 bits (default) with no carry between lo word and hi byte 50 * Count is 16 bits (default) 51 */ 52 #define DMA_4CSCD 53 #define NO_PROG_WIDTH 54 #define ISA_MODE 55 56 #include <sys/types.h> 57 #include <sys/cpuvar.h> 58 #include <sys/disp.h> 59 #include <sys/sunddi.h> 60 #include <sys/cmn_err.h> 61 #include <sys/dma_engine.h> 62 #include <sys/dma_i8237A.h> 63 64 #if defined(DEBUG) 65 #include <sys/promif.h> 66 static int i8237debug = 0; 67 #define dprintf(x) if (i8237debug) (void)prom_printf x 68 #else 69 #define dprintf(x) 70 #endif /* defined(DEBUG) */ 71 72 73 extern int EISA_chaining; 74 75 /* 76 * data structures for maintaining the DMACs 77 */ 78 static kmutex_t dma_engine_lock; 79 static struct d37A_chan_reg_addr chan_addr[] = { D37A_BASE_REGS_VALUES }; 80 static ushort_t d37A_chnl_path[] = { 81 DMAE_PATH_8, /* first 4 DMA channels default to 8-bit xfers */ 82 DMAE_PATH_8, 83 DMAE_PATH_8, 84 DMAE_PATH_8, 85 0, 86 DMAE_PATH_16, /* last 3 DMA channels default to 16-bit xfers */ 87 DMAE_PATH_16, 88 DMAE_PATH_16}; 89 static ushort_t d37A_chnl_mode[] = { 90 DMAE_TRANS_SNGL, DMAE_TRANS_SNGL, DMAE_TRANS_SNGL, DMAE_TRANS_SNGL, 91 #ifdef DMA_4CSCD 92 DMAE_TRANS_CSCD, 93 #else /* !DMA_4CSCD */ 94 DMAE_TRANS_SNGL, 95 #endif /* !DMA_4CSCD */ 96 DMAE_TRANS_SNGL, DMAE_TRANS_SNGL, DMAE_TRANS_SNGL}; 97 #ifdef DMA_BUF_CHAIN 98 static ddi_dma_cookie_t *d37A_next_cookie[] = 99 {0, 0, 0, 0, 0, 0, 0, 0}; 100 #endif /* DMA_BUF_CHAIN */ 101 102 103 #ifdef DMA_INTR 104 static uint_t d37A_intr(caddr_t); 105 #endif 106 static int d37A_set_mode(struct ddi_dmae_req *, int); 107 static int d37A_write_addr(ulong_t, int); 108 static ulong_t d37A_read_addr(int); 109 static int d37A_write_count(long, int); 110 static long d37A_read_count(int); 111 112 #ifdef DMA_BUF_CHAIN 113 static void dEISA_setchain(ddi_dma_cookie_t *cp, int chnl); 114 #endif 115 116 /* 117 * Routine: d37A_init() 118 * purpose: initializes the 8237A. 119 * caller: dma_init() 120 * calls: d37A macros, d37A_init() 121 */ 122 123 /*ARGSUSED*/ 124 int 125 d37A_init(dev_info_t *dip) 126 { 127 #ifdef DMA_INTR 128 ddi_iblock_cookie_t iblk_cookie = 0; 129 int error; 130 131 if ((error = ddi_add_intr(dip, (uint_t)0, &iblk_cookie, 132 (ddi_idevice_cookie_t *)0, d37A_intr, (caddr_t)NULL)) != 133 DDI_SUCCESS) { 134 if (error != DDI_INTR_NOTFOUND) 135 cmn_err(CE_WARN, "!d37A_init: cannot add dma intr\n"); 136 EISA_chaining = 0; 137 } 138 mutex_init(&dma_engine_lock, NULL, MUTEX_DRIVER, (void *)iblk_cookie); 139 #else /* !DMA_INTR */ 140 mutex_init(&dma_engine_lock, NULL, MUTEX_DRIVER, NULL); 141 #endif /* !DMA_INTR */ 142 143 return (DDI_SUCCESS); 144 } 145 146 /* 147 * Routine: d37A_valid() 148 * purpose: validates the channel to be acquired. 149 * caller: i_dmae_acquire() 150 * calls: 151 */ 152 153 int 154 d37A_dma_valid(int chnl) 155 { 156 #ifdef DMA_4CSCD 157 if (chnl == 4) 158 return (0); 159 #endif /* DMA_4CSCD */ 160 return (1); 161 } 162 163 /* 164 * Routine: d37A_release() 165 * purpose: resets the 8237A mode. 166 * caller: i_dmae_free() 167 * calls: 168 */ 169 170 void 171 d37A_dma_release(int chnl) 172 { 173 #ifdef DMA_4CSCD 174 if (chnl == 4) 175 return; 176 #endif /* DMA_4CSCD */ 177 d37A_chnl_mode[chnl] = DMAE_TRANS_SNGL; 178 } 179 180 /* 181 * routine: d37A_dma_disable() 182 * purpose: Prevent the DMAC from responding to external hardware 183 * requests for DMA service on the given channel 184 * caller: dma_disable() 185 * calls: d37A macros 186 */ 187 void 188 d37A_dma_disable(int chnl) 189 { 190 dprintf(("d37A_dma_disable: chnl=%d mask_reg=0x%x\n", 191 chnl, chan_addr[chnl].mask_reg)); 192 193 outb(chan_addr[chnl].mask_reg, (chnl & 3) | DMA_SETMSK); 194 } 195 196 197 /* 198 * routine: d37A_dma_enable() 199 * purpose: Enable to DMAC to respond to hardware requests for DMA 200 * service on the specified channel. 201 * caller: dma_enable() 202 * calls: d37A macros 203 */ 204 205 void 206 d37A_dma_enable(int chnl) 207 { 208 dprintf(("d37A_dma_enable: chnl=%d mask_reg=0x%x val=0x%x\n", 209 chnl, chan_addr[chnl].mask_reg, chnl & 3)); 210 211 /* mutex_enter(&dma_engine_lock); */ 212 outb(chan_addr[chnl].mask_reg, chnl & 3); 213 /* mutex_exit(&dma_engine_lock); */ 214 } 215 216 217 /* 218 * routine: d37A_get_best_mode() 219 * purpose: stub routine - determine optimum transfer method 220 * caller: dma_get_best_mode(). 221 * calls: 222 */ 223 /* ARGSUSED */ 224 uchar_t 225 d37A_get_best_mode(struct ddi_dmae_req *dmaereqp) 226 { 227 return (DMAE_CYCLES_2); 228 } 229 230 #ifdef DMA_INTR 231 /* 232 * routine: d37A_intr() 233 * purpose: stub routine 234 * caller: 235 * calls: dma_intr(). 236 */ 237 /*ARGSUSED*/ 238 static uint_t 239 d37A_intr(caddr_t arg) 240 { 241 int chnl, istate, nstate; 242 uint_t mask; 243 244 if ((istate = (inb(EISA_DMAIS) & 0xef)) != 0) { 245 /* channel 4 can't interrupt */ 246 chnl = 0; 247 nstate = istate; 248 mutex_enter(&dma_engine_lock); 249 do { 250 if (istate & 1) { 251 dEISA_setchain(d37A_next_cookie[chnl], chnl); 252 #ifdef DEBUG 253 if (chnl < 4) 254 mask = inb(DMAC1_ALLMASK) >> (chnl); 255 else 256 mask = inb(DMAC2_ALLMASK) >> (chnl - 4); 257 if (mask & 1) 258 prom_printf("eisa: dma buffer chaining failure chnl %d!\n", chnl); 259 260 #endif /* DEBUG */ 261 } 262 chnl++; 263 istate >>= 1; 264 } while (istate); 265 chnl = 0; 266 do { 267 if ((nstate & 1) && d37A_next_cookie[chnl]) 268 d37A_next_cookie[chnl] = _dmae_nxcookie(chnl); 269 chnl++; 270 nstate >>= 1; 271 } while (nstate); 272 mutex_exit(&dma_engine_lock); 273 return (DDI_INTR_CLAIMED); 274 } 275 return (DDI_INTR_UNCLAIMED); 276 } 277 #endif /* DMA_INTR */ 278 279 280 #ifdef DMA_BUF_CHAIN 281 /* 282 * routine: dEISA_setchain() 283 * purpose: Set next buffer address/count from chain 284 * caller: d37A_intr() 285 * calls: d37A macros 286 */ 287 static void 288 dEISA_setchain(ddi_dma_cookie_t *cp, int chnl) 289 { 290 if (cp) { 291 dprintf(("dEISA_setchain: chnl=%d next_addr=%x count=%lx\n", 292 chnl, cp->dmac_address, cp->dmac_size)); 293 (void) d37A_write_addr(cp->dmac_address, chnl); 294 (void) d37A_write_count(cp->dmac_size, chnl); 295 outb(chan_addr[chnl].scm_reg, chnl | EISA_ENCM | EISA_CMOK); 296 } else { 297 /* 298 * clear chain enable bit 299 */ 300 outb(chan_addr[chnl].scm_reg, chnl); 301 dprintf(("dEISA_setchain: chnl=%d end\n", chnl)); 302 } 303 } 304 #endif /* DMA_BUF_CHAIN */ 305 306 307 /* 308 * routine: d37A_prog_chan() 309 * purpose: program the Mode registers and the Base registers of a 310 * DMA channel for a subsequent hardware-initiated transfer. 311 * caller: dma_prog_chan() 312 * calls: d37A_write_addr(), d37A_write_count(), d37A macros. 313 */ 314 315 int 316 d37A_prog_chan(struct ddi_dmae_req *dmaereqp, ddi_dma_cookie_t *cp, int chnl) 317 { 318 if (d37A_chnl_mode[chnl] == DMAE_TRANS_CSCD) { 319 dprintf(("d37A_prog_chan err: chnl=%d in cascade mode\n", 320 chnl)); 321 return (DDI_FAILURE); 322 } 323 #ifndef MEM_TO_MEM 324 if (dmaereqp && dmaereqp->der_dest == DMAE_DEST_MEM) { 325 dprintf(("d37A_prog_chan err: memory to memory mode not supported.\n")); 326 return (DDI_FAILURE); 327 } 328 #endif /* !MEM_TO_MEM */ 329 330 dprintf(("d37A_prog_chan: chnl=%d dmaereq=%p\n", 331 chnl, (void *)dmaereqp)); 332 333 if (dmaereqp) { 334 switch (chnl) { 335 case DMAE_CH0: 336 case DMAE_CH1: 337 case DMAE_CH2: 338 case DMAE_CH3: 339 #ifdef NO_PROG_WIDTH 340 if (dmaereqp->der_path && 341 dmaereqp->der_path != DMAE_PATH_8) { 342 dprintf(("d37A_prog_chan err: chnl %d not programmed.\n", chnl)); 343 return (DDI_FAILURE); 344 } 345 #endif /* NO_PROG_WIDTH */ 346 break; 347 348 #ifndef DMA_4CSCD 349 case DMAE_CH4: 350 #endif /* !DMA_4CSCD */ 351 case DMAE_CH5: 352 case DMAE_CH6: 353 case DMAE_CH7: 354 #ifdef NO_PROG_WIDTH 355 if (dmaereqp->der_path && 356 dmaereqp->der_path != DMAE_PATH_16) { 357 dprintf(("d37A_prog_chan err: chnl %d not programmed.\n", chnl)); 358 return (DDI_FAILURE); 359 } 360 #endif /* NO_PROG_WIDTH */ 361 break; 362 363 default: 364 dprintf(("d37A_prog_chan err: chnl %d not programmed.\n", chnl)); 365 return (DDI_FAILURE); 366 } 367 } else 368 chnl &= 3; 369 mutex_enter(&dma_engine_lock); 370 371 d37A_dma_disable(chnl); 372 if (dmaereqp) 373 (void) d37A_set_mode(dmaereqp, chnl); 374 375 if (cp) { 376 (void) d37A_write_addr(cp->dmac_address, chnl); 377 (void) d37A_write_count(cp->dmac_size, chnl); 378 379 #ifdef DMA_BUF_CHAIN 380 if (dmaereqp && dmaereqp->der_bufprocess == DMAE_BUF_CHAIN && 381 (d37A_next_cookie[chnl] = _dmae_nxcookie(chnl))) { 382 /* 383 * i/o operation has more than 1 cookie 384 * so enable dma buffer chaining 385 */ 386 drv_usecwait(10); 387 outb(chan_addr[chnl].scm_reg, chnl | EISA_ENCM); 388 drv_usecwait(15); 389 dEISA_setchain(d37A_next_cookie[chnl], chnl); 390 d37A_next_cookie[chnl] = _dmae_nxcookie(chnl); 391 } 392 #endif /* DMA_BUF_CHAIN */ 393 } 394 mutex_exit(&dma_engine_lock); 395 return (DDI_SUCCESS); 396 } 397 398 399 /* 400 * routine: d37A_dma_swsetup() 401 * purpose: program the Mode registers and the Base register for the 402 * specified channel. 403 * caller: dma_swsetup() 404 * calls: d37A_write_addr(), d37A_write_count(), d37A macros. 405 */ 406 407 int 408 d37A_dma_swsetup(struct ddi_dmae_req *dmaereqp, ddi_dma_cookie_t *cp, int chnl) 409 { 410 if (d37A_chnl_mode[chnl] == DMAE_TRANS_CSCD) { 411 dprintf(("d37A_dma_swsetup err: chnl %d not programmed\n", 412 chnl)); 413 return (DDI_FAILURE); 414 } 415 416 dprintf(("d37A_dma_swsetup: chnl=%d dmaereq=%p.\n", 417 chnl, (void *)dmaereqp)); 418 419 /* MUST BE IN BLOCK MODE FOR SOFTWARE INITIATED REQUESTS */ 420 if (dmaereqp->der_trans != DMAE_TRANS_BLCK) 421 dmaereqp->der_trans = DMAE_TRANS_BLCK; 422 423 switch (chnl) { 424 case DMAE_CH0: 425 case DMAE_CH1: 426 case DMAE_CH2: 427 case DMAE_CH3: 428 #ifdef NO_PROG_WIDTH 429 if (dmaereqp->der_path && dmaereqp->der_path != DMAE_PATH_8) { 430 dprintf(("d37A_dma_swsetup err: chnl %d not programmed.\n", chnl)); 431 return (DDI_FAILURE); 432 } 433 #endif /* NO_PROG_WIDTH */ 434 break; 435 436 #ifndef DMA_4CSCD 437 case DMAE_CH4: 438 #endif /* !DMA_4CSCD */ 439 case DMAE_CH5: 440 case DMAE_CH6: 441 case DMAE_CH7: 442 #ifdef NO_PROG_WIDTH 443 if (dmaereqp->der_path && dmaereqp->der_path != DMAE_PATH_16) { 444 dprintf(("d37A_dma_swsetup err: chnl %d not programmed.\n", chnl)); 445 return (DDI_FAILURE); 446 } 447 #endif /* NO_PROG_WIDTH */ 448 break; 449 450 default: 451 dprintf(("d37A_dma_swsetup err: chnl %d not set up.\n", chnl)); 452 return (DDI_FAILURE); 453 }; 454 455 mutex_enter(&dma_engine_lock); 456 457 d37A_dma_disable(chnl); 458 (void) d37A_set_mode(dmaereqp, chnl); 459 460 (void) d37A_write_addr(cp->dmac_address, chnl); 461 (void) d37A_write_count(cp->dmac_size, chnl); 462 463 #ifdef DMA_BUF_CHAIN 464 if (dmaereqp->der_bufprocess == DMAE_BUF_CHAIN && 465 (d37A_next_cookie[chnl] = _dmae_nxcookie(chnl))) { 466 /* 467 * i/o operation has more than 1 cookie 468 * so enable dma buffer chaining 469 */ 470 outb(chan_addr[chnl].scm_reg, chnl | EISA_ENCM); 471 dEISA_setchain(d37A_next_cookie[chnl], chnl); 472 d37A_next_cookie[chnl] = _dmae_nxcookie(chnl); 473 } 474 #endif /* DMA_BUF_CHAIN */ 475 mutex_exit(&dma_engine_lock); 476 return (DDI_SUCCESS); 477 } 478 479 480 /* 481 * routine: d37A_dma_swstart() 482 * purpose: SW start transfer setup on the indicated channel. 483 * caller: dma_swstart() 484 * calls: d37A_dma_enable(), d37A macros 485 */ 486 487 void 488 d37A_dma_swstart(int chnl) 489 { 490 dprintf(("d37A_dma_swstart: chnl=%d\n", chnl)); 491 492 mutex_enter(&dma_engine_lock); 493 d37A_dma_enable(chnl); 494 outb(chan_addr[chnl].reqt_reg, DMA_SETMSK | chnl); /* set request bit */ 495 mutex_exit(&dma_engine_lock); 496 } 497 498 499 /* 500 * routine: d37A_dma_stop() 501 * purpose: Stop any activity on the indicated channel. 502 * caller: dma_stop() 503 * calls: d37A macros 504 */ 505 506 void 507 d37A_dma_stop(int chnl) 508 { 509 dprintf(("d37A_dma_stop: chnl=%d\n", chnl)); 510 511 mutex_enter(&dma_engine_lock); 512 d37A_dma_disable(chnl); 513 outb(chan_addr[chnl].reqt_reg, chnl & 3); /* reset request bit */ 514 mutex_exit(&dma_engine_lock); 515 } 516 517 518 /* 519 * routine: d37A_get_chan_stat() 520 * purpose: retrieve the Current Address and Count registers for the 521 * specified channel. 522 * caller: dma_get_chan_stat() 523 * calls: d37A_read_addr(), d37A_read_count(). 524 */ 525 void 526 d37A_get_chan_stat(int chnl, ulong_t *addressp, int *countp) 527 { 528 ulong_t taddr; 529 int tcount; 530 531 mutex_enter(&dma_engine_lock); 532 taddr = d37A_read_addr(chnl); 533 tcount = d37A_read_count(chnl); 534 mutex_exit(&dma_engine_lock); 535 if (addressp) 536 *addressp = taddr; 537 if (countp) 538 *countp = tcount; 539 dprintf(("d37A_get_chan_stat: chnl=%d address=%lx count=%x\n", 540 chnl, taddr, tcount)); 541 } 542 543 544 /* 545 * routine: d37A_set_mode() 546 * purpose: program the Mode registers of the 547 * DMAC for a subsequent hardware-initiated transfer. 548 * caller: d37A_prog_chan(), d37A_dma_swsetup 549 * calls: 550 */ 551 552 static int 553 d37A_set_mode(struct ddi_dmae_req *dmaereqp, int chnl) 554 { 555 uchar_t mode = 0, emode = 0; 556 557 #ifdef ISA_MODE 558 #if defined(lint) 559 emode = emode; 560 #endif 561 mode = chnl & 3; 562 563 switch (dmaereqp->der_command) { 564 case DMAE_CMD_READ: 565 mode |= DMAMODE_READ; 566 break; 567 case DMAE_CMD_WRITE: 568 mode |= DMAMODE_WRITE; 569 break; 570 case DMAE_CMD_VRFY: 571 mode |= DMAMODE_VERF; 572 break; 573 case DMAE_CMD_TRAN: 574 mode |= 0x0C; /* for Adaptec 1st party DMA on chnl 0 */ 575 break; 576 default: 577 return (DDI_FAILURE); 578 } 579 580 if (dmaereqp->der_bufprocess == DMAE_BUF_AUTO) 581 mode |= DMAMODE_AUTO; 582 583 if (dmaereqp->der_step == DMAE_STEP_DEC) 584 mode |= DMAMODE_DECR; 585 586 switch (dmaereqp->der_trans) { 587 case DMAE_TRANS_SNGL: 588 mode |= DMAMODE_SINGLE; 589 break; 590 case DMAE_TRANS_BLCK: 591 mode |= DMAMODE_BLOCK; 592 break; 593 case DMAE_TRANS_DMND: 594 break; 595 case DMAE_TRANS_CSCD: 596 mode |= DMAMODE_CASC; 597 break; 598 default: 599 return (DDI_FAILURE); 600 } 601 d37A_chnl_mode[chnl] = dmaereqp->der_trans; 602 603 dprintf(("d37A_set_mode: chnl=%d mode_reg=0x%x mode=0x%x\n", 604 chnl, chan_addr[chnl].mode_reg, mode)); 605 outb(chan_addr[chnl].mode_reg, mode); 606 #endif /* ISA_MODE */ 607 608 #ifdef EISA_EXT_MODE 609 emode = chnl & 3; 610 d37A_chnl_path[chnl] = dmaereqp->der_path; 611 612 switch (dmaereqp->der_path) { 613 case DMAE_PATH_8: 614 /* emode |= EISA_DMA_8; */ 615 break; 616 case DMAE_PATH_16: 617 emode |= EISA_DMA_16; 618 break; 619 case DMAE_PATH_32: 620 emode |= EISA_DMA_32; 621 break; 622 case DMAE_PATH_16B: 623 emode |= EISA_DMA_16B; 624 break; 625 default: 626 switch (chnl) { 627 case DMAE_CH0: 628 case DMAE_CH1: 629 case DMAE_CH2: 630 case DMAE_CH3: 631 d37A_chnl_path[chnl] = DMAE_PATH_8; 632 /* emode |= EISA_DMA_8; */ 633 break; 634 case DMAE_CH5: 635 case DMAE_CH6: 636 case DMAE_CH7: 637 d37A_chnl_path[chnl] = DMAE_PATH_16; 638 emode |= EISA_DMA_16; 639 break; 640 } 641 } 642 emode |= (dmaereqp->der_cycles & 3) << 4; 643 outb(chan_addr[chnl].emode_reg, emode); 644 645 dprintf(("d37A_set_mode: chnl=%d em_reg=0x%x emode=0x%x\n", 646 chnl, chan_addr[chnl].emode_reg, emode)); 647 #endif /* EISA_EXT_MODE */ 648 return (DDI_SUCCESS); 649 } 650 651 652 /* 653 * routine: d37A_write_addr() 654 * purpose: write the 24- or 32-bit physical address into the Base Address 655 * Register for the indicated channel. 656 * caller: d37A_prog_chan(), d37A_dma_swsetup(). 657 * calls: d37A macros 658 */ 659 660 static int 661 d37A_write_addr(ulong_t paddress, int chnl) 662 { 663 uchar_t *adr_byte; 664 665 dprintf(("d37A_write_addr: chnl=%d address=%lx\n", chnl, paddress)); 666 667 switch (d37A_chnl_path[chnl]) { 668 case DMAE_PATH_8: 669 case DMAE_PATH_16B: 670 case DMAE_PATH_32: 671 /* 672 * program DMA controller with byte address 673 */ 674 break; 675 676 case DMAE_PATH_16: 677 /* 678 * convert byte address to shifted word address 679 */ 680 paddress = (paddress & ~0x1ffff) | ((paddress & 0x1ffff) >> 1); 681 break; 682 683 default: 684 return (DDI_FAILURE); 685 } 686 kpreempt_disable(); /* don't preempt thread while using flip-flop */ 687 outb(chan_addr[chnl].ff_reg, 0); /* set flipflop */ 688 689 adr_byte = (uchar_t *)&paddress; 690 outb(chan_addr[chnl].addr_reg, adr_byte[0]); 691 outb(chan_addr[chnl].addr_reg, adr_byte[1]); 692 outb(chan_addr[chnl].page_reg, adr_byte[2]); 693 #ifdef ADDR_32 694 outb(chan_addr[chnl].hpage_reg, adr_byte[3]); 695 #endif /* ADDR_32 */ 696 697 kpreempt_enable(); 698 return (DDI_SUCCESS); 699 } 700 701 702 /* 703 * routine: d37A_read_addr() 704 * purpose: read the 24- or 32-bit physical address from the Current Address 705 * Register for the indicated channel. 706 * caller: d37A_get_chan_stat(). 707 * calls: d37A macros 708 */ 709 710 static ulong_t 711 d37A_read_addr(int chnl) 712 { 713 ulong_t paddress = 0; 714 uchar_t *adr_byte; 715 716 kpreempt_disable(); /* don't preempt thread while using flip-flop */ 717 adr_byte = (uchar_t *)&paddress; 718 outb(chan_addr[chnl].ff_reg, 0); /* set flipflop */ 719 720 adr_byte[0] = inb(chan_addr[chnl].addr_reg); 721 adr_byte[1] = inb(chan_addr[chnl].addr_reg); 722 adr_byte[2] = inb(chan_addr[chnl].page_reg); 723 #ifdef ADDR_32 724 adr_byte[3] = inb(chan_addr[chnl].hpage_reg); 725 #endif /* ADDR_32 */ 726 727 kpreempt_enable(); 728 729 switch (d37A_chnl_path[chnl]) { 730 case DMAE_PATH_8: 731 case DMAE_PATH_16B: 732 case DMAE_PATH_32: 733 /* 734 * return with byte address 735 */ 736 break; 737 738 case DMAE_PATH_16: 739 /* 740 * convert shifted word address to byte address 741 */ 742 paddress = (paddress & ~0x1ffff) | ((paddress & 0x0ffff) << 1); 743 break; 744 745 default: 746 return ((ulong_t)DDI_FAILURE); 747 } 748 749 dprintf(("d37A_read_addr: chnl=%d address=%lx.\n", chnl, paddress)); 750 return (paddress); 751 } 752 753 754 /* 755 * routine: d37A_write_count() 756 * purpose: write the 16- or 24-bit count into the Base Count Register for 757 * the indicated channel. 758 * caller: d37A_prog_chan(), d37A_dma_swsetup() 759 * calls: d37A macros 760 */ 761 762 static int 763 d37A_write_count(long count, int chnl) 764 { 765 uchar_t *count_byte; 766 767 dprintf(("d37A_write_count: chnl=%d count=0x%lx\n", chnl, count)); 768 769 switch (d37A_chnl_path[chnl]) { 770 case DMAE_PATH_16: 771 /* 772 * Convert byte count to word count 773 */ 774 count >>= 1; 775 /* FALLTHROUGH */ 776 case DMAE_PATH_8: 777 case DMAE_PATH_16B: 778 case DMAE_PATH_32: 779 --count; 780 break; 781 782 default: 783 return (DDI_FAILURE); 784 } 785 786 kpreempt_disable(); /* don't preempt thread while using flip-flop */ 787 outb(chan_addr[chnl].ff_reg, 0); /* set flipflop */ 788 789 count_byte = (uchar_t *)&count; 790 outb(chan_addr[chnl].cnt_reg, count_byte[0]); 791 outb(chan_addr[chnl].cnt_reg, count_byte[1]); 792 #ifdef COUNT_24 793 outb(chan_addr[chnl].hcnt_reg, count_byte[2]); 794 #endif /* COUNT_24 */ 795 796 kpreempt_enable(); 797 return (DDI_SUCCESS); 798 } 799 800 801 /* 802 * routine: d37A_read_count() 803 * purpose: read the 16- or 24-bit count from the Current Count Register for 804 * the indicated channel 805 * caller: d37A_get_chan_stat() 806 * calls: d37A macros 807 */ 808 809 static long 810 d37A_read_count(int chnl) 811 { 812 long count = 0; 813 uchar_t *count_byte; 814 815 kpreempt_disable(); /* don't preempt thread while using flip-flop */ 816 count_byte = (uchar_t *)&count; 817 outb(chan_addr[chnl].ff_reg, 0); /* set flipflop */ 818 819 count_byte[0] = inb(chan_addr[chnl].cnt_reg); 820 count_byte[1] = inb(chan_addr[chnl].cnt_reg); 821 #ifdef COUNT_24 822 count_byte[2] = inb(chan_addr[chnl].hcnt_reg); 823 #endif /* COUNT_24 */ 824 825 #ifdef COUNT_24 826 if ((ulong_t)count == 0xffffff) 827 #else /* !COUNT_24 */ 828 if ((ulong_t)count == 0xffff) 829 #endif /* !COUNT_24 */ 830 count = -1; 831 832 kpreempt_enable(); 833 834 switch (d37A_chnl_path[chnl]) { 835 case DMAE_PATH_8: 836 case DMAE_PATH_16B: 837 case DMAE_PATH_32: 838 ++count; 839 break; 840 841 case DMAE_PATH_16: 842 /* 843 * Convert incremented word count to byte count 844 */ 845 count = (count + 1) << 1; 846 break; 847 } 848 dprintf(("d37A_read_count: chnl=%d count=0x%lx\n", chnl, count)); 849 return (count); 850 } 851