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

📄 low.c

📁 DOS_PCI_DRIVER,DOS环境下运行的PCI驱动程序,个人觉得比较好用.
💻 C
📖 第 1 页 / 共 4 页
字号:
		_asm pop di
		_asm pop es
	}

	local_irq_restore(0);

	return res;
}

unsigned long test_and_clear_bit(unsigned long nr,void far * addr)
{
	unsigned long res;
	unsigned short mask_clear;
	unsigned short mask_test;
	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_test = 1 << nr;
	}
	else
	{
		is_low_word = 0;
		mask_test = 1 << (nr - 16);
	}

	mask_clear = ~mask_test;
	
	res = 0;

	local_irq_save(0);

	if(is_low_word)
	{
		_asm push es
		_asm push di
		_asm les di,p
		_asm mov ax,mask_test
		_asm mov dx,word ptr es:[di]
		_asm and dx,ax
		_asm jz clear_bit_1
		_asm mov word ptr [res],1
		clear_bit_1:
			_asm mov ax,mask_clear
			_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_test
		_asm mov dx,word ptr es:[di]
		_asm and dx,ax
		_asm jz clear_bit_2
		_asm mov word ptr [res],1
		clear_bit_2:
		_asm mov ax,mask_clear
		_asm and word ptr es:[di],ax
		_asm pop di
		_asm pop es
	}
}

unsigned long test_and_change_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 change_bit_1
		_asm mov word ptr [res],1
		change_bit_1:
			_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 mov dx,word ptr es:[di]
		_asm and dx,ax
		_asm jz change_bit_2
		_asm mov word ptr [res],1
		change_bit_2:
		_asm xor word ptr es:[di],ax
		_asm pop di
		_asm pop es
	}

	local_irq_restore(0);

	return res;
}

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

	res = 0;

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

    begin_loop1_noset:
		_asm rcr ax,1
		_asm jnc noset_found1
		_asm inc cx
		_asm cmp cx,16
		_asm jz begin2_noset
		_asm jmp begin_loop1_noset

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

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

	begin_loop2_noset:
		_asm rcr ax,1
		_asm jnc noset_found2
		_asm inc cx
		_asm cmp cx,16
		_asm jz return_32_noset
		_asm jmp begin_loop2_noset
			
	noset_found2:
		_asm mov [res],cx
		
		return res + 16;

	return_32_noset:

		return 32L;
}

unsigned long find_next_zero_bit(void * addr,unsigned long size, unsigned long offset)
{
	unsigned long * p = ((unsigned long far *) addr) + (offset >> 5);
	unsigned long result = offset & ~31UL;
	unsigned long tmp;

	if (offset >= size)
		return size;

	local_irq_save(0);

	size -= result;
	offset &= 31UL;

	if (offset) 
	{
		tmp = *p++;
		tmp |= ~0UL >> (32-offset);
		if (size < 32)
			goto found_first;

		if (tmp != ~0UL)
			goto found_middle;

		size -= 32;
		result += 32;
	}

	while (size >= 32) 
	{
		if ((tmp = *p++) != ~0UL)
			goto found_middle;

		result += 32;
		size -= 32;
	}

	if (!size)
	{
		local_irq_restore(0);
		return result;
	}

	tmp = *p;

	found_first:
		tmp |= ~0UL << size;
		if (tmp == ~0UL)        /* Are any bits zero? */
		{
			local_irq_restore(0);
			return result + size; /* Nope. */
		}

	found_middle:
		local_irq_restore(0);
		return result + ffz(tmp);
}

/**
 * atomic_add - add integer to atomic variable
 * @i: integer value to add
 * @v: pointer of type atomic_t
 * 
 * Atomically adds @i to @v.  Note that the guaranteed useful range
 * of an atomic_t is only 24 bits.
 */
void atomic_add(long i, atomic_t far * v)
{
	long far * p;

	p = &(v->count);

	local_irq_save(0);

	_asm les di,p
	_asm mov ax,[i]
	_asm add word ptr es:[di],ax
	_asm mov ax,[i + 2]
	_asm adc word ptr es:[di + 2],ax
	
	local_irq_restore(0);
}

