📄 low.c
字号:
_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 + -