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

📄 low.c

📁 DOS_PCI_DRIVER,DOS环境下运行的PCI驱动程序,个人觉得比较好用.
💻 C
📖 第 1 页 / 共 4 页
字号:
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <STDARG.H>
#include <string.h>
#include <ctype.h>

#include "typedef.h"
#include "low.h"
#include "list.h"

#define SET_VECT 1

#ifdef DEBUG_HARDWARE_INTERRUPT
       #define FLUSH_IRQ 0x4c
#endif

extern unsigned long flags;
extern unsigned short flags_irq[];

extern unsigned char is_in_interrupt;

extern unsigned long GlobalTickCount;

extern unsigned char is_chain;

extern struct irq_table global_irq_table[];

extern struct list_head global_event_list;

extern struct eventmap event_map;

extern unsigned long event_next;

extern struct LDT moveld;

extern struct LDT far * p_moveld;

extern unsigned char mystack[];        
extern unsigned char busy;

extern void (_interrupt _far * old_int1c_handler)(void);
extern void (_interrupt _far * old_int8_handler)(void);

#pragma check_stack(off)

u8 inb(u16 port)
{
	_asm mov dx,port
	_asm in al,dx
}
	
u16 inw(u16 port)
{
	_asm mov dx,port
	_asm in ax,dx
}	

u32 inl(u16 port)
{
	_asm mov dx,port
	_asm in ax,dx
	_asm mov cx,ax
	_asm add dx,2
	_asm in ax,dx
	_asm mov bx,ax
	_asm mov dx,bx
	_asm mov ax,cx
}

void outb(u8 value,u16 port)
{
	_asm mov al,value
	_asm mov dx,port
	_asm out dx,al
}
	
void outw(u16 value,u16 port)
{
	_asm mov ax,value
	_asm mov dx,port
	_asm out dx,ax
}
	
void outl(u32 value,u16 port)
{
	_asm mov dx,port
	_asm mov ax,[bp + 6]
	_asm out dx,ax
	_asm add dx,2
	_asm mov ax,[bp + 8]
	_asm out dx,ax
}

#pragma check_stack(on)

unsigned long get_base_memory_size(void)
{
	unsigned short iAx;
	unsigned long size;

	_asm int BIOS_BASE_MEMORY_SIZE
	_asm mov iAx,ax

	size = iAx;

	return (size * 1024L);
}

unsigned long get_extend_memory_size(void)
{
	union REGS r;
	struct SREGS segs;
	unsigned long size;
	unsigned short temp;


	r.x.ax = FUNCTION_MEMORY_SIZE;

	_asm mov ax,es
	_asm mov temp,ax

	segs.es = temp;

	_asm mov ax,ds
	_asm mov temp,ax

	segs.ds = temp;

	int86x(BIOS_EXTEND_MEMORY,&r,&r,&segs);

	size = r.x.ax;
	
	return (size * 1024L);
}

#pragma check_stack(off)

void init_moveld(void)
{
	memset(moveld.a,0,64);
	moveld.src_attr = 0x92;
	moveld.dest_attr = 0x92;
	moveld.src_seg_limit_hi = 0xcf;
	moveld.dest_seg_limit_hi = 0xcf;
	moveld.src_size = 0xffff;
	moveld.dest_size = 0xffff;
}

long basemem_to_extmem(void far * p,unsigned long ext_base,unsigned short size_w)
{	
	unsigned long base_24;
	unsigned short moveld_seg;
	unsigned short moveld_off;
	union REGS r;
	struct SREGS segs;
	unsigned short temp;

	if(ext_base >= MAX_EXTEND_MEMORY_SIZE)
		return -EINVAL;

	init_moveld();

	base_24 = ptr_to_dma(p);
	moveld.src_base_0_15 = (base_24 & 0xffff);
	moveld.src_base_16_23 = ((base_24 >> 16) & 0xff);
	moveld.src_base_24_31 = 0;
	moveld.dest_base_0_15 = (ext_base & 0xffff);
	moveld.dest_base_16_23 = ((ext_base >> 16) & 0xff);
	moveld.dest_base_24_31 = (ext_base >> 24);
	
	moveld_seg = FP_SEG(p_moveld);
	moveld_off = FP_OFF(p_moveld);

	r.h.ah = FUNCTION_MOVE_MEMORY;
	r.h.al = 0;
	r.x.cx = size_w;
	segs.cs = moveld_seg;
	segs.es = moveld_seg;
	r.x.si = moveld_off;

	_asm pushf
	_asm pop temp

	temp &= 0x0200;
	if(!temp)
	{
	    _asm sti
	}

	int86x(BIOS_EXTEND_MEMORY,&r,&r,&segs);

	if(!temp)
	{
	    _asm cli
	}

	if(r.h.ah != 0)
		return -EINVAL;

	return 0;
}

long extmem_to_basemem(void far * p,unsigned long ext_base,unsigned short size_w)
{
	unsigned long base_24;
	unsigned short moveld_seg,moveld_off;
	union REGS r;
	struct SREGS segs;
	unsigned short temp;

	if(ext_base >= MAX_EXTEND_MEMORY_SIZE)
		return -EINVAL;

	init_moveld();

	base_24 = ptr_to_dma(p);
	moveld.src_base_0_15 = (ext_base & 0xffff);
	moveld.src_base_16_23 = ((ext_base >> 16) & 0xff);
	moveld.src_base_24_31 = (ext_base >> 24);
	moveld.dest_base_0_15 = (base_24 & 0xffff);
	moveld.dest_base_16_23 = (base_24 >> 16) & 0xff;
	moveld.dest_base_24_31 = 0;

	moveld_seg = FP_SEG(p_moveld);
	moveld_off = FP_OFF(p_moveld);

	r.h.ah = FUNCTION_MOVE_MEMORY;
	r.h.al = 0;
	r.x.cx = size_w;
	segs.cs = moveld_seg;
	segs.es = moveld_seg;
	r.x.si = moveld_off;

	_asm pushf
	_asm pop temp

	temp &= 0x0200;
	if(!temp)
	{
	    _asm sti
	}

	int86x(BIOS_EXTEND_MEMORY,&r,&r,&segs);

	if(!temp)
	{
	    _asm cli
	}

	if(r.h.ah != 0)
		return -EINVAL;

	return 0;
}

unsigned char readb(unsigned long abs_addr)
{
	void far * addr;
	unsigned char buf[4];
	void far * bufp;

	if(abs_addr < EXTEND_MEMORY_BASE)
	{
		addr = MK_FP(abs_addr);
		return *((volatile unsigned char far *)addr);
	}
	else
	{
		bufp = (void far *)&(buf[0]);

		if(extmem_to_basemem(bufp,abs_addr,2))
			return -EINVAL;
		 
		return buf[0];
	}
}

unsigned short readw(unsigned long abs_addr) 
{
	void far * addr;
	unsigned char buf[4];
	void far * bufp;

	if(abs_addr < EXTEND_MEMORY_BASE)
	{
		addr = MK_FP(abs_addr);
		return *((volatile unsigned short far *)addr);
	}
	else
	{
		bufp = (void far *)&(buf[0]);

		if(extmem_to_basemem(bufp,abs_addr,2))
			return -EINVAL;
		 
		return buf[0] + (unsigned short)buf[1] * 256;
	}
}

unsigned long readl(unsigned long abs_addr)
{
	void far * addr;
	unsigned char buf[4];
	void far * bufp;

	if(abs_addr < EXTEND_MEMORY_BASE)
	{
		addr = MK_FP(abs_addr);
	
		return (*(volatile unsigned long far *)addr);
	}
	else
	{
		bufp = (void far *)&(buf[0]);

		if(extmem_to_basemem(bufp,abs_addr,2))
			return -EINVAL;
		 
		return (*(volatile unsigned long far *)buf);
	}
}

void writeb(unsigned char b,unsigned long abs_addr)
{
	void far * addr;
	unsigned char buf[4];
	void far * bufp;

	if(abs_addr < EXTEND_MEMORY_BASE)
	{
		addr = MK_FP(abs_addr);
		*(volatile unsigned char far *)addr  =  b;
	}
	else
	{
		bufp = (void far *)&(buf[0]);

		if(extmem_to_basemem(bufp,abs_addr,2))
			return;

		buf[0] = b;
		(void)basemem_to_extmem(bufp,abs_addr,2);
	}
}


void writew(unsigned short b,unsigned long abs_addr)
{ 	
	void far * addr;
	unsigned char buf[2];
	void far * bufp;

	if(abs_addr < EXTEND_MEMORY_BASE)
	{
		addr = MK_FP(abs_addr);	
		*(volatile unsigned short far *)addr  =  b;
	}
	else
	{
		buf[0] = b & 0xff;
		buf[1] = b / 256;

		bufp = (void far *)&(buf[0]);

		(void)basemem_to_extmem(bufp,abs_addr,1);
	}
}

