Problem with DDI/DDK DMA for UNIX SVR4
Simon Hung
shung at riipsdev.Waterloo.NCR.Com
Fri Jun 7 06:19:30 AEST 1991
I have been trying to use the DMA functions found in the DDI/DKI of UNIX
System V Release 4. So far, I have been unsuccessful. Any help to
determine the origin of my problem would be greatly appreciated.
My objective is to write a SCSI device driver for a in-house designed SCSI
board and to use the DMA to transfer data between the SCSI hardware and
kernel memory. Please note, I have managed to program the DMA hardware
directly and made successful transfers, so the hardware is OK.
The following program illustrates how I use the DDI/DKI's dma functions :
/* -------------------------------------------------------------------------*/
#define CHANNEL_3 3 /* DMA channel no. */
#define BUFSIZE 50000 /* User buffer size */
char *user_buf;
struct dma_db db1, db2;
struct dma_cb cb;
/* Allocate user buffer */
user_buf = mem_alloc ( BUFSIZE, KM_SLEEP );
/* Allocate dma target and request buffer */
db1 = dma_get_buf ( DMA_SLEEP );
db2 = dma_get_buf ( DMA_SLEEP );
/* Allocate dma control block */
cb = dma_get_cb ( DMA_SLEEP );
/* Set up target and request buffer */
db1->address = kvtophys ( user_buf );
db1->count = message_length;
db2->address = 0x410; /* scsi DMA port address */
db2->count = message_length;
/* Set up dma control block */
cb->targbufs = db1;
cb->reqrbufs = db2;
cb->command = DMA_CMD_WRITE;
cb->targ_type = DMA_TYPE_MEM;
cb->reqr_type = DMA_TYPE_IO;
cb->targ_step = DMA_STEP_INC;
cb->reqr_step = DMA_STEP_HOLD;
cb->trans_type = DMA_TRANS_BLCK;
cb->targ_path = DMA_PATH_8;
cb->reqr_step = DMA_PATH_8;
cb->cycles = DMA_CYCLES_1;
cb->bufprocess = DMA_BUF_SNGL;
dma_disable ( CHANNEL_3 );
if ( dma_prog ( cb, CHANNEL_3, DMA_NOSLEEP)==0 )
{
dma_enable ( CHANNEL_3 );
/**********************************************************
When program reaches this point, the system is crash and
prints - Unexpected NMI in system mode.
***********************************************************/
/* ------------------------------------------------------------------------ */
I am using a MCA 386sx machine. Here is the way I program the DMA directly
using DMA extended function register :
#define FREG 0x18
#define EFREG 0x1a
paddr_t address;
int io_address;
/* Mask off channel 3 */
outb ( FREG, 0x93 );
/* Select mode register */
outb ( FREG, 0x73 );
/* Write mode register :
- Write memory transfer
- Data Transfer Operation
- Use programmed I/O address
*/
outb ( EFREG, 0xd );
/* Select memory address register */
outb ( FREG, 0x23 );
/* Set up target address */
address = kvtophys ( user_buf );
outb ( EFREG, address );
outb ( EFREG, address>>8 );
outb ( EFREG, address>>16 );
/* Select I/O address register */
outb ( FREG, 0x43 );
/* Set up I/O address */
io_address = 0x410;
outb ( EFREG, io_address );
outb ( EFREG, io_addess>>8 );
/* Select Transfer Count register */
outb ( FREG, 0x43 );
/* Set up Transfer Count */
outb ( EFREG, message_length );
outb ( EFREG, message_length>>8 );
/* Unmask channel 3 */
outb ( FREG, 0xa3 );
/* --------------------------------------------------------------------------*/
Your advice is appreciated and I'm looking forward to hearing from someone.
Regards,
Simon Hung
More information about the Comp.unix.questions
mailing list