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