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
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]
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)
58 #include <sys/types.h>
59 #include <sys/cpuvar.h>
61 #include <sys/sunddi.h>
62 #include <sys/cmn_err.h>
63 #include <sys/dma_engine.h>
64 #include <sys/dma_i8237A.h>
67 #include <sys/promif.h>
68 static int i8237debug
= 0;
69 #define dprintf(x) if (i8237debug) (void)prom_printf 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 */
88 DMAE_PATH_16
, /* last 3 DMA channels default to 16-bit xfers */
91 static ushort_t d37A_chnl_mode
[] = {
92 DMAE_TRANS_SNGL
, DMAE_TRANS_SNGL
, DMAE_TRANS_SNGL
, DMAE_TRANS_SNGL
,
95 #else /* !DMA_4CSCD */
97 #endif /* !DMA_4CSCD */
98 DMAE_TRANS_SNGL
, DMAE_TRANS_SNGL
, DMAE_TRANS_SNGL
};
100 static ddi_dma_cookie_t
*d37A_next_cookie
[] =
101 {0, 0, 0, 0, 0, 0, 0, 0};
102 #endif /* DMA_BUF_CHAIN */
106 static uint_t
d37A_intr(caddr_t
);
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);
115 static void dEISA_setchain(ddi_dma_cookie_t
*cp
, int chnl
);
119 * Routine: d37A_init()
120 * purpose: initializes the 8237A.
122 * calls: d37A macros, d37A_init()
127 d37A_init(dev_info_t
*dip
)
130 ddi_iblock_cookie_t iblk_cookie
= 0;
133 if ((error
= ddi_add_intr(dip
, (uint_t
)0, &iblk_cookie
,
134 (ddi_idevice_cookie_t
*)0, d37A_intr
, (caddr_t
)NULL
)) !=
136 if (error
!= DDI_INTR_NOTFOUND
)
137 cmn_err(CE_WARN
, "!d37A_init: cannot add dma intr\n");
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()
156 d37A_dma_valid(int chnl
)
161 #endif /* DMA_4CSCD */
166 * Routine: d37A_release()
167 * purpose: resets the 8237A mode.
168 * caller: i_dmae_free()
173 d37A_dma_release(int chnl
)
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()
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()
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().
227 d37A_get_best_mode(struct ddi_dmae_req
*dmaereqp
)
229 return (DMAE_CYCLES_2
);
234 * routine: d37A_intr()
235 * purpose: stub routine
241 d37A_intr(caddr_t arg
)
243 int chnl
, istate
, nstate
;
246 if ((istate
= (inb(EISA_DMAIS
) & 0xef)) != 0) {
247 /* channel 4 can't interrupt */
250 mutex_enter(&dma_engine_lock
);
253 dEISA_setchain(d37A_next_cookie
[chnl
], chnl
);
256 mask
= inb(DMAC1_ALLMASK
) >> (chnl
);
258 mask
= inb(DMAC2_ALLMASK
) >> (chnl
- 4);
260 prom_printf("eisa: dma buffer chaining failure chnl %d!\n", chnl
);
269 if ((nstate
& 1) && d37A_next_cookie
[chnl
])
270 d37A_next_cookie
[chnl
] = _dmae_nxcookie(chnl
);
274 mutex_exit(&dma_engine_lock
);
275 return (DDI_INTR_CLAIMED
);
277 return (DDI_INTR_UNCLAIMED
);
279 #endif /* DMA_INTR */
284 * routine: dEISA_setchain()
285 * purpose: Set next buffer address/count from chain
286 * caller: d37A_intr()
290 dEISA_setchain(ddi_dma_cookie_t
*cp
, int chnl
)
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
);
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",
323 return (DDI_FAILURE
);
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
));
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 */
352 #endif /* !DMA_4CSCD */
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 */
366 dprintf(("d37A_prog_chan err: chnl %d not programmed.\n", chnl
));
367 return (DDI_FAILURE
);
371 mutex_enter(&dma_engine_lock
);
373 d37A_dma_disable(chnl
);
375 (void) d37A_set_mode(dmaereqp
, chnl
);
378 (void) d37A_write_addr(cp
->dmac_address
, chnl
);
379 (void) d37A_write_count(cp
->dmac_size
, chnl
);
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
389 outb(chan_addr
[chnl
].scm_reg
, chnl
| EISA_ENCM
);
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
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",
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
;
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 */
440 #endif /* !DMA_4CSCD */
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 */
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
);
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
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.
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
524 * caller: dma_get_chan_stat()
525 * calls: d37A_read_addr(), d37A_read_count().
528 d37A_get_chan_stat(int chnl
, ulong_t
*addressp
, int *countp
)
533 mutex_enter(&dma_engine_lock
);
534 taddr
= d37A_read_addr(chnl
);
535 tcount
= d37A_read_count(chnl
);
536 mutex_exit(&dma_engine_lock
);
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
555 d37A_set_mode(struct ddi_dmae_req
*dmaereqp
, int chnl
)
557 uchar_t mode
= 0, emode
= 0;
565 switch (dmaereqp
->der_command
) {
567 mode
|= DMAMODE_READ
;
570 mode
|= DMAMODE_WRITE
;
573 mode
|= DMAMODE_VERF
;
576 mode
|= 0x0C; /* for Adaptec 1st party DMA on chnl 0 */
579 return (DDI_FAILURE
);
582 if (dmaereqp
->der_bufprocess
== DMAE_BUF_AUTO
)
583 mode
|= DMAMODE_AUTO
;
585 if (dmaereqp
->der_step
== DMAE_STEP_DEC
)
586 mode
|= DMAMODE_DECR
;
588 switch (dmaereqp
->der_trans
) {
589 case DMAE_TRANS_SNGL
:
590 mode
|= DMAMODE_SINGLE
;
592 case DMAE_TRANS_BLCK
:
593 mode
|= DMAMODE_BLOCK
;
595 case DMAE_TRANS_DMND
:
597 case DMAE_TRANS_CSCD
:
598 mode
|= DMAMODE_CASC
;
601 return (DDI_FAILURE
);
603 d37A_chnl_mode
[chnl
] = dmaereqp
->der_trans
;
605 dprintf(("d37A_set_mode: chnl=%d mode_reg=0x%x mode=0x%x\n",
606 chnl
, chan_addr
[chnl
].mode_reg
, mode
));
607 outb(chan_addr
[chnl
].mode_reg
, mode
);
608 #endif /* ISA_MODE */
612 d37A_chnl_path
[chnl
] = dmaereqp
->der_path
;
614 switch (dmaereqp
->der_path
) {
616 /* emode |= EISA_DMA_8; */
619 emode
|= EISA_DMA_16
;
622 emode
|= EISA_DMA_32
;
625 emode
|= EISA_DMA_16B
;
633 d37A_chnl_path
[chnl
] = DMAE_PATH_8
;
634 /* emode |= EISA_DMA_8; */
639 d37A_chnl_path
[chnl
] = DMAE_PATH_16
;
640 emode
|= EISA_DMA_16
;
644 emode
|= (dmaereqp
->der_cycles
& 3) << 4;
645 outb(chan_addr
[chnl
].emode_reg
, emode
);
647 dprintf(("d37A_set_mode: chnl=%d em_reg=0x%x emode=0x%x\n",
648 chnl
, chan_addr
[chnl
].emode_reg
, emode
));
649 #endif /* EISA_EXT_MODE */
650 return (DDI_SUCCESS
);
655 * routine: d37A_write_addr()
656 * purpose: write the 24- or 32-bit physical address into the Base Address
657 * Register for the indicated channel.
658 * caller: d37A_prog_chan(), d37A_dma_swsetup().
663 d37A_write_addr(ulong_t paddress
, int chnl
)
667 dprintf(("d37A_write_addr: chnl=%d address=%lx\n", chnl
, paddress
));
669 switch (d37A_chnl_path
[chnl
]) {
674 * program DMA controller with byte address
680 * convert byte address to shifted word address
682 paddress
= (paddress
& ~0x1ffff) | ((paddress
& 0x1ffff) >> 1);
686 return (DDI_FAILURE
);
688 kpreempt_disable(); /* don't preempt thread while using flip-flop */
689 outb(chan_addr
[chnl
].ff_reg
, 0); /* set flipflop */
691 adr_byte
= (uchar_t
*)&paddress
;
692 outb(chan_addr
[chnl
].addr_reg
, adr_byte
[0]);
693 outb(chan_addr
[chnl
].addr_reg
, adr_byte
[1]);
694 outb(chan_addr
[chnl
].page_reg
, adr_byte
[2]);
696 outb(chan_addr
[chnl
].hpage_reg
, adr_byte
[3]);
700 return (DDI_SUCCESS
);
705 * routine: d37A_read_addr()
706 * purpose: read the 24- or 32-bit physical address from the Current Address
707 * Register for the indicated channel.
708 * caller: d37A_get_chan_stat().
713 d37A_read_addr(int chnl
)
715 ulong_t paddress
= 0;
718 kpreempt_disable(); /* don't preempt thread while using flip-flop */
719 adr_byte
= (uchar_t
*)&paddress
;
720 outb(chan_addr
[chnl
].ff_reg
, 0); /* set flipflop */
722 adr_byte
[0] = inb(chan_addr
[chnl
].addr_reg
);
723 adr_byte
[1] = inb(chan_addr
[chnl
].addr_reg
);
724 adr_byte
[2] = inb(chan_addr
[chnl
].page_reg
);
726 adr_byte
[3] = inb(chan_addr
[chnl
].hpage_reg
);
731 switch (d37A_chnl_path
[chnl
]) {
736 * return with byte address
742 * convert shifted word address to byte address
744 paddress
= (paddress
& ~0x1ffff) | ((paddress
& 0x0ffff) << 1);
748 return ((ulong_t
)DDI_FAILURE
);
751 dprintf(("d37A_read_addr: chnl=%d address=%lx.\n", chnl
, paddress
));
757 * routine: d37A_write_count()
758 * purpose: write the 16- or 24-bit count into the Base Count Register for
759 * the indicated channel.
760 * caller: d37A_prog_chan(), d37A_dma_swsetup()
765 d37A_write_count(long count
, int chnl
)
769 dprintf(("d37A_write_count: chnl=%d count=0x%lx\n", chnl
, count
));
771 switch (d37A_chnl_path
[chnl
]) {
774 * Convert byte count to word count
785 return (DDI_FAILURE
);
788 kpreempt_disable(); /* don't preempt thread while using flip-flop */
789 outb(chan_addr
[chnl
].ff_reg
, 0); /* set flipflop */
791 count_byte
= (uchar_t
*)&count
;
792 outb(chan_addr
[chnl
].cnt_reg
, count_byte
[0]);
793 outb(chan_addr
[chnl
].cnt_reg
, count_byte
[1]);
795 outb(chan_addr
[chnl
].hcnt_reg
, count_byte
[2]);
796 #endif /* COUNT_24 */
799 return (DDI_SUCCESS
);
804 * routine: d37A_read_count()
805 * purpose: read the 16- or 24-bit count from the Current Count Register for
806 * the indicated channel
807 * caller: d37A_get_chan_stat()
812 d37A_read_count(int chnl
)
817 kpreempt_disable(); /* don't preempt thread while using flip-flop */
818 count_byte
= (uchar_t
*)&count
;
819 outb(chan_addr
[chnl
].ff_reg
, 0); /* set flipflop */
821 count_byte
[0] = inb(chan_addr
[chnl
].cnt_reg
);
822 count_byte
[1] = inb(chan_addr
[chnl
].cnt_reg
);
824 count_byte
[2] = inb(chan_addr
[chnl
].hcnt_reg
);
825 #endif /* COUNT_24 */
828 if ((ulong_t
)count
== 0xffffff)
829 #else /* !COUNT_24 */
830 if ((ulong_t
)count
== 0xffff)
831 #endif /* !COUNT_24 */
836 switch (d37A_chnl_path
[chnl
]) {
845 * Convert incremented word count to byte count
847 count
= (count
+ 1) << 1;
850 dprintf(("d37A_read_count: chnl=%d count=0x%lx\n", chnl
, count
));