⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dosdma.c

📁 wince下著名的视频播放器源码
💻 C
字号:
/*    Implementation of DMA routines on DOS    Copyright (C) 1999 by Andrew Zabolotny, <bit@eltech.ru>    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Library General Public License for more details.    You should have received a copy of the GNU Library General Public    License along with this library; if not, write to the Free    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "dosdma.h"#include <dos.h>#include <dpmi.h>#include <sys/nearptr.h>#include <malloc.h>__dma_regs dma[8] = {/* *INDENT-OFF* */	{DMA_ADDR_0, DMA_PAGE_0, DMA_SIZE_0,	 DMA1_MASK_REG, DMA1_CLEAR_FF_REG, DMA1_MODE_REG},	{DMA_ADDR_1, DMA_PAGE_1, DMA_SIZE_1,	 DMA1_MASK_REG, DMA1_CLEAR_FF_REG, DMA1_MODE_REG},	{DMA_ADDR_2, DMA_PAGE_2, DMA_SIZE_2,	 DMA1_MASK_REG, DMA1_CLEAR_FF_REG, DMA1_MODE_REG},	{DMA_ADDR_3, DMA_PAGE_3, DMA_SIZE_3,	 DMA1_MASK_REG, DMA1_CLEAR_FF_REG, DMA1_MODE_REG},	{DMA_ADDR_4,          0, DMA_SIZE_4,	 DMA2_MASK_REG, DMA2_CLEAR_FF_REG, DMA2_MODE_REG},	{DMA_ADDR_5, DMA_PAGE_5, DMA_SIZE_5,	 DMA2_MASK_REG, DMA2_CLEAR_FF_REG, DMA2_MODE_REG},	{DMA_ADDR_6, DMA_PAGE_6, DMA_SIZE_6,	 DMA2_MASK_REG, DMA2_CLEAR_FF_REG, DMA2_MODE_REG},	{DMA_ADDR_7, DMA_PAGE_7, DMA_SIZE_7,	 DMA2_MASK_REG, DMA2_CLEAR_FF_REG, DMA2_MODE_REG}/* *INDENT-ON* */};static int __initialized = 0;static int __buffer_count = 0;static __dpmi_meminfo __locked_data;int dma_initialize(){	if (!__djgpp_nearptr_enable())		return 0;	/* Trick: Avoid re-setting DS selector limit on each memory allocation	   call */	__djgpp_selector_limit = 0xffffffff;	__locked_data.address = __djgpp_base_address + (unsigned long)&dma;	__locked_data.size = sizeof(dma);	if (__dpmi_lock_linear_region(&__locked_data))		return 0;	return (__initialized = 1);}void dma_finalize(){	if (!__initialized)		return;	__dpmi_unlock_linear_region(&__locked_data);	__djgpp_nearptr_disable();}dma_buffer *dma_allocate(unsigned int channel, unsigned int size){	int parsize = (size + 15) >> 4;	/* size in paragraphs */	int par = 0;				/* Real-mode paragraph */	int selector = 0;			/* Protected-mode selector */	int mask = channel <= 3 ? 0xfff : 0x1fff;	/* Alignment mask in para. */	int allocsize = parsize;	/* Allocated size in paragraphs */	int count;					/* Try count */	int bound = 0;				/* Nearest bound address */	int maxsize;				/* Maximal possible block size */	dma_buffer *buffer = NULL;	__dpmi_meminfo buff_info, struct_info;	if (!dma_initialize())		return NULL;	/* Loop until we'll get a properly aligned memory block */	for (count = 8; count; count--) {		int resize = (selector != 0);		/* Try first to resize (possibly previously) allocated block */		if (resize) {			maxsize = (bound + parsize) - par;			if (maxsize > parsize * 2)				maxsize = parsize * 2;			if (maxsize == allocsize)				resize = 0;			else {				allocsize = maxsize;				/* BUG WARNING: there is an error in dpmi.h DJGPP 2.01 library:				   the order of "selector" and "alloc size" should be				   reversed */				if (__dpmi_resize_dos_memory(allocsize, selector, &maxsize) !=					0) resize = 0;			}		}		if (!resize) {			if (selector)				__dpmi_free_dos_memory(selector), selector = 0;			par = __dpmi_allocate_dos_memory(allocsize, &selector);		}		if ((par == 0) || (par == -1))			goto exit;		/* If memory block contains a properly aligned portion, quit loop */		bound = (par + mask + 1) & ~mask;		if (par + parsize <= bound)			break;		if (bound + parsize <= par + allocsize) {			par = bound;			break;		}	}	if (!count) {		__dpmi_free_dos_memory(selector);		goto exit;	}	buffer = malloc(sizeof(dma_buffer));	buffer->linear = (void *)(__djgpp_conventional_base + bound * 16);	buffer->physical = bound * 16;	buffer->size = parsize * 16;	buffer->selector = selector;	buffer->channel = channel;	buff_info.address = buffer->physical;	buff_info.size = buffer->size;	/*	   Don't pay attention to return code since under plain DOS it often	   returns error (at least under HIMEM/CWSDPMI and EMM386/DPMI)	 */	__dpmi_lock_linear_region(&buff_info);	/* Lock the DMA buffer control structure as well */	struct_info.address = __djgpp_base_address + (unsigned long)buffer;	struct_info.size = sizeof(dma_buffer);	if (__dpmi_lock_linear_region(&struct_info)) {		__dpmi_unlock_linear_region(&buff_info);		__dpmi_free_dos_memory(selector);		free(buffer);		buffer = NULL;		goto exit;	}  exit:	if (buffer)		__buffer_count++;	else if (--__buffer_count == 0)		dma_finalize();	return buffer;}void dma_free(dma_buffer * buffer){	__dpmi_meminfo buff_info;	if (!buffer)		return;	buff_info.address = buffer->physical;	buff_info.size = buffer->size;	__dpmi_unlock_linear_region(&buff_info);	__dpmi_free_dos_memory(buffer->selector);	free(buffer);	if (--__buffer_count == 0)		dma_finalize();}void dma_start(dma_buffer * buffer, unsigned long count, unsigned char mode){	/* Disable interrupts */	int old_ints = disable();	dma_disable(buffer->channel);	dma_set_mode(buffer->channel, mode);	dma_clear_ff(buffer->channel);	dma_set_addr(buffer->channel, buffer->physical);	dma_clear_ff(buffer->channel);	dma_set_count(buffer->channel, count);	dma_enable(buffer->channel);	/* Re-enable interrupts */	if (old_ints)		enable();}/* ex:set ts=4: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -