- /*
- By Marcus Xing
- lib/lib_kernel_in_c.c
- 内核中用C写的功能函数
- */
- #include "type.h"
- #include "const.h"
- #include "ipc.h"
- #include "protect.h"
- #include "proc.h"
- #include "console.h"
- #include "tty.h"
- #include "global.h"
- #include "proto.h"
- /* 内部声明 */
- extern void I_to_A(const char *psz_Str,int num); /* 此函数用汇编写的 */
- static int V_Printf(char *buf,const char *fmt,const char *args);
- static char* I_To_A_By_Radix(int num,int radix,char *buf);
- /*----------------------------------------------------------------------Disp_Int
- 此函数以16进制打印一个32位的整数,
- 不考虑无符号,前面的0不打印
- */
- void Disp_Int(int num)
- {
- char buffer[16]; /* 栈中的局部临时数组 */
- I_To_A(buffer,num); /* 将数字转换为字符数组送到临时数组中 */
- Disp_Str(buffer); /* 交付打印 */
- }
- /*------------------------------------------------------------------------Printf
- 模拟Printf函数,可由用户进程调用,格式字符串长度不能超过128
- 想使用就须调用Init_Console
- */
- int Printf(const char *fmt,...)
- {
- char buf[128]; /* 解析好的串存放之地 */
- /* 指向格式字符串的后一个参数 */
- char *args_begin = (char*)((char*)(&fmt) + 4);
- /* 解析格式字符串 */
- int len = V_Printf(buf,fmt,args_begin);
- /* 系统调用,交给内核在调用该函数的进程所绑定的控制台打印出来 */
- Write(buf);
- return len; /* 返回串的长度 */
- }
- /*-----------------------------------------------------------------------Str_Cpy
- 复制字符串,保证dest空间足够存放
- */
- void Str_Cpy(char *dest,const char *src)
- {
- while((*src != '/0') && (*dest++ = *src++));
- *dest = '/0';
- }
- /*-----------------------------------------------------------------------Str_Len
- 求字符串长度
- */
- int Str_Len(const char *sz_str)
- {
- int len = 0;
- while(*sz_str++ != '/0')
- {
- len++;
- }
- return len;
- }
- /*-------------------------------------------------------------------------Delay
- 粗糙的延迟函数
- */
- void Delay(u32 time)
- {
- u32 i,j,k;
- for(i = 0 ; i < time ; i++)
- {
- for(j = 0 ; j < 100 ; j++)
- {
- for(k = 0 ; k < 10000 ; k++)
- {
- }
- }
- }
- }
- /*--------------------------------------------------------------------Cursor_Loc
- 光标跟随,使用了IO指令,注意使用IO指令的段是否有权限
- */
- void Cursor_Loc()
- {
- /* 保证原子性 */
- Disable_Int();
- /* 根据d_Disp_Pos设置光标 */
- Out_Byte(CRTC_ADDR_REG,CURSOR_H);
- Out_Byte(CRTC_DATA_REG,((d_Disp_Pos / 2) >> 8) & 0xff);
- Out_Byte(CRTC_ADDR_REG,CURSOR_L);
- Out_Byte(CRTC_DATA_REG,(d_Disp_Pos / 2) & 0xff);
- Enable_Int();
- }
- /*--------------------------------------------------------------------Make_Color
- 产生一个颜色值
- */
- u8 Make_Color(u8 forward_color,u8 back_color)
- {
- u8 color = (back_color << 4) & 0xf0;
- color |= forward_color;
- return color;
- }
- /*----------------------------------------------------------------Assert_Failure
- 断言功能函数
- */
- void Assert_Failure(char *file,char *base_file,int line)
- {
- /* 否则在格式字符串的开头设为ASSERT标记,并把调用此函数的文件名等信息打印出来 */
- Printf("%c!ASEERT FILE:%s BASE FILE:%s LINE:%d",MAGIC_CHAR_ASSERT,file,base_file,line);
- /* 如果是用户进程则会跳转到这,死循环阻塞当前进程 */
- while(1);
- }
- /*-------------------------------------------------------------------------Panic
- PANIC功能函数,不在用户进程中调用,发生严重问题使用才使用,会hlt掉整个系统
- */
- void Panic(char *fmt,...)
- {
- /* 解析格式字符串到buf */
- char buf[256];
- char *args_first = (char*)((char*)&fmt + 4);
- V_Printf(buf,fmt,args_first);
- /* 附加上PANIC标志后打印之,永远不会返回 */
- Printf("%c!%s",MAGIC_CHAR_PANIC,buf);
- }
- /*---------------------------------------------------------------------Get_Ticks
- 返回当前的ticks值
- */
- int Get_Ticks()
- {
- Message m;
- m.msg_type = GET_TICKS; /* 设置消息类型 */
- Send_Receive_Shell(BOTH,4,&m);
- return m.r1;
- }
- /*----------------------------------------------------------------------V_Printf
- 解析格式字符串的功能函数
- */
- static int V_Printf(char *buf,const char *fmt,const char *args)
- {
- char tmp[128]; /* 临时存放由数字转成串的空间 */
- char *p = buf;
- /* 遍历格式字符串 */
- for(;*fmt != '/0';fmt++)
- {
- /* 如果不是控制字符,则直接放到buf中,开始下一次循环 */
- if(*fmt != '%')
- {
- *p++ = *fmt;
- continue;
- }
- /* 如果是控制字符,则指向'%'后的字符,解析之 */
- fmt++;
- switch(*fmt)
- {
- /* 如果是x,代表16进制数字 */
- case 'x':
- /* 从可变参数表取出一个参数,解释成16进制整数并转换成串存放到tmp中 */
- I_To_A_By_Radix((int)(*((int*)args)),16,tmp);
- Str_Cpy(p,tmp); /* 把转换好的串拷贝到buf中 */
- p += Str_Len(tmp); /* 移动p指向buf下一个可用的地址 */
- args += 4; /* 指向下一个可变参数 */
- break;
- /* 如果是d代表10进制数字 */
- case 'd':
- /* 从可变参数表取出一个参数,解释成10进制整数并转换成串存放到tmp中 */
- I_To_A_By_Radix((int)(*((int*)args)),10,tmp);
- Str_Cpy(p,tmp); /* 把转换好的串拷贝到buf中 */
- p += Str_Len(tmp); /* 移动p指向buf下一个可用的地址 */
- args += 4; /* 指向下一个可变参数 */
- break;
- /* 如果是c代表一个字符 */
- case 'c':
- *p++ = (char)(*(char*)args);
- args += 4;
- break;
- /* 如果是s代表字符串 */
- case 's':
- Str_Cpy(p,*(char**)args);
- p += Str_Len(*(char**)args);
- args += 4;
- break;
- default:
- break;
- }
- }
- *p = '/0'; /* 添加结束标志 */
- return p - buf; /* 返回格式串的长度 */
- }
- /*---------------------------------------------------------------I_To_A_By_Radix
- 功能函数,把num转化为radix进制的串保存到buf中
- */
- static char* I_To_A_By_Radix(int num,int radix,char *buf)
- {
- int quotient = num /radix; /* 求得商 */
- int remainder = num % radix; /* 求得余数 */
- /* 如果商不为0,则递归调用 */
- if(quotient != 0)
- {
- buf = I_To_A_By_Radix(quotient,radix,buf);
- }
- /* 如果余数大于9,则转为字母,存入buf中 */
- *buf++ = (remainder > 9) ? (remainder - 10 + 'A'):(remainder + '0');
- return buf;
- }