www.pudn.com > r&s1.10°æ±¾£«Îĵµ.rar > trace.c


/* 
=============================================================================== 
| Copyright (C) 2004 RuanHaiShen, All rights reserved. 
| SUMMARY:  
|   Tracing system. 
| 
| DESCRIPTION: 
|   See http://www.01s.org for documentation, latest information, license  
|   and contact details. 
|   email:ruanhaishen@01s.org 
=============================================================================*/  
/*===========================================================================*/ 
#include  
#include  
#include  
#include  
 
#include "arch/arch.h" 
#include "inc/queue.h" 
#include "inc/kernel.h" 
#include "inc/memory.h" 
#include "inc/ipc.h" 
#include "inc/kapi.h" 
 
 
#define DISP_BASE               0xB800       /* Base segment of display (0xB800=VGA, 0xB000=Mono)  */ 
#define DISP_MAX_X                  80       /* Maximum number of columns                          */ 
#define DISP_MAX_Y                  25       /* Maximum number of rows                             */ 
#define RS_DISP_MIN_Y                2 
#define RS_DISP_MAX_Y               25 
 
#define DISP_FGND_BLACK           0x00 
#define DISP_FGND_BLUE            0x01 
#define DISP_FGND_GREEN           0x02 
#define DISP_FGND_CYAN            0x03 
#define DISP_FGND_RED             0x04 
#define DISP_FGND_PURPLE          0x05 
#define DISP_FGND_BROWN           0x06 
#define DISP_FGND_LIGHT_GRAY      0x07 
#define DISP_FGND_DARK_GRAY       0x08 
#define DISP_FGND_LIGHT_BLUE      0x09 
#define DISP_FGND_LIGHT_GREEN     0x0A 
#define DISP_FGND_LIGHT_CYAN      0x0B 
#define DISP_FGND_LIGHT_RED       0x0C 
#define DISP_FGND_LIGHT_PURPLE    0x0D 
#define DISP_FGND_YELLOW          0x0E 
#define DISP_FGND_WHITE           0x0F 
 
#define DISP_BGND_BLACK           0x00 
#define DISP_BGND_BLUE            0x10 
#define DISP_BGND_GREEN           0x20 
#define DISP_BGND_CYAN            0x30 
#define DISP_BGND_RED             0x40 
#define DISP_BGND_PURPLE          0x50 
#define DISP_BGND_BROWN           0x60 
#define DISP_BGND_LIGHT_GRAY      0x70 
 
#define DISP_BLINK                0x80 
 
#define ICC_8254_CWR              0x43       /* 8254 PIT control word register address.            */ 
#define ICC_8254_CTR0             0x40       /* 8254 PIT timer 0 register address.                 */ 
#define ICC_8254_CTR1             0x41       /* 8254 PIT timer 1 register address.                 */ 
#define ICC_8254_CTR2             0x42       /* 8254 PIT timer 2 register address.                 */ 
 
#define ICC_8254_CTR0_MODE3       0x36       /* 8254 PIT binary mode 3 for counter 0 control word. */ 
#define ICC_8254_CTR2_MODE0       0xB0       /* 8254 PIT binary mode 0 for counter 2 control word. */ 
#define ICC_8254_CTR2_LATCH       0x80       /* 8254 PIT latch command control word                */ 
 
#define VECT_TICK                 0x08       /* Vector number for 82C54 timer tick                 */ 
#define VECT_DOS_CHAIN            0x81       /* Vector number used to chain DOS                    */ 
 
static jmp_buf _jump_flag; 
static bool _exit_flag; 
unsigned char _dos_tick_counter; 
 
bool key_get(int *c) 
{ 
    if (kbhit()) { 
        *c = getch(); 
        return true; 
    } else { 
        *c = 0x00; 
        return false; 
    } 
} 
 
static void cursor_movenext(unsigned char* px, unsigned char* py) 
{ 
    (*px)++; 
    if (*px > DISP_MAX_X) { 
        *px = 0; 
        (*py)++; 
    } 
} 
 