/**
 * atomic_sub - subtract the atomic variable
 * @i: integer value to subtract
 * @v: pointer of type atomic_t
 * 
 * Atomically subtracts @i from @v.  Note that the guaranteed
 * useful range of an atomic_t is only 24 bits.
 */
void atomic_sub(long i,atomic_t far * v)
{
	long far * p;

	p = &(v->count);

	local_irq_save(0);

	_asm les di,p
	_asm mov ax,[i]
	_asm sub word ptr es:[di],ax
	_asm mov ax,[i + 2]
	_asm sbb word ptr es:[di + 2],ax
	
	local_irq_restore(0);
}

/**
 * atomic_sub_and_test - subtract value from variable and test result
 * @i: integer value to subtract
 * @v: pointer of type atomic_t
 * 
 * Atomically subtracts @i from @v and returns
 * true if the result is zero, or false for all
 * other cases.  Note that the guaranteed
 * useful range of an atomic_t is only 24 bits.
 */
long atomic_sub_and_test(long i,atomic_t far * v)
{
	long far * p;
	long res;

	res = 0L;
	p = &(v->count);

	local_irq_save(0);

	_asm les di,p
	_asm mov ax,[i]
	_asm sub word ptr es:[di + 2],ax
	_asm mov ax,[i + 2]
	_asm sbb word ptr es:[di],ax
	_asm mov ax,es:[di]
	_asm mov dx,es:[di + 2]
	_asm or ax,dx
	_asm jnz return_res
	_asm mov word ptr [res],1
	_asm mov word ptr [res + 2],0
	
	return_res:
		
		local_irq_restore(0);

		return res;
}

/**
 * atomic_inc - increment atomic variable
 * @v: pointer of type atomic_t
 * 
 * Atomically increments @v by 1.  Note that the guaranteed
 * useful range of an atomic_t is only 24 bits.
 */
void atomic_inc(atomic_t far * v)
{
	long far * p;

	p = &(v->count);

	local_irq_save(0);

	_asm les di,p
	_asm add word ptr es:[di],1
	_asm adc word ptr es:[di + 2],0
	
	local_irq_restore(0);
}

/**
 * atomic_dec_and_test - decrement and test
 * @v: pointer of type atomic_t
 * 
 * Atomically decrements @v by 1 and
 * returns true if the result is 0, or false for all other
 * cases.  Note that the guaranteed
 * useful range of an atomic_t is only 24 bits.
 */ 
long atomic_dec_and_test(atomic_t far * v)
{
	long far * p;
	long res;

	res = 0L;
	p = &(v->count);

	local_irq_save(0);

	_asm les di,p
	_asm sub word ptr es:[di],1
	_asm sbb word ptr es:[di + 2],0
	_asm mov ax,es:[di]
	_asm mov dx,es:[di + 2]
	_asm or ax,dx
	_asm jnz return_res1
	_asm mov word ptr [res],1
	_asm mov word ptr [res + 2],0
	
	return_res1:

		local_irq_restore(0);

		return res;
}

/**
 * atomic_dec - decrement atomic variable
 * @v: pointer of type atomic_t
 * 
 * Atomically decrements @v by 1.  Note that the guaranteed
 * useful range of an atomic_t is only 24 bits.
 */ 
void atomic_dec(atomic_t far * v)
{
	long far * p;

	p = &(v->count);

	local_irq_save(0);

	_asm les di,p
	_asm sub word ptr es:[di],1
	_asm sbb word ptr es:[di + 2],0

	local_irq_restore(0);
}

/**
 * atomic_inc_and_test - increment and test 
 * @v: pointer of type atomic_t
 * 
 * Atomically increments @v by 1
 * and returns true if the result is zero, or false for all
 * other cases.  Note that the guaranteed
 * useful range of an atomic_t is only 24 bits.
 */ 
long atomic_inc_and_test(atomic_t far * v)
{
	long far * p;
	long res;

	res = 0L;
	p = &(v->count);

	local_irq_save(0);

	_asm les di,p
	_asm add word ptr es:[di],1
	_asm adc word ptr es:[di + 2],0
	_asm mov ax,es:[di]
	_asm mov dx,es:[di + 2]
	_asm or ax,dx
	_asm jnz return_res2
	_asm mov word ptr [res],1
	_asm mov word ptr [res + 2],0
	
	return_res2:

		local_irq_restore(0);

		return res;
}

void zero_is_chain(void)
{
	is_chain = 0;
}

unsigned long is_interrupt(void)
{
	return (unsigned long)is_in_interrupt;
}

#pragma check_stack(on)

#pragma check_stack(off)

extern unsigned char common_is_sti;
extern struct irq_action far * common_action;
extern long common_irq;
extern unsigned char common_is_sti;
extern void far * common_ptr;
extern unsigned short common_intsp,common_intss;
extern unsigned short common_temp;

#ifdef DEBUG_HARDWARE_INTERRUPT_USE_MEMORY
    extern unsigned long run_status;
    extern unsigned long status1;
    extern unsigned long status2;
	extern 	void (_far * irq_handler)(long irq,void far * __hcd);
    extern unsigned long pass_count;
#endif

void common_new_handler(long irq)
{
	unsigned short temp;

	#ifdef DEBUG_HARDWARE_INTERRUPT_USE_MEMORY
			run_status = 0L;
			status1 = 0;
			status2 = 0;
			irq_handler = 0;
	#endif

	DisableIRQ((unsigned short)irq);

	_asm pushf
	_asm pop temp

	common_is_sti = 0;
	if(temp & 0x0200)
	{
		_asm cli	
		common_is_sti = 1;
	}

	is_chain = 1;
	common_irq = irq;

	_asm mov ax,seg common_intsp
	_asm mov es,ax
	_asm lea di,common_intsp
	_asm mov es:[di],sp

	_asm mov ax,seg common_intss
	_asm mov es,ax
	_asm lea di,common_intss
	_asm mov es:[di],ss

	common_ptr =  (void far *)(&(mystack[MY_STACK_SIZE - 5]));

	common_temp = FP_SEG(common_ptr);

	_asm mov ax,seg common_temp
	_asm mov es,ax
	_asm lea di,common_temp
	_asm mov ss,es:[di]

	common_temp = FP_OFF(common_ptr);

	_asm mov ax,seg common_temp
	_asm mov es,ax
	_asm lea di,common_temp
	_asm mov sp,es:[di]

	irq_for_each_action(common_action,common_irq)
	{
		AddLogToXms("Call irq handler %p,irq %d\n",
		       common_action->handler,common_irq);

		#ifdef DEBUG_HARDWARE_INTERRUPT_USE_MEMORY
			run_status = 1;

			irq_handler = common_action->handler;
		#endif

		common_action->handler(common_irq,common_action->__hcd);
	}

	_asm mov ax,seg common_intsp
	_asm mov es,ax
	_asm lea di,common_intsp
	_asm mov sp,es:[di]

	_asm mov ax,seg common_intss
	_asm mov es,ax
	_asm lea di,common_intss
	_asm mov ss,es:[di]

	if(is_chain && global_irq_table[common_irq].old_handler)
	{
		AddLogToXms("Call chain_intr for irq %d\n",common_irq);

		#ifdef DEBUG_HARDWARE_INTERRUPT_USE_MEMORY
			run_status |= 2;
		#endif

		_chain_intr(global_irq_table[common_irq].old_handler);
		is_chain = 0;
	}

	SendEOI((unsigned short)common_irq);

	if(common_is_sti)
	{
		_asm sti		
	}

	EnableIRQ((unsigned short)common_irq);				
}

void _interrupt new_handler_0(void)
{
	++is_in_interrupt;
	common_new_handler(0);
	--is_in_interrupt;
}

void _interrupt new_handler_1(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(1);
	--is_in_interrupt;
}

void _interrupt new_handler_2(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(2);
	--is_in_interrupt;
}

void _interrupt new_handler_3(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(3);
	--is_in_interrupt;
}

void _interrupt new_handler_4(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(4);
	--is_in_interrupt;
}

void _interrupt new_handler_5(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(5);
	--is_in_interrupt;
}

void _interrupt new_handler_6(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(6);
	--is_in_interrupt;
}

void _interrupt new_handler_7(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(7);
	--is_in_interrupt;
}

void _interrupt new_handler_8(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(8);
	--is_in_interrupt;
}

void _interrupt new_handler_9(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(9);
	--is_in_interrupt;
}

void _interrupt new_handler_10(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;

	#ifdef DEBUG_HARDWARE_INTERRUPT_USE_MEMORY
		++pass_count;
	#endif

	#ifdef DEBUG_HARDWARE_INTERRUPT
		BeginLog();
	#endif

	common_new_handler(10);

	#ifdef DEBUG_HARDWARE_INTERRUPT
		EndLog();
	#endif

	--is_in_interrupt;
}

void _interrupt new_handler_11(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;

	#ifdef DEBUG_HARDWARE_INTERRUPT_USE_MEMORY
		++pass_count;
	#endif

	#ifdef DEBUG_HARDWARE_INTERRUPT
		BeginLog();
	#endif

	common_new_handler(11);

	#ifdef DEBUG_HARDWARE_INTERRUPT
		EndLog();
	#endif

	--is_in_interrupt;
}

void _interrupt new_handler_12(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(12);
	--is_in_interrupt;
}

void _interrupt new_handler_13(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(13);
	--is_in_interrupt;
}

void _interrupt new_handler_14(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(14);
	--is_in_interrupt;
}

void _interrupt new_handler_15(void)
{
	if(is_in_interrupt)
	    return;

	++is_in_interrupt;
	common_new_handler(15);
	--is_in_interrupt;
}

#pragma check_stack(on)

void init_irq_table(void)
{
	unsigned short i;

	for(i = 0; i < 16; ++i)
	{
		INIT_LIST_HEAD (&(global_irq_table[i].irq_action_list));
	}

	for(i = 0; i < 16; ++i)
	{
		global_irq_table[i].old_handler = 0;
	}

	for(i = 0; i < 16; ++i)
	{
		flags_irq[i] = 0;
	}

	global_irq_table[0].new_handler = new_handler_0;
	global_irq_table[1].new_handler = new_handler_1;
	global_irq_table[2].new_handler = new_handler_2;
	global_irq_table[3].new_handler = new_handler_3;
	global_irq_table[4].new_handler = new_handler_4;
	global_irq_table[5].new_handler = new_handler_5;
	global_irq_table[6].new_handler = new_handler_6;
	global_irq_table[7].new_handler = new_handler_7;
	global_irq_table[8].new_handler = new_handler_8;
	global_irq_table[9].new_handler = new_handler_9;
	global_irq_table[10].new_handler = new_handler_10;
	global_irq_table[11].new_handler = new_handler_11;
	global_irq_table[12].new_handler = new_handler_12;
	global_irq_table[13].new_handler = new_handler_13;
	global_irq_table[14].new_handler = new_handler_14;
	global_irq_table[15].new_handler = new_handler_15;

	global_irq_table[0].vect_num = 0x08;
	global_irq_table[1].vect_num = 0x09;
	global_irq_table[2].vect_num = 0x0a;
	global_irq_table[3].vect_num = 0x0b;
	global_irq_table[4].vect_num = 0x0c;
	global_irq_table[5].vect_num = 0x0d;
	global_irq_table[6].vect_num = 0x0e;
	global_irq_table[7].vect_num = 0x0f;
	global_irq_table[8].vect_num = 0x70;
	global_irq_table[9].vect_num = 0x71;
	global_irq_table[10].vect_num = 0x72;
	global_irq_table[11].vect_num = 0x73;
	global_irq_table[12].vect_num = 0x74;

⌨️ 快捷键说明

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