void writel(unsigned long b,unsigned long abs_addr)
{ 	
	void far * addr;
	unsigned char buf[4];
	void far * bufp;

	if(abs_addr < EXTEND_MEMORY_BASE)
	{
		addr = MK_FP(abs_addr);
		*(volatile unsigned long far *)addr = b;
	}
	else
	{
		*(volatile unsigned long far *)buf = b;

		bufp = (void far *)&(buf[0]);

		(void)basemem_to_extmem(bufp,abs_addr,2);
	}
}

#pragma check_stack(on)

#pragma check_stack(off)

void local_irq_restore(unsigned long irq)
{
	--flags;
	if(!flags)
	{
		_asm sti
	}

	if(irq && irq < 16)
	{
		--flags_irq[irq];
		if(!flags_irq[irq])
		{
			EnableIRQ((unsigned short)irq);
		}	
	}
}

void local_irq_save(unsigned long irq)
{
	unsigned temp;
	
	temp = 0;

	++flags;
	
	_asm pushf
	_asm pop temp
	
	if(temp & 0x0200)
	{
		_asm cli
	}

	if(irq && irq < 16)
	{
		++flags_irq[irq];
		DisableIRQ((unsigned short)irq);
	}
}

dma_addr_t ptr_to_dma(void far * p)
{
	unsigned short seg_temp,offset_temp;
	dma_addr_t buf;
		
	seg_temp = FP_SEG(p);
	offset_temp = FP_OFF(p);
	buf = (dma_addr_t)(((unsigned long)seg_temp * 16L) 
		+ (unsigned long)offset_temp);
		
	return	buf;	
}		

void far * MK_FP(unsigned long p)
{
    unsigned short temp;

    temp = p >> 4;
    _asm mov dx,temp
    _asm push dx

    temp = p % 16;
    _asm mov ax,temp
    _asm pop dx
}

void far * malloc_align(align_pointer far * p,unsigned long size,
	unsigned long align_size)
{	
	p->p_start = malloc((unsigned short)(size + align_size - 1L));
	if(!p->p_start)
		return NULL;

	p->abs_addr = ptr_to_dma(p->p_start);

	p->abs_addr = ROUND_UP((p->abs_addr),align_size);

	p->p_align = MK_FP(p->abs_addr);

	return (p->p_align);
}

void free_align(align_pointer far * p)
{
	if(p->p_start)
		free(p->p_start);
}

void copy_align_pointer(align_pointer far * dst,align_pointer far * src)
{
	dst->p_start = src->p_start;
	dst->p_align = src->p_align;
	dst->abs_addr = src->abs_addr;
}

unsigned long GetTickCount(void)
{
	return GlobalTickCount;
}

void udelay(unsigned long ms)
{
	unsigned long TickCount;
	unsigned char is_reverse;
	unsigned temp;
	unsigned is_cli;

	TickCount = GetTickCount();

	ms = ROUND_UP_TICK_COUNT(ms);

	is_reverse = 0;
	if(TickCount + ms < TickCount)
	{
		is_reverse = 1;
	}			

	TickCount += ms;

	_asm pushf
	_asm pop temp

	is_cli = 0;
	if(!(temp & 0x0200))
	{
		_asm sti		
    	is_cli = 1;
	}

	while(1)
	{
		if(!is_interrupt())
		{
			if(is_reverse)
			{
				if(!GetTickCount())
					is_reverse = 0;
			}

			if(!is_reverse)
			{
			  if(GetTickCount() >= TickCount)
				  goto move_move;
			}				   
		}
	}

	move_move:

		if(is_cli)
	    {
			_asm cli
	    }

    	return;
}

int is_reach_time_limit(struct TickCountVal far * pTickCount)
{
	unsigned long tick;

	tick = GetTickCount();

	if(pTickCount->end >= pTickCount->start)
	{
		return (tick >= pTickCount->end);
	}		

	return ((tick >= pTickCount->end) && (tick <= pTickCount->start));
}

