JOS1-1

调用顺序:

1.

init.c /  void i386_init(void)       

2. 

console.c /  void cons_init()   

3. 

 cga_init();
 kbd_init();
 serial_init();

4.

/* 
 * 获取显存第一个位置的指针
 * 获取当前光标位置
 */
static void
cga_init(void)
{
    volatile uint16_t *cp;
    uint16_t was;
    unsigned pos;

    cp = (uint16_t*) (KERNBASE + CGA_BUF);
    was = *cp;                             /*保存显存前2个字节*/
    *cp = (uint16_t) 0xA55A;               /*重新写显存的第一个位置 背景为高亮绿色 前景为洋红 */
    if (*cp != 0xA55A) {
        cp = (uint16_t*) (KERNBASE + MONO_BUF);
        addr_6845 = MONO_BASE;
    } else {
        *cp = was;                         /*显存第一个位置恢复原样*/
        addr_6845 = CGA_BASE;
    }

    /* Extract cursor location */          /*获取光标位置*/
    outb(addr_6845, 14);                   /*0x3d4 - 0eh*/
    pos = inb(addr_6845 + 1) << 8;         /*高八位*/
    outb(addr_6845, 15);                   /*0x3d4 - 0fh*/
    pos |= inb(addr_6845 + 1);             /*低八位*/

    crt_buf = (uint16_t*) cp;             
    crt_pos = pos;
}


/*串口I/O初始化*/
static void
serial_init(void)
{
    // Turn off the FIFO
    outb(COM1+COM_FCR, 0);

    // Set speed; requires DLAB latch
    outb(COM1+COM_LCR, COM_LCR_DLAB);
    outb(COM1+COM_DLL, (uint8_t) (115200 / 9600));
    outb(COM1+COM_DLM, 0);

    // 8 data bits, 1 stop bit, parity off; turn off DLAB latch
    outb(COM1+COM_LCR, COM_LCR_WLEN8 & ~COM_LCR_DLAB);

    // No modem controls
    outb(COM1+COM_MCR, 0);
    // Enable rcv interrupts
    outb(COM1+COM_IER, COM_IER_RDI);

    // Clear any preexisting overrun indications and interrupts
    // Serial port doesn't exist if COM_LSR returns 0xFF
    serial_exists = (inb(COM1+COM_LSR) != 0xFF);
    (void) inb(COM1+COM_IIR);
    (void) inb(COM1+COM_RX);

}

5.

cprintf()  -->  vcprintf() -->  vprintfmt()

-->putch()/printfmt()-->cputchar()-->cons_putc()

-->

serial_putc(c) 将数据输出到外设

lpt_putc(c)     数据输出到并行接口

cga_putc(c)    (函数内会处理转义字符)数据输出到cga

    // What is the purpose of this?
    if (crt_pos >= CRT_SIZE) {
        int i;
 
        memmove(crt_buf, crt_buf + CRT_COLS, (CRT_SIZE - CRT_COLS) * sizeof(uint16_t));
        for (i = CRT_SIZE - CRT_COLS; i < CRT_SIZE; i++)
            crt_buf[i] = 0x0700 | ' ';
        crt_pos -= CRT_COLS;
    }

作用:如果输出的数据超过一个屏幕 80×25 大小 那么就会向上卷屏。
memmove作用是向上卷一行,那么下面自然是原来的最后一行,这样倒数第一行与倒数第二行重复,所以倒数第一行用空格填充并且把pos设置好。

    outb(addr_6845, 14);
    outb(addr_6845 + 1, crt_pos >> 8);
    outb(addr_6845, 15);
    outb(addr_6845 + 1, crt_pos);

根据当前位置移动光标。
vprintfmt()中处理八进制的代码:

        // (unsigned) octal
        case 'o':
            // Replace this with your code.
            putch('X', putdat);
            putch('X', putdat);
            putch('X', putdat);
            break;

我们来看看十六进制是如何实现的:

        // (unsigned) hexadecimal
        case 'x':
            num = getuint(&ap, lflag);
            base = 16;
        number:
            printnum(putch, putdat, num, base, width, padc);
            break;

Exercise 8. We have omitted a small fragment of code - the code necessary to print octal numbers using patterns of the form "%o". Find and fill in this code fragment.

        // (unsigned) octal
        case 'o':
            // Replace this with your code.                     
            //putch('X', putdat);
            //putch('X', putdat);
            //putch('X', putdat);
            num = getuint(&ap, lflag);
            base = 8;
            goto number;
            break;

6.

i386_init() --> test_backtrace() -->

void
test_backtrace(int x)
{
    cprintf("entering test_backtrace %d\n", x);
    if (x > 0)
        test_backtrace(x-1);
    else
        mon_backtrace(0, 0, 0);
    cprintf("leaving test_backtrace %d\n", x);
}

-->

int
mon_backtrace(int argc, char **argv, struct Trapframe *tf)
{
    // Your code here.
    return 0;
}
posted @ 2014-07-22 22:58  乾卦  阅读(199)  评论(0)    收藏  举报