remove unnecessary uint_t casts of 0
[unleashed.git] / usr / src / uts / common / io / i8237A.c
blobc7e53e00932dec1b7089fda1fca22e3adad2ea54
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
29 /* All Rights Reserved */
31 /* Copyright (c) 1988, 1989 Intel Corp. */
32 /* All Rights Reserved */
34 #pragma ident "%Z%%M% %I% %E% SMI"
37 * Set features for each architecture. List of features:
38 * ADDR_32: Address is 32 bits
39 * COUNT_24: Count is 24 bits
40 * DMA_4CSCD: DMA channel 4 is used for cascade of channels 0-3)
41 * DMA_INTR: DMA interrupt is available (always with DMA_BUF_CHAIN)
42 * DMA_BUF_CHAIN: DMA buffer chaining is available (always with DMA_INTR)
43 * MEM_TO_MEM: Memory to memory transfers available
44 * NO_PROG_WIDTH: Channel data width is NOT programmable
45 * SCATER_GATHER Scatter-gather DMA is available (code not implemented)
46 * ISA_MODE Standard ISA modes available
47 * EISA_EXT_MODE: EISA extension modes available
51 * Address is 24 bits (default) with no carry between lo word and hi byte
52 * Count is 16 bits (default)
54 #define DMA_4CSCD
55 #define NO_PROG_WIDTH
56 #define ISA_MODE
58 #include <sys/types.h>
59 #include <sys/cpuvar.h>
60 #include <sys/disp.h>
61 #include <sys/sunddi.h>
62 #include <sys/cmn_err.h>
63 #include <sys/dma_engine.h>
64 #include <sys/dma_i8237A.h>
66 #if defined(DEBUG)
67 #include <sys/promif.h>
68 static int i8237debug = 0;
69 #define dprintf(x) if (i8237debug) (void)prom_printf x
70 #else
71 #define dprintf(x)
72 #endif /* defined(DEBUG) */
75 extern int EISA_chaining;
78 * data structures for maintaining the DMACs
80 static kmutex_t dma_engine_lock;
81 static struct d37A_chan_reg_addr chan_addr[] = { D37A_BASE_REGS_VALUES };
82 static ushort_t d37A_chnl_path[] = {
83 DMAE_PATH_8, /* first 4 DMA channels default to 8-bit xfers */
84 DMAE_PATH_8,
85 DMAE_PATH_8,
86 DMAE_PATH_8,
88 DMAE_PATH_16, /* last 3 DMA channels default to 16-bit xfers */
89 DMAE_PATH_16,
90 DMAE_PATH_16};
91 static ushort_t d37A_chnl_mode[] = {
92 DMAE_TRANS_SNGL, DMAE_TRANS_SNGL, DMAE_TRANS_SNGL, DMAE_TRANS_SNGL,
93 #ifdef DMA_4CSCD
94 DMAE_TRANS_CSCD,
95 #else /* !DMA_4CSCD */
96 DMAE_TRANS_SNGL,
97 #endif /* !DMA_4CSCD */
98 DMAE_TRANS_SNGL, DMAE_TRANS_SNGL, DMAE_TRANS_SNGL};
99 #ifdef DMA_BUF_CHAIN
100 static ddi_dma_cookie_t *d37A_next_cookie[] =
101 {0, 0, 0, 0, 0, 0, 0, 0};
102 #endif /* DMA_BUF_CHAIN */
105 #ifdef DMA_INTR
106 static uint_t d37A_intr(caddr_t);
107 #endif
108 static int d37A_set_mode(struct ddi_dmae_req *, int);
109 static int d37A_write_addr(ulong_t, int);
110 static ulong_t d37A_read_addr(int);
111 static int d37A_write_count(long, int);
112 static long d37A_read_count(int);
114 #ifdef DMA_BUF_CHAIN
115 static void dEISA_setchain(ddi_dma_cookie_t *cp, int chnl);
116 #endif
119 * Routine: d37A_init()
120 * purpose: initializes the 8237A.
121 * caller: dma_init()
122 * calls: d37A macros, d37A_init()
125 /*ARGSUSED*/
127 d37A_init(dev_info_t *dip)
129 #ifdef DMA_INTR
130 ddi_iblock_cookie_t iblk_cookie = 0;
131 int error;
133 if ((error = ddi_add_intr(dip, 0, &iblk_cookie,
134 (ddi_idevice_cookie_t *)0, d37A_intr, NULL)) !=
135 DDI_SUCCESS) {
136 if (error != DDI_INTR_NOTFOUND)
137 cmn_err(CE_WARN, "!d37A_init: cannot add dma intr\n");
138 EISA_chaining = 0;
140 mutex_init(&dma_engine_lock, NULL, MUTEX_DRIVER, (void *)iblk_cookie);
141 #else /* !DMA_INTR */
142 mutex_init(&dma_engine_lock, NULL, MUTEX_DRIVER, NULL);
143 #endif /* !DMA_INTR */
145 return (DDI_SUCCESS);
149 * Routine: d37A_valid()
150 * purpose: validates the channel to be acquired.
151 * caller: i_dmae_acquire()
152 * calls:
156 d37A_dma_valid(int chnl)
158 #ifdef DMA_4CSCD
159 if (chnl == 4)
160 return (0);
161 #endif /* DMA_4CSCD */
162 return (1);
166 * Routine: d37A_release()
167 * purpose: resets the 8237A mode.
168 * caller: i_dmae_free()
169 * calls:
172 void
173 d37A_dma_release(int chnl)
175 #ifdef DMA_4CSCD
176 if (chnl == 4)
177 return;
178 #endif /* DMA_4CSCD */
179 d37A_chnl_mode[chnl] = DMAE_TRANS_SNGL;
183 * routine: d37A_dma_disable()
184 * purpose: Prevent the DMAC from responding to external hardware
185 * requests for DMA service on the given channel
186 * caller: dma_disable()
187 * calls: d37A macros
189 void
190 d37A_dma_disable(int chnl)
192 dprintf(("d37A_dma_disable: chnl=%d mask_reg=0x%x\n",
193 chnl, chan_addr[chnl].mask_reg));
195 outb(chan_addr[chnl].mask_reg, (chnl & 3) | DMA_SETMSK);
200 * routine: d37A_dma_enable()
201 * purpose: Enable to DMAC to respond to hardware requests for DMA
202 * service on the specified channel.
203 * caller: dma_enable()
204 * calls: d37A macros
207 void
208 d37A_dma_enable(int chnl)
210 dprintf(("d37A_dma_enable: chnl=%d mask_reg=0x%x val=0x%x\n",
211 chnl, chan_addr[chnl].mask_reg, chnl & 3));
213 /* mutex_enter(&dma_engine_lock); */
214 outb(chan_addr[chnl].mask_reg, chnl & 3);
215 /* mutex_exit(&dma_engine_lock); */
220 * routine: d37A_get_best_mode()
221 * purpose: stub routine - determine optimum transfer method
222 * caller: dma_get_best_mode().
223 * calls:
225 /* ARGSUSED */
226 uchar_t
227 d37A_get_best_mode(struct ddi_dmae_req *dmaereqp)
229 return (DMAE_CYCLES_2);
232 #ifdef DMA_INTR
234 * routine: d37A_intr()
235 * purpose: stub routine
236 * caller:
237 * calls: dma_intr().
239 /*ARGSUSED*/
240 static uint_t
241 d37A_intr(caddr_t arg)
243 int chnl, istate, nstate;
244 uint_t mask;
246 if ((istate = (inb(EISA_DMAIS) & 0xef)) != 0) {
247 /* channel 4 can't interrupt */
248 chnl = 0;
249 nstate = istate;
250 mutex_enter(&dma_engine_lock);
251 do {
252 if (istate & 1) {
253 dEISA_setchain(d37A_next_cookie[chnl], chnl);
254 #ifdef DEBUG
255 if (chnl < 4)
256 mask = inb(DMAC1_ALLMASK) >> (chnl);
257 else
258 mask = inb(DMAC2_ALLMASK) >> (chnl - 4);
259 if (mask & 1)
260 prom_printf("eisa: dma buffer chaining failure chnl %d!\n", chnl);
262 #endif /* DEBUG */
264 chnl++;
265 istate >>= 1;
266 } while (istate);
267 chnl = 0;
268 do {
269 if ((nstate & 1) && d37A_next_cookie[chnl])
270 d37A_next_cookie[chnl] = _dmae_nxcookie(chnl);
271 chnl++;
272 nstate >>= 1;
273 } while (nstate);
274 mutex_exit(&dma_engine_lock);
275 return (DDI_INTR_CLAIMED);
277 return (DDI_INTR_UNCLAIMED);
279 #endif /* DMA_INTR */
282 #ifdef DMA_BUF_CHAIN
284 * routine: dEISA_setchain()
285 * purpose: Set next buffer address/count from chain
286 * caller: d37A_intr()
287 * calls: d37A macros
289 static void
290 dEISA_setchain(ddi_dma_cookie_t *cp, int chnl)
292 if (cp) {
293 dprintf(("dEISA_setchain: chnl=%d next_addr=%x count=%lx\n",
294 chnl, cp->dmac_address, cp->dmac_size));
295 (void) d37A_write_addr(cp->dmac_address, chnl);
296 (void) d37A_write_count(cp->dmac_size, chnl);
297 outb(chan_addr[chnl].scm_reg, chnl | EISA_ENCM | EISA_CMOK);
298 } else {
300 * clear chain enable bit
302 outb(chan_addr[chnl].scm_reg, chnl);
303 dprintf(("dEISA_setchain: chnl=%d end\n", chnl));
306 #endif /* DMA_BUF_CHAIN */
310 * routine: d37A_prog_chan()
311 * purpose: program the Mode registers and the Base registers of a
312 * DMA channel for a subsequent hardware-initiated transfer.
313 * caller: dma_prog_chan()
314 * calls: d37A_write_addr(), d37A_write_count(), d37A macros.
318 d37A_prog_chan(struct ddi_dmae_req *dmaereqp, ddi_dma_cookie_t *cp, int chnl)
320 if (d37A_chnl_mode[chnl] == DMAE_TRANS_CSCD) {
321 dprintf(("d37A_prog_chan err: chnl=%d in cascade mode\n",
322 chnl));
323 return (DDI_FAILURE);
325 #ifndef MEM_TO_MEM
326 if (dmaereqp && dmaereqp->der_dest == DMAE_DEST_MEM) {
327 dprintf(("d37A_prog_chan err: memory to memory mode not supported.\n"));
328 return (DDI_FAILURE);
330 #endif /* !MEM_TO_MEM */
332 dprintf(("d37A_prog_chan: chnl=%d dmaereq=%p\n",
333 chnl, (void *)dmaereqp));
335 if (dmaereqp) {
336 switch (chnl) {
337 case DMAE_CH0:
338 case DMAE_CH1:
339 case DMAE_CH2:
340 case DMAE_CH3:
341 #ifdef NO_PROG_WIDTH
342 if (dmaereqp->der_path &&
343 dmaereqp->der_path != DMAE_PATH_8) {
344 dprintf(("d37A_prog_chan err: chnl %d not programmed.\n", chnl));
345 return (DDI_FAILURE);
347 #endif /* NO_PROG_WIDTH */
348 break;
350 #ifndef DMA_4CSCD
351 case DMAE_CH4:
352 #endif /* !DMA_4CSCD */
353 case DMAE_CH5:
354 case DMAE_CH6:
355 case DMAE_CH7:
356 #ifdef NO_PROG_WIDTH
357 if (dmaereqp->der_path &&
358 dmaereqp->der_path != DMAE_PATH_16) {
359 dprintf(("d37A_prog_chan err: chnl %d not programmed.\n", chnl));
360 return (DDI_FAILURE);
362 #endif /* NO_PROG_WIDTH */
363 break;
365 default:
366 dprintf(("d37A_prog_chan err: chnl %d not programmed.\n", chnl));
367 return (DDI_FAILURE);
369 } else
370 chnl &= 3;
371 mutex_enter(&dma_engine_lock);
373 d37A_dma_disable(chnl);
374 if (dmaereqp)
375 (void) d37A_set_mode(dmaereqp, chnl);
377 if (cp) {
378 (void) d37A_write_addr(cp->dmac_address, chnl);
379 (void) d37A_write_count(cp->dmac_size, chnl);
381 #ifdef DMA_BUF_CHAIN
382 if (dmaereqp && dmaereqp->der_bufprocess == DMAE_BUF_CHAIN &&
383 (d37A_next_cookie[chnl] = _dmae_nxcookie(chnl))) {
385 * i/o operation has more than 1 cookie
386 * so enable dma buffer chaining
388 drv_usecwait(10);
389 outb(chan_addr[chnl].scm_reg, chnl | EISA_ENCM);
390 drv_usecwait(15);
391 dEISA_setchain(d37A_next_cookie[chnl], chnl);
392 d37A_next_cookie[chnl] = _dmae_nxcookie(chnl);
394 #endif /* DMA_BUF_CHAIN */
396 mutex_exit(&dma_engine_lock);
397 return (DDI_SUCCESS);
402 * routine: d37A_dma_swsetup()
403 * purpose: program the Mode registers and the Base register for the
404 * specified channel.
405 * caller: dma_swsetup()
406 * calls: d37A_write_addr(), d37A_write_count(), d37A macros.
410 d37A_dma_swsetup(struct ddi_dmae_req *dmaereqp, ddi_dma_cookie_t *cp, int chnl)
412 if (d37A_chnl_mode[chnl] == DMAE_TRANS_CSCD) {
413 dprintf(("d37A_dma_swsetup err: chnl %d not programmed\n",
414 chnl));
415 return (DDI_FAILURE);
418 dprintf(("d37A_dma_swsetup: chnl=%d dmaereq=%p.\n",
419 chnl, (void *)dmaereqp));
421 /* MUST BE IN BLOCK MODE FOR SOFTWARE INITIATED REQUESTS */
422 if (dmaereqp->der_trans != DMAE_TRANS_BLCK)
423 dmaereqp->der_trans = DMAE_TRANS_BLCK;
425 switch (chnl) {
426 case DMAE_CH0:
427 case DMAE_CH1:
428 case DMAE_CH2:
429 case DMAE_CH3:
430 #ifdef NO_PROG_WIDTH
431 if (dmaereqp->der_path && dmaereqp->der_path != DMAE_PATH_8) {
432 dprintf(("d37A_dma_swsetup err: chnl %d not programmed.\n", chnl));
433 return (DDI_FAILURE);
435 #endif /* NO_PROG_WIDTH */
436 break;
438 #ifndef DMA_4CSCD
439 case DMAE_CH4:
440 #endif /* !DMA_4CSCD */
441 case DMAE_CH5:
442 case DMAE_CH6:
443 case DMAE_CH7:
444 #ifdef NO_PROG_WIDTH
445 if (dmaereqp->der_path && dmaereqp->der_path != DMAE_PATH_16) {
446 dprintf(("d37A_dma_swsetup err: chnl %d not programmed.\n", chnl));
447 return (DDI_FAILURE);
449 #endif /* NO_PROG_WIDTH */
450 break;
452 default:
453 dprintf(("d37A_dma_swsetup err: chnl %d not set up.\n", chnl));
454 return (DDI_FAILURE);
457 mutex_enter(&dma_engine_lock);
459 d37A_dma_disable(chnl);
460 (void) d37A_set_mode(dmaereqp, chnl);
462 (void) d37A_write_addr(cp->dmac_address, chnl);
463 (void) d37A_write_count(cp->dmac_size, chnl);
465 #ifdef DMA_BUF_CHAIN
466 if (dmaereqp->der_bufprocess == DMAE_BUF_CHAIN &&
467 (d37A_next_cookie[chnl] = _dmae_nxcookie(chnl))) {
469 * i/o operation has more than 1 cookie
470 * so enable dma buffer chaining
472 outb(chan_addr[chnl].scm_reg, chnl | EISA_ENCM);
473 dEISA_setchain(d37A_next_cookie[chnl], chnl);
474 d37A_next_cookie[chnl] = _dmae_nxcookie(chnl);
476 #endif /* DMA_BUF_CHAIN */
477 mutex_exit(&dma_engine_lock);
478 return (DDI_SUCCESS);
483 * routine: d37A_dma_swstart()
484 * purpose: SW start transfer setup on the indicated channel.
485 * caller: dma_swstart()
486 * calls: d37A_dma_enable(), d37A macros
489 void
490 d37A_dma_swstart(int chnl)
492 dprintf(("d37A_dma_swstart: chnl=%d\n", chnl));
494 mutex_enter(&dma_engine_lock);
495 d37A_dma_enable(chnl);
496 outb(chan_addr[chnl].reqt_reg, DMA_SETMSK | chnl); /* set request bit */
497 mutex_exit(&dma_engine_lock);
502 * routine: d37A_dma_stop()
503 * purpose: Stop any activity on the indicated channel.
504 * caller: dma_stop()
505 * calls: d37A macros
508 void
509 d37A_dma_stop(int chnl)
511 dprintf(("d37A_dma_stop: chnl=%d\n", chnl));
513 mutex_enter(&dma_engine_lock);
514 d37A_dma_disable(chnl);
515 outb(chan_addr[chnl].reqt_reg, chnl & 3); /* reset request bit */
516 mutex_exit(&dma_engine_lock);
521 * routine: d37A_get_chan_stat()
522 * purpose: retrieve the Current Address and Count registers for the
523 * specified channel.
524 * caller: dma_get_chan_stat()
525 * calls: d37A_read_addr(), d37A_read_count().
527 void
528 d37A_get_chan_stat(int chnl, ulong_t *addressp, int *countp)
530 ulong_t taddr;
531 int tcount;
533 mutex_enter(&dma_engine_lock);
534 taddr = d37A_read_addr(chnl);
535 tcount = d37A_read_count(chnl);
536 mutex_exit(&dma_engine_lock);
537 if (addressp)
538 *addressp = taddr;
539 if (countp)
540 *countp = tcount;
541 dprintf(("d37A_get_chan_stat: chnl=%d address=%lx count=%x\n",
542 chnl, taddr, tcount));
547 * routine: d37A_set_mode()
548 * purpose: program the Mode registers of the
549 * DMAC for a subsequent hardware-initiated transfer.
550 * caller: d37A_prog_chan(), d37A_dma_swsetup
551 * calls:
554 static int
555 d37A_set_mode(struct ddi_dmae_req *dmaereqp, int chnl)
557 uchar_t mode = 0, emode = 0;
559 #ifdef ISA_MODE
560 mode = chnl & 3;
562 switch (dmaereqp->der_command) {
563 case DMAE_CMD_READ:
564 mode |= DMAMODE_READ;
565 break;
566 case DMAE_CMD_WRITE:
567 mode |= DMAMODE_WRITE;
568 break;
569 case DMAE_CMD_VRFY:
570 mode |= DMAMODE_VERF;
571 break;
572 case DMAE_CMD_TRAN:
573 mode |= 0x0C; /* for Adaptec 1st party DMA on chnl 0 */
574 break;
575 default:
576 return (DDI_FAILURE);
579 if (dmaereqp->der_bufprocess == DMAE_BUF_AUTO)
580 mode |= DMAMODE_AUTO;
582 if (dmaereqp->der_step == DMAE_STEP_DEC)
583 mode |= DMAMODE_DECR;
585 switch (dmaereqp->der_trans) {
586 case DMAE_TRANS_SNGL:
587 mode |= DMAMODE_SINGLE;
588 break;
589 case DMAE_TRANS_BLCK:
590 mode |= DMAMODE_BLOCK;
591 break;
592 case DMAE_TRANS_DMND:
593 break;
594 case DMAE_TRANS_CSCD:
595 mode |= DMAMODE_CASC;
596 break;
597 default:
598 return (DDI_FAILURE);
600 d37A_chnl_mode[chnl] = dmaereqp->der_trans;
602 dprintf(("d37A_set_mode: chnl=%d mode_reg=0x%x mode=0x%x\n",
603 chnl, chan_addr[chnl].mode_reg, mode));
604 outb(chan_addr[chnl].mode_reg, mode);
605 #endif /* ISA_MODE */
607 #ifdef EISA_EXT_MODE
608 emode = chnl & 3;
609 d37A_chnl_path[chnl] = dmaereqp->der_path;
611 switch (dmaereqp->der_path) {
612 case DMAE_PATH_8:
613 /* emode |= EISA_DMA_8; */
614 break;
615 case DMAE_PATH_16:
616 emode |= EISA_DMA_16;
617 break;
618 case DMAE_PATH_32:
619 emode |= EISA_DMA_32;
620 break;
621 case DMAE_PATH_16B:
622 emode |= EISA_DMA_16B;
623 break;
624 default:
625 switch (chnl) {
626 case DMAE_CH0:
627 case DMAE_CH1:
628 case DMAE_CH2:
629 case DMAE_CH3:
630 d37A_chnl_path[chnl] = DMAE_PATH_8;
631 /* emode |= EISA_DMA_8; */
632 break;
633 case DMAE_CH5:
634 case DMAE_CH6:
635 case DMAE_CH7:
636 d37A_chnl_path[chnl] = DMAE_PATH_16;
637 emode |= EISA_DMA_16;
638 break;
641 emode |= (dmaereqp->der_cycles & 3) << 4;
642 outb(chan_addr[chnl].emode_reg, emode);
644 dprintf(("d37A_set_mode: chnl=%d em_reg=0x%x emode=0x%x\n",
645 chnl, chan_addr[chnl].emode_reg, emode));
646 #endif /* EISA_EXT_MODE */
647 return (DDI_SUCCESS);
652 * routine: d37A_write_addr()
653 * purpose: write the 24- or 32-bit physical address into the Base Address
654 * Register for the indicated channel.
655 * caller: d37A_prog_chan(), d37A_dma_swsetup().
656 * calls: d37A macros
659 static int
660 d37A_write_addr(ulong_t paddress, int chnl)
662 uchar_t *adr_byte;
664 dprintf(("d37A_write_addr: chnl=%d address=%lx\n", chnl, paddress));
666 switch (d37A_chnl_path[chnl]) {
667 case DMAE_PATH_8:
668 case DMAE_PATH_16B:
669 case DMAE_PATH_32:
671 * program DMA controller with byte address
673 break;
675 case DMAE_PATH_16:
677 * convert byte address to shifted word address
679 paddress = (paddress & ~0x1ffff) | ((paddress & 0x1ffff) >> 1);
680 break;
682 default:
683 return (DDI_FAILURE);
685 kpreempt_disable(); /* don't preempt thread while using flip-flop */
686 outb(chan_addr[chnl].ff_reg, 0); /* set flipflop */
688 adr_byte = (uchar_t *)&paddress;
689 outb(chan_addr[chnl].addr_reg, adr_byte[0]);
690 outb(chan_addr[chnl].addr_reg, adr_byte[1]);
691 outb(chan_addr[chnl].page_reg, adr_byte[2]);
692 #ifdef ADDR_32
693 outb(chan_addr[chnl].hpage_reg, adr_byte[3]);
694 #endif /* ADDR_32 */
696 kpreempt_enable();
697 return (DDI_SUCCESS);
702 * routine: d37A_read_addr()
703 * purpose: read the 24- or 32-bit physical address from the Current Address
704 * Register for the indicated channel.
705 * caller: d37A_get_chan_stat().
706 * calls: d37A macros
709 static ulong_t
710 d37A_read_addr(int chnl)
712 ulong_t paddress = 0;
713 uchar_t *adr_byte;
715 kpreempt_disable(); /* don't preempt thread while using flip-flop */
716 adr_byte = (uchar_t *)&paddress;
717 outb(chan_addr[chnl].ff_reg, 0); /* set flipflop */
719 adr_byte[0] = inb(chan_addr[chnl].addr_reg);
720 adr_byte[1] = inb(chan_addr[chnl].addr_reg);
721 adr_byte[2] = inb(chan_addr[chnl].page_reg);
722 #ifdef ADDR_32
723 adr_byte[3] = inb(chan_addr[chnl].hpage_reg);
724 #endif /* ADDR_32 */
726 kpreempt_enable();
728 switch (d37A_chnl_path[chnl]) {
729 case DMAE_PATH_8:
730 case DMAE_PATH_16B:
731 case DMAE_PATH_32:
733 * return with byte address
735 break;
737 case DMAE_PATH_16:
739 * convert shifted word address to byte address
741 paddress = (paddress & ~0x1ffff) | ((paddress & 0x0ffff) << 1);
742 break;
744 default:
745 return ((ulong_t)DDI_FAILURE);
748 dprintf(("d37A_read_addr: chnl=%d address=%lx.\n", chnl, paddress));
749 return (paddress);
754 * routine: d37A_write_count()
755 * purpose: write the 16- or 24-bit count into the Base Count Register for
756 * the indicated channel.
757 * caller: d37A_prog_chan(), d37A_dma_swsetup()
758 * calls: d37A macros
761 static int
762 d37A_write_count(long count, int chnl)
764 uchar_t *count_byte;
766 dprintf(("d37A_write_count: chnl=%d count=0x%lx\n", chnl, count));
768 switch (d37A_chnl_path[chnl]) {
769 case DMAE_PATH_16:
771 * Convert byte count to word count
773 count >>= 1;
774 /* FALLTHROUGH */
775 case DMAE_PATH_8:
776 case DMAE_PATH_16B:
777 case DMAE_PATH_32:
778 --count;
779 break;
781 default:
782 return (DDI_FAILURE);
785 kpreempt_disable(); /* don't preempt thread while using flip-flop */
786 outb(chan_addr[chnl].ff_reg, 0); /* set flipflop */
788 count_byte = (uchar_t *)&count;
789 outb(chan_addr[chnl].cnt_reg, count_byte[0]);
790 outb(chan_addr[chnl].cnt_reg, count_byte[1]);
791 #ifdef COUNT_24
792 outb(chan_addr[chnl].hcnt_reg, count_byte[2]);
793 #endif /* COUNT_24 */
795 kpreempt_enable();
796 return (DDI_SUCCESS);
801 * routine: d37A_read_count()
802 * purpose: read the 16- or 24-bit count from the Current Count Register for
803 * the indicated channel
804 * caller: d37A_get_chan_stat()
805 * calls: d37A macros
808 static long
809 d37A_read_count(int chnl)
811 long count = 0;
812 uchar_t *count_byte;
814 kpreempt_disable(); /* don't preempt thread while using flip-flop */
815 count_byte = (uchar_t *)&count;
816 outb(chan_addr[chnl].ff_reg, 0); /* set flipflop */
818 count_byte[0] = inb(chan_addr[chnl].cnt_reg);
819 count_byte[1] = inb(chan_addr[chnl].cnt_reg);
820 #ifdef COUNT_24
821 count_byte[2] = inb(chan_addr[chnl].hcnt_reg);
822 #endif /* COUNT_24 */
824 #ifdef COUNT_24
825 if ((ulong_t)count == 0xffffff)
826 #else /* !COUNT_24 */
827 if ((ulong_t)count == 0xffff)
828 #endif /* !COUNT_24 */
829 count = -1;
831 kpreempt_enable();
833 switch (d37A_chnl_path[chnl]) {
834 case DMAE_PATH_8:
835 case DMAE_PATH_16B:
836 case DMAE_PATH_32:
837 ++count;
838 break;
840 case DMAE_PATH_16:
842 * Convert incremented word count to byte count
844 count = (count + 1) << 1;
845 break;
847 dprintf(("d37A_read_count: chnl=%d count=0x%lx\n", chnl, count));
848 return (count);