unsigned long ffs(unsigned long value)
{
	long res;

	res = 0;

	_asm mov ax,[value]
	_asm mov cx,0

    begin_loop1_set:
		_asm rcr ax,1
		_asm jc set_found1
		_asm inc cx
		_asm cmp cx,16
		_asm jz begin2_set
		_asm jmp begin_loop1_set

	set_found1:
		_asm mov [res],cx
		
		return res;

	begin2_set:	
		_asm mov cx,0
		_asm mov ax,[value + 2]

	begin_loop2_set:
		_asm rcr ax,1
		_asm jc set_found2
		_asm inc cx
		_asm cmp cx,16
		_asm jz return_32_set
		_asm jmp begin_loop2_set
			
	set_found2:
		_asm mov [res],cx
		
		return res + 16;

	return_32_set:

		return 32L;
}

void set_bit(unsigned long nr, void far * addr)
{
	unsigned is_low_word;
	unsigned short mask;
	unsigned long far * p;

	p = (unsigned long far *)addr + (nr >> 5);
	nr &= 31UL;

	if(nr <= 15)
	{
		is_low_word = 1;
		mask = 1 << nr;
	}
	else
	{
		is_low_word = 0;
		mask = 1 << (nr - 16);
	}
	
	local_irq_save(0);

	if(is_low_word)
	{
		_asm push es
		_asm push di
		_asm les di,p
		_asm mov ax,mask
		_asm or word ptr es:[di],ax
		_asm pop di
		_asm pop es
	}
	else
	{
		_asm push es
		_asm push di
		_asm les di,p
		_asm add di,2
		_asm mov ax,mask
		_asm or word ptr es:[di],ax
		_asm pop di
		_asm pop es
	}

	local_irq_restore(0);
}

void clear_bit(unsigned long nr,void far * addr)
{
	unsigned is_low_word;
	unsigned short mask;
	unsigned long far * p;

	p = (unsigned long far *)addr + (nr >> 5);
	nr &= 31UL;

	if(nr <= 15)
	{
		is_low_word = 1;
		mask = ~(1 << nr);
	}
	else
	{
		is_low_word = 0;
		mask = ~(1 << (nr - 16));
	}
	
	local_irq_save(0);

	if(is_low_word)
	{
		_asm push es
		_asm push di
		_asm les di,p
		_asm mov ax,mask
		_asm and word ptr es:[di],ax
		_asm pop di
		_asm pop es
	}
	else
	{
		_asm push es
		_asm push di
		_asm les di,p
		_asm add di,2
		_asm mov ax,mask
		_asm and word ptr es:[di],ax
		_asm pop di
		_asm pop es
	}

	local_irq_restore(0);
}

void change_bit(unsigned long nr, volatile void *addr)
{
	unsigned is_low_word;
	unsigned short mask;
	unsigned long far * p;

	nr &= 31UL;
	p = (unsigned long far *)addr + (nr >> 5);

	if(nr <= 15)
	{
		is_low_word = 1;
		mask = 1 << nr;
	}
	else
	{
		is_low_word = 0;
		mask = 1 << (nr - 16);
	}
	
	local_irq_save(0);

	if(is_low_word)
	{
		_asm push es
		_asm push di
		_asm les di,p
		_asm mov ax,mask
		_asm xor word ptr es:[di],ax
		_asm pop di
		_asm pop es
	}
	else
	{
		_asm push es
		_asm push di
		_asm les di,p
		_asm add di,2
		_asm mov ax,mask
		_asm xor word ptr es:[di],ax
		_asm pop di
		_asm pop es
	}

	local_irq_restore(0);
}

unsigned long test_and_set_bit(unsigned long nr, void far * addr)
{
	unsigned long res;
	unsigned short mask;
	unsigned is_low_word;
	unsigned long far * p;

	nr &= 31UL;
	p = (unsigned long far *)addr + (nr >> 5);

	if(nr <= 15)
	{
		is_low_word = 1;
		mask = 1 << nr;
	}
	else
	{
		is_low_word = 0;
		mask = 1 << (nr - 16);
	}
	
	res = 0;

	local_irq_save(0);

	if(is_low_word)
	{
		_asm push es
		_asm push di
		_asm les di,p
		_asm mov ax,mask
		_asm mov dx,word ptr es:[di]
		_asm and dx,ax
		_asm jz set_bit_1
		_asm mov word ptr [res],1
		set_bit_1:
			_asm or word ptr es:[di],ax
			_asm pop di
			_asm pop es	
	}
	else
	{
		_asm push es
		_asm push di
		_asm les di,p
		_asm add di,2
		_asm mov ax,mask
		_asm mov dx,word ptr es:[di]
		_asm and dx,ax
		_asm jz set_bit_2
		_asm mov word ptr [res],1
		set_bit_2:
		_asm or word ptr es:[di],ax

⌨️ 快捷键说明

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