📄 isadma.c
字号:
/* isaDma.c - DMA Controller Device (I8237) Utilities/Support Module *//* Copyright 1984-2001 Wind River Systems, Inc. *//* Copyright 1996,1997,1998 Motorola, Inc., All Rights Reserved *//*modification history--------------------01d,16sep01,dat Use of WRS_ASM macro01c,15apr99,srr Changed to WRS address space naming convention.01b,15apr98,dat added INCLUDE_ISADMA01a,12dec97,rbb created by Motorola.*//*DESCRIPTIONThis module contains routines that support ISA DMA transfers. The routinesprovided will initialize the DMA configuration, start and stop DMA transfersand return the status of an ISA DMA transfer.This module is normally included as a source module. The macro INCLUDE_ISADMAmust be defined if any code is to be compiled.Notes:1. These routines assume that a dual i8237 DMA controller device is present (e.g., I82378ZB, W83C553F).*//* includes */#include "vxWorks.h"#include "i8237.h"#include "config.h"#ifdef INCLUDE_ISADMA /* do nothing if not defined *//* defines */#ifndef EIEIO_SYNC# define EIEIO_SYNC _WRS_ASM (" eieio; sync")#endif /* EIEIO_SYNC */#define I8237_BASE_ADDRESS ISA_MSTR_IO_LOCAL#define PCIV_PCIMPU_RAM_OFFSET PCI_SLV_MEM_BUS/* typedefs *//* globals *//* forward declarations */extern void isaDmaInit(); /* initialize DMA (global configuration) */extern void isaDmaStart(); /* initialize DMA channel for transfer */extern void isaDmaStop(); /* disable DMA channel */extern UINT isaDmaStatus(); /* query DMA channel for transfer status *//* externals *//********************************************************************************* isaDmaInit - DMA controller initialization** This function's purpose is to initialize the dual DMA controller* device to a sane state. This initialization is from a global* configuration standpoint, and needs only to be performed once.** RETURNS: N/A*/void isaDmaInit (void) { register UINT channel; register UINT rvalue1, rvalue2; register I8237_DMA1 *pDma1; register I8237_DMA2 *pDma2; /* setup pointers to the DMA controller devices */ pDma1 = (I8237_DMA1 *)(I8237_BASE_ADDRESS + I8237_DMA1_OFFSET); pDma2 = (I8237_DMA2 *)(I8237_BASE_ADDRESS + I8237_DMA2_OFFSET); /* perform a H/W reset of the devices */ pDma1->mc = 0x00; EIEIO_SYNC; pDma2->mc = 0x00; EIEIO_SYNC; /* initialize all channels to a sane state */ for (channel = 0; channel < 4; channel++) { /* * dependent upon the channel, setup the specifics: * * demand * address-increment * autoinitialize-disable * read-transfer */ switch (channel) { case 0: rvalue1 = (I8237_MODE_TM_DEMAND|I8237_MODE_CH0SEL|I8237_MODE_TT_READ); rvalue2 = (I8237_MODE_TM_CASCADE|I8237_MODE_CH0SEL); break; case 1: rvalue1 = (I8237_MODE_TM_DEMAND|I8237_MODE_CH1SEL|I8237_MODE_TT_READ); rvalue2 = (I8237_MODE_TM_DEMAND|I8237_MODE_CH1SEL|I8237_MODE_TT_READ); break; case 2: rvalue1 = (I8237_MODE_TM_DEMAND|I8237_MODE_CH2SEL|I8237_MODE_TT_READ); rvalue2 = (I8237_MODE_TM_DEMAND|I8237_MODE_CH2SEL|I8237_MODE_TT_READ); break; case 3: rvalue1 = (I8237_MODE_TM_DEMAND|I8237_MODE_CH2SEL|I8237_MODE_TT_READ); rvalue2 = (I8237_MODE_TM_DEMAND|I8237_MODE_CH2SEL|I8237_MODE_TT_READ); break; default: rvalue1 = 0x00; rvalue2 = 0x00; break; } /* write to write mode registers */ pDma1->wm = rvalue1; EIEIO_SYNC; pDma2->wm = rvalue2; EIEIO_SYNC; } /* enable all channels */ pDma1->cm = 0x00; EIEIO_SYNC; pDma2->cm = 0x00; EIEIO_SYNC; /* * initialize the global DMA configuration * * DACK# active low * DREQ active high * fixed priority * channel group enable */ pDma1->cs = 0x00; EIEIO_SYNC; pDma2->cs = 0x00; EIEIO_SYNC; }/********************************************************************************* isaDmaStart - start DMA transfer** This function's purpose is to initialize the specified DMA* channel for a DMA transfer.** RETURNS: N/A*/void isaDmaStart ( register UINT dmaChannelNumber, /* DMA channel number (0 - 7) */ register UINT dmaTransferMode, /* DMA transfer mode */ register UINT dmaTransferType, /* DMA transfer type */ register UINT address, /* address */ register UINT nBytes /* number of bytes */ ) { register UINT rvalue; register UINT channelNumber; register I8237_DMA1 *pDma1; register I8237_DMA2 *pDma2; register I8237_PAGE *pPage; register I8237_HIGHPAGE *pHigh; /* setup pointers to the DMA controller devices */ pDma1 = (I8237_DMA1 *)(I8237_BASE_ADDRESS + I8237_DMA1_OFFSET); pDma2 = (I8237_DMA2 *)(I8237_BASE_ADDRESS + I8237_DMA2_OFFSET); pPage = (I8237_PAGE *)(I8237_BASE_ADDRESS + I8237_PAGE_OFFSET); pHigh = (I8237_HIGHPAGE *)(I8237_BASE_ADDRESS + I8237_HIGH_OFFSET); /* * create DMA address (PCI/ISA to system memory) * create physical i8237 channel number * number of programmed bytes is less one than the transfer */ address |= PCIV_PCIMPU_RAM_OFFSET; channelNumber = dmaChannelNumber & 0x3; nBytes--; /* * disable channel for DMA transfer initialization * setup the address of the transfer */ if (dmaChannelNumber < 4) { /* disable the selected channel */ pDma1->wsmb = (I8237_WSMB_CHMASKSEL | channelNumber); EIEIO_SYNC; /* * initialize the address (A07-A00) of the transfer * initialize the address (A15-A08) of the transfer */ pDma1->cbp = 0x00; EIEIO_SYNC; pDma1->bac[channelNumber].bca = (UCHAR)(address >> 0); EIEIO_SYNC; pDma1->bac[channelNumber].bca = (UCHAR)(address >> 8); EIEIO_SYNC; /* initialize the count of the transfer */ pDma1->cbp = 0x00; EIEIO_SYNC; pDma1->bac[channelNumber].bcc = (UCHAR)(nBytes >> 0); EIEIO_SYNC; pDma1->bac[channelNumber].bcc = (UCHAR)(nBytes >> 8); EIEIO_SYNC; } else { /* disable the selected channel */ pDma2->wsmb = (I8237_WSMB_CHMASKSEL | channelNumber); EIEIO_SYNC; /* * initialize the address (A07-A00) of the transfer * initialize the address (A15-A08) of the transfer */ pDma2->cbp = 0x00; EIEIO_SYNC; pDma2->bac[channelNumber].bca = (UCHAR)(address >> 0); EIEIO_SYNC; pDma2->bac[channelNumber].bca = (UCHAR)(address >> 8); EIEIO_SYNC; /* initialize the count of the transfer */ pDma2->cbp = 0x00; EIEIO_SYNC; pDma2->bac[channelNumber].bcc = (UCHAR)(nBytes >> 0); EIEIO_SYNC; pDma2->bac[channelNumber].bcc = (UCHAR)(nBytes >> 8); EIEIO_SYNC; } /* * setup the address (A23-A16) of the transfer * setup the address (A31-A24) of the transfer */ switch (dmaChannelNumber) { case 0: pPage->p_ch0 = (UCHAR)(address >> 16); EIEIO_SYNC; pHigh->p_ch0 = (UCHAR)(address >> 24); EIEIO_SYNC; break; case 1: pPage->p_ch1 = (UCHAR)(address >> 16); EIEIO_SYNC; pHigh->p_ch1 = (UCHAR)(address >> 24); EIEIO_SYNC; break; case 2: pPage->p_ch2 = (UCHAR)(address >> 16); EIEIO_SYNC; pHigh->p_ch2 = (UCHAR)(address >> 24); EIEIO_SYNC; break; case 3: pPage->p_ch3 = (UCHAR)(address >> 16); EIEIO_SYNC; pHigh->p_ch3 = (UCHAR)(address >> 24); EIEIO_SYNC; break; case 5: pPage->p_ch5 = (UCHAR)(address >> 16); EIEIO_SYNC; pHigh->p_ch5 = (UCHAR)(address >> 24); EIEIO_SYNC; break; case 6: pPage->p_ch6 = (UCHAR)(address >> 16); EIEIO_SYNC; pHigh->p_ch6 = (UCHAR)(address >> 24); EIEIO_SYNC; break; case 7: pPage->p_ch7 = (UCHAR)(address >> 16); EIEIO_SYNC; pHigh->p_ch7 = (UCHAR)(address >> 24); EIEIO_SYNC; break; } /* initialize the transfer specifics (write mode register) */ switch (channelNumber) { case 0: rvalue = dmaTransferMode | dmaTransferType | I8237_MODE_CH0SEL; break; case 1: rvalue = dmaTransferMode | dmaTransferType | I8237_MODE_CH1SEL; break; case 2: rvalue = dmaTransferMode | dmaTransferType | I8237_MODE_CH2SEL; break; case 3: rvalue = dmaTransferMode | dmaTransferType | I8237_MODE_CH3SEL; break; default: rvalue = 0x00; break; } /* enable channel for DMA transfer */ if (dmaChannelNumber < 4) { pDma1->wm = rvalue; EIEIO_SYNC; pDma1->wsmb = channelNumber; EIEIO_SYNC; } else { pDma2->wm = rvalue; EIEIO_SYNC; pDma2->wsmb = channelNumber; EIEIO_SYNC; } }/********************************************************************************* isaDmaStop - Stop DMA transfer** This functions purpose is to disable (stop) the specified DMA* channel for a DMA transfer.** RETURNS: N/A*/void isaDmaStop ( register UINT dmaChannelNumber /* DMA channel number (0 - 7) */ ) { register UINT channelNumber; register I8237_DMA1 *pDma1; register I8237_DMA2 *pDma2; /* setup pointers to the DMA controller devices */ pDma1 = (I8237_DMA1 *)(I8237_BASE_ADDRESS + I8237_DMA1_OFFSET); pDma2 = (I8237_DMA2 *)(I8237_BASE_ADDRESS + I8237_DMA2_OFFSET); /* create physical i8237 channel number */ channelNumber = dmaChannelNumber & 0x3; /* disable channel */ if (dmaChannelNumber < 4) { pDma1->wsmb = (I8237_WSMB_CHMASKSEL | channelNumber); EIEIO_SYNC; } else { pDma2->wsmb = (I8237_WSMB_CHMASKSEL | channelNumber); EIEIO_SYNC; } }/********************************************************************************* isaDmaStatus - get DMA transfer status** This function's purpose is to query the specified DMA channel* for DMA transfer status. And to return this status in a* logical format (see values below).** RETURNS: DMA Transfer Status* 0: Request=0, TerminalCount=0* 1: Request=0, TerminalCount=1* 2: Request=1, TerminalCount=0* 3: Request=1, TerminalCount=1*/UINT isaDmaStatus ( register UINT dmaChannelNumber /* DMA channel number (0 - 7) */ ) { register UINT rvalue, svalue; register UINT channelNumber; register I8237_DMA1 *pDma1; register I8237_DMA2 *pDma2; /* setup pointers to the DMA controller devices */ pDma1 = (I8237_DMA1 *)(I8237_BASE_ADDRESS + I8237_DMA1_OFFSET); pDma2 = (I8237_DMA2 *)(I8237_BASE_ADDRESS + I8237_DMA2_OFFSET); /* create physical i8237 channel number */ channelNumber = dmaChannelNumber & 0x3; /* read DMA status register */ if (dmaChannelNumber < 4) { rvalue = pDma1->cs; EIEIO_SYNC; } else { rvalue = pDma2->cs; EIEIO_SYNC; } /* mask off unwanted channels' status */ rvalue &= ((0x10 << channelNumber) | (0x01 << channelNumber)); /* convert to logical status */ svalue = 0; if (rvalue & 0xF0) { svalue |= 0x2; } if (rvalue & 0x0F) { svalue |= 0x1; } return (svalue);}#endif /* INCLUDE_ISADMA */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -