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
, 0, &iblk_cookie
,
134 (ddi_idevice_cookie_t
*)0, d37A_intr
, 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;
562 switch (dmaereqp
->der_command
) {
564 mode
|= DMAMODE_READ
;
567 mode
|= DMAMODE_WRITE
;
570 mode
|= DMAMODE_VERF
;
573 mode
|= 0x0C; /* for Adaptec 1st party DMA on chnl 0 */
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
;
589 case DMAE_TRANS_BLCK
:
590 mode
|= DMAMODE_BLOCK
;
592 case DMAE_TRANS_DMND
:
594 case DMAE_TRANS_CSCD
:
595 mode
|= DMAMODE_CASC
;
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 */
609 d37A_chnl_path
[chnl
] = dmaereqp
->der_path
;
611 switch (dmaereqp
->der_path
) {
613 /* emode |= EISA_DMA_8; */
616 emode
|= EISA_DMA_16
;
619 emode
|= EISA_DMA_32
;
622 emode
|= EISA_DMA_16B
;
630 d37A_chnl_path
[chnl
] = DMAE_PATH_8
;
631 /* emode |= EISA_DMA_8; */
636 d37A_chnl_path
[chnl
] = DMAE_PATH_16
;
637 emode
|= EISA_DMA_16
;
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().
660 d37A_write_addr(ulong_t paddress
, int chnl
)
664 dprintf(("d37A_write_addr: chnl=%d address=%lx\n", chnl
, paddress
));
666 switch (d37A_chnl_path
[chnl
]) {
671 * program DMA controller with byte address
677 * convert byte address to shifted word address
679 paddress
= (paddress
& ~0x1ffff) | ((paddress
& 0x1ffff) >> 1);
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]);
693 outb(chan_addr
[chnl
].hpage_reg
, adr_byte
[3]);
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().
710 d37A_read_addr(int chnl
)
712 ulong_t paddress
= 0;
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
);
723 adr_byte
[3] = inb(chan_addr
[chnl
].hpage_reg
);
728 switch (d37A_chnl_path
[chnl
]) {
733 * return with byte address
739 * convert shifted word address to byte address
741 paddress
= (paddress
& ~0x1ffff) | ((paddress
& 0x0ffff) << 1);
745 return ((ulong_t
)DDI_FAILURE
);
748 dprintf(("d37A_read_addr: chnl=%d address=%lx.\n", chnl
, 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()
762 d37A_write_count(long count
, int chnl
)
766 dprintf(("d37A_write_count: chnl=%d count=0x%lx\n", chnl
, count
));
768 switch (d37A_chnl_path
[chnl
]) {
771 * Convert byte count to word count
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]);
792 outb(chan_addr
[chnl
].hcnt_reg
, count_byte
[2]);
793 #endif /* COUNT_24 */
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()
809 d37A_read_count(int chnl
)
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
);
821 count_byte
[2] = inb(chan_addr
[chnl
].hcnt_reg
);
822 #endif /* COUNT_24 */
825 if ((ulong_t
)count
== 0xffffff)
826 #else /* !COUNT_24 */
827 if ((ulong_t
)count
== 0xffff)
828 #endif /* !COUNT_24 */
833 switch (d37A_chnl_path
[chnl
]) {
842 * Convert incremented word count to byte count
844 count
= (count
+ 1) << 1;
847 dprintf(("d37A_read_count: chnl=%d count=0x%lx\n", chnl
, count
));