advance/driver/01
の編集
http://hrb.osask.jp/wiki/?advance/driver/01
[
リロード
|
差分
|
単語検索
|
一覧
] [
編集
|
バックアップ
|
添付
]
-- 雛形とするページ --
A
Akkie
Athlon64X2
Clover
DAsoran
Falcon
FormatRule
FrontPage
Genesis
Help
I
InterWikiName
InterWikiSandBox
InterWikiテクニカル
Jormungand
K
Kebo
Kor_Lee_Hee_Rak
Leaf
Linux
Linux/wako_memo
MOIZ99
MW
MenuBar
OSC
PG_MANA
ReadersOS
RecentDeleted
SKYDASH
SandBox
Sero
Sigle
Source
Triangle_Ld.
Zxcvbnm
advance
advance/CPU
advance/FDC
advance/FPU
advance/NotHariMain
advance/QEMUVGA
advance/RTC
advance/blike
advance/cpu_reset
advance/driver
advance/driver/01
advance/driver/02
advance/families
advance/filesystem
advance/fwrite
advance/hddboot
advance/he86
advance/hints
advance/ipl
advance/kernel
advance/keycode
advance/osselect
advance/smaller1
advance/startup
advnace/smaller2
anzy
aotatsu
banbi-
bluedwarf
bo
bugs
challengers
cybozulabsyouth11
deskmanta
esb02b
faq
faq/advance
faq/asm
faq/c00-03
faq/c04-07
faq/c08-15
faq/c16-23
faq/c24-31
faq/make
faq/others
faq/qemu
guide
guide03
guide05
guide07
hikarupsp
imp_log/0000
imp_log/0001
imp_log/0002
imp_log/0003
impressions
index
k
killer_elf
kota
lea
lea/10_memory
lea/4_color
lea/idea
lea/terms
links
logs
logs/osa_hrb/comments0000
logs/osa_hrb/rumors0000
masa
members
message
mistakes
moge32
moppoi5168
notice
osdevjp
populars
prog_index
projects
q_and_a
q_and_a_2
qa_log/0000
qa_log/0001
qa_log/0002
qa_log/0003
qa_log/0004
qa_log/0005
qa_log/0006
qa_log/0007
qa_log/0008
qa_log/0009
quark
rankings
rule
sakamoto
sasaki
spc09
spcc_30min_os
tatsu
tools
tools/bim2hrb
tools/bin2obj
tools/cc1
tools/edimg
tools/gas2nask
tools/makefont
tools/nask
tools/obj2bim
tools/sjisconv
uchan
uho
updates
violations
wako
white
win64-bit
x
ytakano
ヘルプ
リックス
質問します
整形ルール
本は買ったぞ!持ってるぞ!
練習用ページ
* デバイスドライバってどうやって作るの? -(by [[K]], 2008.03.21) -発展課題のページ(全部読む前にここを読むのは混乱するのでおすすめじゃないです) --このページは子ページです。親ページはこちら → [[advance/driver]] ---- -このページではデバイスドライバを使えるようにするための、OS本体の改造個所をまとめてあります。 *** naskfunc.nas -asm_hrb_dpiを作成します。終了処理のないasm_hrb_apiだと思えばいいと思います。 _asm_hrb_dpi: ; STI ; 勝手にIF=1にしてはいけないかもしれないのでこれはつけない PUSH DS PUSH ES PUSHAD ; 保存のためのPUSH PUSHAD ; hrb_dpiにわたすためのPUSH MOV AX,SS MOV DS,AX ; OS用のセグメントをDSとESにも入れる MOV ES,AX CALL _hrb_dpi ADD ESP,32 POPAD POP ES POP DS IRETD -asm_hrb_api:の最初のSTIも外してください。割り込み処理中はSTIしてはいけないからです。STIが残っていると割り込み処理中はAPIが呼べないことになってしまいます。 -でも単にSTIを消すだけだと、今度はDPI/APIの呼び出し中は常にIF=0になって割り込み禁止になってしまいます。これはいけません。ということで、dsctbl.cを改造します。 *** dsctbl.c -init_gdtidt()をこんな風にします。 #define AR_TRPGATE32 0x8f (中略) set_gatedesc(idt + 0x40, (int) asm_hrb_api, 2 * 8, AR_TRPGATE32 + 0x60); set_gatedesc(idt + 0x41, (int) asm_hrb_dpi, 2 * 8, AR_TRPGATE32 + 0x60); (中略) *** console.c -cmd_app()を少しだけ書き換えます。これでHrDvも実行できるようになります。 if (appsiz >= 36 && (strncmp(p + 4, "Hari", 4) == 0 || strncmp(p + 4, "HrDv", 4) == 0) && *p == 0x00) { segsiz = *((int *) (p + 0x0000)); (中略) for (i = 0; i < datsiz; i++) { q[esp + i] = p[dathrb + i]; } if (strncmp(p + 4, "HrDv", 4) == 0) { io_store_eflags(0x00003202); /* IOPL=3 */ } start_app(0x1b, 0 * 8 + 4, esp, 1 * 8 + 4, &(task->tss.esp0)); io_store_eflags(0x00000202); /* IOPL=0 */ shtctl = (struct SHTCTL *) *((int *) 0x0fe4); -本当は拡張子とシグネチャが一致しているかどうかもチェックするべきです。ここではめんどくさいので省略。 -この改造だけだとコマンドラインからドライバを実行する(=組み込む)ときに拡張子の.hdvを省略できません。アプリみたいに拡張子を省略してもいいようにしたい人はそういう風に改造するといいでしょう。もしくは、stdrvコマンドとかを作って、"stdrv ドライバ名"って入力しないと起動しないようにしてもいいかもしれません。 *** console.c -hrd_dpi()を作ります。多くの部分がhrb_api()によく似ています。 void hrb_dpi(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax) { struct TASK *task = task_now(); int ds_base = task->ds_base; struct CONSOLE *cons = task->cons; struct FIFO32 *sys_fifo = (struct FIFO32 *) *((int *) 0x0fec); int *reg = &eax + 1; /* eaxの次の番地 */ /* 保存のためのPUSHADを強引に書き換える */ /* reg[0] : EDI, reg[1] : ESI, reg[2] : EBP, reg[3] : ESP */ /* reg[4] : EBX, reg[5] : EDX, reg[6] : ECX, reg[7] : EAX */ int i; struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR; /* ここでHrDvからじゃなければエラーにする処理を書くべき だけど今は手抜き */ if (edx == 1) { dpi_irq_table[ecx].func = eax; dpi_irq_table[ecx].esp = ebx; dpi_irq_table[ecx].task = task; /* 重複登録になっていないか確認したほうがいい */ } else if (edx == 2) { i = io_load_eflags(); io_cli(); reg[7] = fifo32_put(ecx, eax + 256); io_store_eflags(i); } else if (edx == 3) { reg[7] = (int) &task->fifo; } else if (edx == 4) { i = io_load_eflags(); io_cli(); reg[7] = fifo32_put(sys_fifo, eax + 256); io_store_eflags(i); } else if (edx == 5) { めんどくさくなってきたので省略 } return; } -こうするとdpi_irq_table[]関係の処理と、キー入力関係の処理を書き直す必要が出てきます。キー入力については、キーコードから文字コードに変換する処理をドライバにやらせることにしたいので、task_aを以下のように改造します。 *** bootpack.c -HariMain()の一部を書き換えます。 if (256 <= i && i <= 511) { /* キーボードデータ */ if (256 <= i && i <= 256 + 0xef && key_win != 0) { fifo32_put(&key_win->task->fifo, i); } else if (256 + 0xf0 <= i && i <= 256 + 0xf7) { /* Lock */ key_leds = i & 7; fifo32_put(&keycmd, KEYCMD_LED); fifo32_put(&keycmd, key_leds); } else if (i == 256 + 0xf8) { /* Tab */ if (key_win != 0) { keywin_off(key_win); j = key_win->height - 1; if (j == 0) { j = shtctl->top - 1; } key_win = shtctl->sheets[j]; keywin_on(key_win); } } else if (i == 256 + 0xf9) { /* Shift+F1 */ if (key_win != 0) { task = key_win->task; if (task != 0 && task->tss.ss0 != 0) { cons_putstr0(task->cons, "\nBreak(key) :\n"); io_cli(); /* 強制終了処理中にタスクが変わると困るから */ task->tss.eax = (int) &(task->tss.esp0); task->tss.eip = (int) asm_end_app; io_sti(); task_run(task, -1, 0); /* 終了処理を確実にやらせるために、寝ていたら起こす */ } } } else if (i == 256 + 0xfa) { /* Shift+F2 */ /* 新しく作ったコンソールを入力選択状態にする(そのほうが親切だよね?) */ if (key_win != 0) { keywin_off(key_win); } key_win = open_console(shtctl, memtotal); sheet_slide(key_win, 32, 4); sheet_updown(key_win, shtctl->top); keywin_on(key_win); } else if (i == 256 + 0xfb) { /* F11 */ sheet_updown(shtctl->sheets[1], shtctl->top - 1); } else if (i == 256 + 0xfc) { /* キーボードがデータを無事に受け取った */ keycmd_wait = -1; } else if (i == 256 + 0xfd) { /* キーボードがデータを無事に受け取れなかった */ wait_KBC_sendready(); io_out8(PORT_KEYDAT, keycmd_wait); } } else if (512 <= i && i <= 767) { /* マウスデータ */ *** bootpack.h -さて残るは、dpi_irq_table[]関係です。まずはbootpack.hで構造体宣言を書くことにします。 struct STR_DPI_IRQ_TABLE { struct TASK *task; int func, esp; }; extern struct STR_DPI_IRQ_TABLE dpi_irq_table[16]; *** int.c -そしてkeyboard.cのinthandler21()をint.cに引越しさせて、少々改造します。 struct STR_DPI_IRQ_TABLE dpi_irq_table[16]; void call_irq_driver(struct STR_DPI_IRQ_TABLE *table) /* IF=0で呼ぶこと */ { int old_esp0, old_ss0, old_ldtr; struct TSS32 *tss = &(table->task.tss); old_esp0 = tss->esp0; old_ss0 = tss->ss0; old_ldtr = load_ldtr(); store_ldtr(tss->ldtr); start_app(table->func, 4, table->esp, 12, &(tss->esp0)); load_ldtr(old_ldtr); tss->esp0 = old_esp0; tss->ss0 = old_ss0; return; } void inthandler21(int *esp) { if (dpi_irq_table[0x01].task != 0) { call_irq_driver(&dpi_irq_table[0x01]); } else { /* 処理先がないのでとりあえず空読みでもしておく */ io_out8(PIC0_OCW2, 0x61); /* IRQ-01受付完了をPICに通知 */ io_in8(PORT_KEYDAT); } return; } *** naskfunc.nas -int.cでLDTRの読み書き関数が必要になったので準備します。 _load_ldtr: ; int load_ldtr(void); MOV EAX,0 SLDT AX RET _store_ldtr: ; void store_cr0(int ldtr); LLDT [ESP+4] RET -これでOS側の改造は終わりです。 * こめんと欄 -コメントは親ページへ → [[advance/driver]]
タイムスタンプを変更しない
* デバイスドライバってどうやって作るの? -(by [[K]], 2008.03.21) -発展課題のページ(全部読む前にここを読むのは混乱するのでおすすめじゃないです) --このページは子ページです。親ページはこちら → [[advance/driver]] ---- -このページではデバイスドライバを使えるようにするための、OS本体の改造個所をまとめてあります。 *** naskfunc.nas -asm_hrb_dpiを作成します。終了処理のないasm_hrb_apiだと思えばいいと思います。 _asm_hrb_dpi: ; STI ; 勝手にIF=1にしてはいけないかもしれないのでこれはつけない PUSH DS PUSH ES PUSHAD ; 保存のためのPUSH PUSHAD ; hrb_dpiにわたすためのPUSH MOV AX,SS MOV DS,AX ; OS用のセグメントをDSとESにも入れる MOV ES,AX CALL _hrb_dpi ADD ESP,32 POPAD POP ES POP DS IRETD -asm_hrb_api:の最初のSTIも外してください。割り込み処理中はSTIしてはいけないからです。STIが残っていると割り込み処理中はAPIが呼べないことになってしまいます。 -でも単にSTIを消すだけだと、今度はDPI/APIの呼び出し中は常にIF=0になって割り込み禁止になってしまいます。これはいけません。ということで、dsctbl.cを改造します。 *** dsctbl.c -init_gdtidt()をこんな風にします。 #define AR_TRPGATE32 0x8f (中略) set_gatedesc(idt + 0x40, (int) asm_hrb_api, 2 * 8, AR_TRPGATE32 + 0x60); set_gatedesc(idt + 0x41, (int) asm_hrb_dpi, 2 * 8, AR_TRPGATE32 + 0x60); (中略) *** console.c -cmd_app()を少しだけ書き換えます。これでHrDvも実行できるようになります。 if (appsiz >= 36 && (strncmp(p + 4, "Hari", 4) == 0 || strncmp(p + 4, "HrDv", 4) == 0) && *p == 0x00) { segsiz = *((int *) (p + 0x0000)); (中略) for (i = 0; i < datsiz; i++) { q[esp + i] = p[dathrb + i]; } if (strncmp(p + 4, "HrDv", 4) == 0) { io_store_eflags(0x00003202); /* IOPL=3 */ } start_app(0x1b, 0 * 8 + 4, esp, 1 * 8 + 4, &(task->tss.esp0)); io_store_eflags(0x00000202); /* IOPL=0 */ shtctl = (struct SHTCTL *) *((int *) 0x0fe4); -本当は拡張子とシグネチャが一致しているかどうかもチェックするべきです。ここではめんどくさいので省略。 -この改造だけだとコマンドラインからドライバを実行する(=組み込む)ときに拡張子の.hdvを省略できません。アプリみたいに拡張子を省略してもいいようにしたい人はそういう風に改造するといいでしょう。もしくは、stdrvコマンドとかを作って、"stdrv ドライバ名"って入力しないと起動しないようにしてもいいかもしれません。 *** console.c -hrd_dpi()を作ります。多くの部分がhrb_api()によく似ています。 void hrb_dpi(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax) { struct TASK *task = task_now(); int ds_base = task->ds_base; struct CONSOLE *cons = task->cons; struct FIFO32 *sys_fifo = (struct FIFO32 *) *((int *) 0x0fec); int *reg = &eax + 1; /* eaxの次の番地 */ /* 保存のためのPUSHADを強引に書き換える */ /* reg[0] : EDI, reg[1] : ESI, reg[2] : EBP, reg[3] : ESP */ /* reg[4] : EBX, reg[5] : EDX, reg[6] : ECX, reg[7] : EAX */ int i; struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR; /* ここでHrDvからじゃなければエラーにする処理を書くべき だけど今は手抜き */ if (edx == 1) { dpi_irq_table[ecx].func = eax; dpi_irq_table[ecx].esp = ebx; dpi_irq_table[ecx].task = task; /* 重複登録になっていないか確認したほうがいい */ } else if (edx == 2) { i = io_load_eflags(); io_cli(); reg[7] = fifo32_put(ecx, eax + 256); io_store_eflags(i); } else if (edx == 3) { reg[7] = (int) &task->fifo; } else if (edx == 4) { i = io_load_eflags(); io_cli(); reg[7] = fifo32_put(sys_fifo, eax + 256); io_store_eflags(i); } else if (edx == 5) { めんどくさくなってきたので省略 } return; } -こうするとdpi_irq_table[]関係の処理と、キー入力関係の処理を書き直す必要が出てきます。キー入力については、キーコードから文字コードに変換する処理をドライバにやらせることにしたいので、task_aを以下のように改造します。 *** bootpack.c -HariMain()の一部を書き換えます。 if (256 <= i && i <= 511) { /* キーボードデータ */ if (256 <= i && i <= 256 + 0xef && key_win != 0) { fifo32_put(&key_win->task->fifo, i); } else if (256 + 0xf0 <= i && i <= 256 + 0xf7) { /* Lock */ key_leds = i & 7; fifo32_put(&keycmd, KEYCMD_LED); fifo32_put(&keycmd, key_leds); } else if (i == 256 + 0xf8) { /* Tab */ if (key_win != 0) { keywin_off(key_win); j = key_win->height - 1; if (j == 0) { j = shtctl->top - 1; } key_win = shtctl->sheets[j]; keywin_on(key_win); } } else if (i == 256 + 0xf9) { /* Shift+F1 */ if (key_win != 0) { task = key_win->task; if (task != 0 && task->tss.ss0 != 0) { cons_putstr0(task->cons, "\nBreak(key) :\n"); io_cli(); /* 強制終了処理中にタスクが変わると困るから */ task->tss.eax = (int) &(task->tss.esp0); task->tss.eip = (int) asm_end_app; io_sti(); task_run(task, -1, 0); /* 終了処理を確実にやらせるために、寝ていたら起こす */ } } } else if (i == 256 + 0xfa) { /* Shift+F2 */ /* 新しく作ったコンソールを入力選択状態にする(そのほうが親切だよね?) */ if (key_win != 0) { keywin_off(key_win); } key_win = open_console(shtctl, memtotal); sheet_slide(key_win, 32, 4); sheet_updown(key_win, shtctl->top); keywin_on(key_win); } else if (i == 256 + 0xfb) { /* F11 */ sheet_updown(shtctl->sheets[1], shtctl->top - 1); } else if (i == 256 + 0xfc) { /* キーボードがデータを無事に受け取った */ keycmd_wait = -1; } else if (i == 256 + 0xfd) { /* キーボードがデータを無事に受け取れなかった */ wait_KBC_sendready(); io_out8(PORT_KEYDAT, keycmd_wait); } } else if (512 <= i && i <= 767) { /* マウスデータ */ *** bootpack.h -さて残るは、dpi_irq_table[]関係です。まずはbootpack.hで構造体宣言を書くことにします。 struct STR_DPI_IRQ_TABLE { struct TASK *task; int func, esp; }; extern struct STR_DPI_IRQ_TABLE dpi_irq_table[16]; *** int.c -そしてkeyboard.cのinthandler21()をint.cに引越しさせて、少々改造します。 struct STR_DPI_IRQ_TABLE dpi_irq_table[16]; void call_irq_driver(struct STR_DPI_IRQ_TABLE *table) /* IF=0で呼ぶこと */ { int old_esp0, old_ss0, old_ldtr; struct TSS32 *tss = &(table->task.tss); old_esp0 = tss->esp0; old_ss0 = tss->ss0; old_ldtr = load_ldtr(); store_ldtr(tss->ldtr); start_app(table->func, 4, table->esp, 12, &(tss->esp0)); load_ldtr(old_ldtr); tss->esp0 = old_esp0; tss->ss0 = old_ss0; return; } void inthandler21(int *esp) { if (dpi_irq_table[0x01].task != 0) { call_irq_driver(&dpi_irq_table[0x01]); } else { /* 処理先がないのでとりあえず空読みでもしておく */ io_out8(PIC0_OCW2, 0x61); /* IRQ-01受付完了をPICに通知 */ io_in8(PORT_KEYDAT); } return; } *** naskfunc.nas -int.cでLDTRの読み書き関数が必要になったので準備します。 _load_ldtr: ; int load_ldtr(void); MOV EAX,0 SLDT AX RET _store_ldtr: ; void store_cr0(int ldtr); LLDT [ESP+4] RET -これでOS側の改造は終わりです。 * こめんと欄 -コメントは親ページへ → [[advance/driver]]
テキスト整形のルールを表示する