// bootpack.c #include "bootpack.h" #include #define MEMMAN_FREES 4090 // これで約32KB #define MEMMAN_ADDR 0x003c0000 typedef struct _freeinfo { // あき情報 unsigned int addr, size; } FREEINFO, *PFREEINFO; typedef struct _memman { // メモリ管理 int frees, maxfrees, lostsize, losts; FREEINFO free[MEMMAN_FREES]; } MEMMAN, *PMEMMAN; unsigned int memtest(unsigned int start, unsigned int end); void memman_init(PMEMMAN man); unsigned int memman_total(PMEMMAN man); unsigned int memman_alloc(PMEMMAN man, unsigned int size); int memman_free(PMEMMAN man, unsigned int addr, unsigned int size); void HariMain(void) { PBOOTINFO pbinfo = (PBOOTINFO) ADDR_BOOTINFO; char str[256], mcursor[256], keybuf[32], mousebuf[128]; unsigned int memtotal; int mx, my, i; MOUSE_DEC mdec; PMEMMAN memman = (PMEMMAN ) MEMMAN_ADDR; init_gdtidt(); init_pic(); io_sti(); // IDT/PICの初期化が終わったのでCPUの割り込み禁止を解除 // FIFO生成 fifo8_init(&keyfifo, 32, keybuf); fifo8_init(&mousefifo, 128, mousebuf); io_out8(PIC0_IMR, 0xf9); // 1111 1001(PIC1とキーボードを許可) io_out8(PIC1_IMR, 0xef); // 1110 1111(マウスを許可) init_keyboard(); set_palette(COL8_BLACK, COL8_DARKGRAY, init_palette()); init_screen8(pbinfo->vram, pbinfo->scrnx, pbinfo->scrny); // マウスの座標計算 mx = ((pbinfo->scrnx - 16) / 4) * 3; my = ((pbinfo->scrny - 28 - 16) / 4) * 3; // マウス描画 init_mouse_cursor8(mcursor, COL8_DARKWATER); putblock8_8(pbinfo->vram, pbinfo->scrnx, 16, 16, mx, my, mcursor, 16); // マウス位置を文字列で表示 sprintf(str, "mouse is (x, y) = (%d, %d)", mx, my); putfonts8_asc(pbinfo->vram, pbinfo->scrnx, 0, 0, COL8_WHITE, str); // 文字列を表示 sprintf(str, "I will make the hariboteOS after 25 days."); putfonts8_asc(pbinfo->vram, pbinfo->scrnx, 0, 32, COL8_YELLOW, str); enable_mouse(&mdec); memtotal = memtest(0x00400000, 0xbfffffff); memman_init(memman); memman_free(memman, 0x00001000, 0x0009e000); // 0x00001000 - 0x0009efff memman_free(memman, 0x00400000, memtotal - 0x00400000); sprintf(str, "memory %dMB free : %dKB", memtotal / (1024 * 1024), memman_total(memman) / 1024); putfonts8_asc(pbinfo->vram, pbinfo->scrnx, 0, 64, COL8_WHITE, str); while (1) { // 無限ループ(割り込みで取得したデータを監視) io_cli(); if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) { io_stihlt(); // マウスもキーボードもデータなしなら休む } else { if (fifo8_status(&keyfifo) != 0) { // キーボードデータがあるなら i = fifo8_get(&keyfifo); // FIFOから取得 io_sti(); sprintf(str, "%02X", i); // 出力 boxfill8(pbinfo->vram, pbinfo->scrnx, COL8_DARKWATER, 0, 16, 15, 31); putfonts8_asc(pbinfo->vram, pbinfo->scrnx, 0, 16, COL8_WHITE, str); } else if (fifo8_status(&mousefifo) != 0) { // マウスデータがあるなら i = fifo8_get(&mousefifo); // FIFOから取得 io_sti(); if (mouse_decode(&mdec, i) != 0) { // データが3バイト揃ったので表示 sprintf(str, "[lcr %4d %4d]", mdec.x, mdec.y); if ((mdec.btn & 0x01) != 0) str[1] = 'L'; if ((mdec.btn & 0x02) != 0) str[3] = 'R'; if ((mdec.btn & 0x04) != 0) str[2] = 'C'; boxfill8(pbinfo->vram, pbinfo->scrnx, COL8_DARKWATER, 32, 16, 32 + 15 * 8 - 1, 31); putfonts8_asc(pbinfo->vram, pbinfo->scrnx, 32, 16, COL8_WHITE, str); // マウスカーソルの移動 */ boxfill8(pbinfo->vram, pbinfo->scrnx, COL8_DARKWATER, mx, my, mx + 15, my + 15); // マウス消す mx += mdec.x; my += mdec.y; if (mx < 0) mx = 0; if (my < 0) my = 0; if (mx > pbinfo->scrnx - 16) mx = pbinfo->scrnx - 16; if (my > pbinfo->scrny - 16) my = pbinfo->scrny - 16; sprintf(str, "(%3d, %3d)", mx, my); boxfill8(pbinfo->vram, pbinfo->scrnx, COL8_DARKWATER, 0, 0, 79, 15); putfonts8_asc(pbinfo->vram, pbinfo->scrnx, 0, 0, COL8_WHITE, str); putblock8_8(pbinfo->vram, pbinfo->scrnx, 16, 16, mx, my, mcursor, 16); } } } } } #define EFLAGS_AC_BIT 0x00040000 #define CR0_CACHE_DISABLE 0x60000000 unsigned int memtest(unsigned int start, unsigned int end) { char flg486 = 0; unsigned int eflg, cr0, i; // 386か、486以降なのかの確認 eflg = io_load_eflags(); eflg |= EFLAGS_AC_BIT; // AC-bit = 1 io_store_eflags(eflg); eflg = io_load_eflags(); if ((eflg & EFLAGS_AC_BIT) != 0) { // 386ではAC=1にしても自動で0に戻ってしまう flg486 = 1; } eflg &= ~EFLAGS_AC_BIT; // AC-bit = 0 io_store_eflags(eflg); if (flg486 != 0) { cr0 = load_cr0(); cr0 |= CR0_CACHE_DISABLE; // キャッシュ禁止 store_cr0(cr0); } i = memtest_sub(start, end); if (flg486 != 0) { cr0 = load_cr0(); cr0 &= ~CR0_CACHE_DISABLE; // キャッシュ許可 store_cr0(cr0); } return i; } // 構造体の初期化処理 void memman_init(PMEMMAN man) { man->frees = 0; // 空き領域の個数 man->maxfrees = 0; // freesの最大値(空き領域の個数を観察するために使用) man->lostsize = 0; // 開放に失敗したメモリの合計サイズ man->losts = 0; // 開放に失敗した回数 } // すべての空き領域の合計サイズを取得 unsigned int memman_total(PMEMMAN man) { unsigned int i, t = 0; for (i = 0; i < man->frees; i++) t += man->free[i].size; // 変数tにサイズを加算 return t; } // メモリ確保 unsigned int memman_alloc(PMEMMAN man, unsigned int size) { unsigned int i, a; for (i = 0; i < man->frees; i++) { if (man->free[i].size >= size) { // 要求サイズ以上のメモリ領域を発見 a = man->free[i].addr; man->free[i].addr += size; man->free[i].size -= size; if (man->free[i].size == 0) { // 要求メモリサイズと領域メモリサイズが同じだったなら // メモリ領域がちょうどなくなるので前へつめる for (man->frees--; i < man->frees; i++) man->free[i] = man->free[i + 1]; // 構造体の代入 } return a; // 確保したメモリ領域のアドレスを返す } } return 0; // もうあきがないっすよ先輩。休みもないっすよ先輩。 } // メモリ解放 int memman_free(PMEMMAN man, unsigned int addr, unsigned int size) { int i, j; // まとめやすさを考えると、free[]がaddr順に並んでいるほうがいい // だからまず、どこに入れるべきかを決める // 挿入場所の検索 for (i = 0; i < man->frees; i++) if (man->free[i].addr > addr) break; // free[i - 1].addr < addr < free[i].addr // 前にメモリ領域がある if (i > 0) { if (man->free[i - 1].addr + man->free[i - 1].size == addr) { // 前のあき領域にまとめられる man->free[i - 1].size += size; if (i < man->frees) { // 後ろもある if (addr + size == man->free[i].addr) { // なんと後ろともまとめられる You are Lucky! man->free[i - 1].size += man->free[i].size; // man->free[i]の削除 // free[i]がなくなったので前へつめる for (man->frees--; i < man->frees; i++) man->free[i] = man->free[i + 1]; // 構造体の代入 } } return 0; // 成功終了 } } // 後ろにメモリ領域がある if (i < man->frees) { if (addr + size == man->free[i].addr) { // 後ろとまとめられる man->free[i].addr = addr; man->free[i].size += size; return 0; // 成功終了 } } // 前後にメモリ領域がない if (man->frees < MEMMAN_FREES) { // free[i]より後ろを、後ろへずらして、すきまを作る for (j = man->frees; j > i; j--) { man->free[j] = man->free[j - 1]; } man->frees++; if (man->maxfrees < man->frees) man->maxfrees = man->frees; // 最大値を更新 man->free[i].addr = addr; man->free[i].size = size; return 0; // 成功終了 } // 後ろにずらせなかった man->losts++; man->lostsize += size; return -1; // 失敗終了 }