5.18. ideinit関数
この関数ではIDEの割り込みの有効化と、ディスク1の存在確認を行う。
ide.cに宣言されている静的なint型の変数havedisk1が、ディスク1の有無を示すフラグとなっており、値が1場合にディスク1があることを示す。
IDEからの割り込みをioapicenable関数で有効化する。 IRQ番号は「OSDev Interrupt」(リンク29)の表「Standard ISA IRQs」をによると、14番がPrimary ATA Hard Disk、と15番がSecondary ATA Hard Diskとなっている。 ここでは14番(IRQ_IDE)からの割り込みを有効化する。 割り込み先はcpuid(LAPIC ID)が最も大きいcpuに設定する。 cpu数を示す大域変数ncpuはmpinit関数で設定した。
idewait関数でディスク0がビジーでもエラーでもなくなるまで待つ。
ディスク1の有無を確認するために、読み書きを行うディスクをディスク1に切り替える。
「OSDev ATA PIO Mode」(リンク23)によると、IDEコントローラのdrive/headレジスタ(0x1f6)の4bitを1にすることでディスク1に切り替えられる。
また、5~7bitは101で固定のようだが、ここでは0xe0で全て1に設定している。
ディスク1のステータスレジスタ(0x1f7)から0以外の値が読み取れるまで、for文で1000回ループする。
エラーになっていようがレディになっていようがとりあえず0以外が返ってくればディスク1が存在することは確認できる。
ディスク1の存在確認完了後、読み書きするディスクをディスク0に戻す。
traps.h
#define IRQ_IDE 14
ide.c
static int havedisk1;
/* 略 */
void
ideinit(void)
{
int i;
initlock(&idelock, "ide");
ioapicenable(IRQ_IDE, ncpu - 1);
idewait(0);
// Check if disk 1 is present
outb(0x1f6, 0xe0 | (1<<4));
for(i=0; i<1000; i++){
if(inb(0x1f7) != 0){
havedisk1 = 1;
break;
}
}
// Switch back to disk 0.
outb(0x1f6, 0xe0 | (0<<4));
}