static void cursor_nextrow(unsigned char* px, unsigned char* py) 
{ 
    (*px) = 0; 
    (*py)++; 
    if (*py > RS_DISP_MAX_Y) { 
        *py = RS_DISP_MIN_Y; 
    } 
} 
 
static void x86_vga_write_char(unsigned char x, unsigned char y, const char c, char style) 
{ 
    unsigned short offset; 
    char far* pv; 
     
    offset = DISP_MAX_X * 2 * y + x * 2; 
    pv = (char far *)MK_FP(DISP_BASE, offset); 
    *pv++ = c; 
    *pv = style; 
} 
 
 
void x86_vga_write(unsigned char *s, int count) 
{ 
    unsigned char abyte; 
    static unsigned char xpos = 0; 
    static unsigned char ypos = 0; 
    
    while (count--) { 
        abyte = *s++; 
        if (abyte != '\n') { 
            x86_vga_write_char(xpos, ypos, abyte, DISP_FGND_WHITE); 
            cursor_movenext(&xpos, &ypos); 
        } else { 
            cursor_nextrow(&xpos, &ypos); 
        } 
    } 
} 
 
static void clear_screen(char color) 
{ 
    char far *pv; 
    int i; 
 
    pv = (unsigned char far *)MK_FP(DISP_BASE, 0x0000); 
 
    for (i = 0; i < (DISP_MAX_X * DISP_MAX_Y); i++) { 
        *pv++ = ' '; 
        *pv++ = color; 
    } 
} 
 
static void* intr_vect_get(int vect) 
{ 
    unsigned short *pvect; 
    int off; 
    int seg; 
 
    pvect = (unsigned short *)MK_FP(0x0000, vect * 4); 
    CRITICAL_ENTER; 
    off = *pvect++; 
    seg = *pvect; 
    CRITICAL_EXIT; 
    return (MK_FP(seg, off)); 
} 
 
static void intr_vect_set(int vect, void* isr) 
{ 
    unsigned short *pvect; 
 
    pvect = (unsigned short *)MK_FP(0x0000, vect * 4); 
    CRITICAL_ENTER; 
    *pvect++ = (unsigned short)FP_OFF(isr); 
    *pvect = (unsigned short)FP_SEG(isr); 
    CRITICAL_EXIT; 
} 
 
static void tick_rate_set (int freq) 
{ 
    int count; 
 
    if (freq == 18) { 
        count = 0; 
    } else if (freq > 0) { 
        count = (int)(((long)2386360L / freq + 1) >> 1); 
    } else { 
        count = 0; 
    } 
    CRITICAL_ENTER; 
    outp(ICC_8254_CWR, ICC_8254_CTR0_MODE3); 
    outp(ICC_8254_CTR0, count & 0xFF); 
    outp(ICC_8254_CTR0, (count >> 8) & 0xFF); 
    CRITICAL_EXIT; 
} 
 
static void dos_save_return(void) 
{ 
    void* isr_old; 
 
    _exit_flag = false; 
    _dos_tick_counter = 1; 
 
    isr_old = intr_vect_get(VECT_TICK); 
    intr_vect_set(VECT_DOS_CHAIN, isr_old); 
 
    intr_vect_set(VECT_TICK, __timer_intr_s); 
    tick_rate_set(TICKS_PER_SEC);  
 
    setjmp(_jump_flag); 
    if (_exit_flag) { 
        CRITICAL_ENTER; 
        tick_rate_set(18);                                 /* restore tick*/ 
        CRITICAL_EXIT; 
        isr_old = intr_vect_get(VECT_DOS_CHAIN); 
        intr_vect_set(VECT_TICK, isr_old); 
        clear_screen(DISP_FGND_WHITE + DISP_BGND_BLACK);   /* clear the display*/ 
        exit(0);                                           /* return to DOS*/ 
    } 
} 
 
static void return_to_dos(void) 
{ 
    _exit_flag = true; 
    longjmp(_jump_flag, 1); 
} 
 
void hardware_init(void) 
{ 
    disable_irq(); 
    dos_save_return(); 
    clear_screen(DISP_FGND_WHITE);  
} 
 
void halt(void) 
{ 
    return_to_dos(); 
} 
 
/*===========================================================================*/