ide.c static int idewait(int checkerr)

トップページ
jupiteroak.hatenablog.com


ide.c
https://github.com/mit-pdos/xv6-public/blob/master/ide.c#L38

static int idewait(int checkerr)
{
  int r;

  while(((r = inb(0x1f7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY)
    ;
  if(checkerr && (r & (IDE_DF|IDE_ERR)) != 0)
    return -1;
  return 0;
}

idewait関数は、ハードディスクが使用できる状態であることを確認します。

引数 int checkerr
検出したいエラーの種類を指定します。
ハードディスクドライブの障害エラーを検出したい場合、checkerrの値は0b 0010 0000を指定します。
その他のエラーを検出したい場合、checkerrの値は0b 0000 0001を指定します。

戻り値 0 または -1
ハードディスクの準備に問題がない場合は、0が戻り値となります。
引数で指定したエラーが検出された場合は、-1が戻り値となります。


処理の内容 

ハードディスクドライブがスピンダウンやエラーを起こしていないことを確認する

while(((r = inb(0x1f7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY)

in命令(ポート入力命令)でI/Oポートアドレス0x1f7を指定することにより、ハードディスクコントローラが持つStatus Registerの値(8bit)を読み取っています。
Status Registerは、現在のハードディスクドライブの状態を示しているレジスタです。
読み取った値を IDE_BSY | IDE_DRDY (0xC0 = 0b1100 0000)でマスク処理することにより、Status Registerのbit7(BSYフラグ)とbit6(RDYフラグ)の値を取り出しています。
((r = inb(0x1f7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY が偽となる場合→取り出した値(0b xx00 0000)がIDE_DRDY(0x40 = 0b 0100 0000)と同じ場合→Status Registerのbit7(BSYフラグ)に1がセットされていない、かつ、Status Registerのbit6(RDYフラグ)に1がセットされている場合は、whileループから脱出して次の処理に進みます。Status Registerのbit6(RDYフラグ)に1がセットされている時は、ハードディスクドライブがスピンダウンやエラーを起こしていないことを意味しています。
((r = inb(0x1f7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY が真となる場合→取り出した値(0b xx00 0000)がIDE_DRDY(0x40 = 0b 0100 0000)と異なる場合→Status Registerのbit7(BSYフラグ)に1がセットされている場合は、whileループを繰り返します。Status Registerのbit7(BSYフラグ)に1がセットされている時は、Status Registerのbit6(RDYフラグ)に1がセットされていても意味をなしません。

ハードディスクドライブのエラーを検出する

if(checkerr && (r & (IDE_DF|IDE_ERR)) != 0)
    return -1;
return 0;

読み取ったStatus Registerの値rをIDE_DF | IDE_ERR(#define IDE_DF 0x20 #define IDE_ERR 0x01)でマスク処理することにより、Status Registerのbit5(DFフラグ)とbit0(ERRフラグ)の値を取り出しています。
Status Registerのbit5(DFフラグ)が1にセットされている時は、ハードディスクドライブの障害エラーが生じたことを意味します。
Status Registerのbit0(ERRフラグ)が1にセットされている時は、その他のエラーが生じたことを意味します。

checkerr && (r & (IDE_DF|IDE_ERR)) != 0 が偽となる場合は、if文内の処理に入らず、0を戻り値としてリターンします。
checkerr && (r & (IDE_DF|IDE_ERR)) != 0 が偽となる場合は、以下の4通りになります。

①checkerrが0
ハードディスクドライブの障害エラーも、その他のエラーも、検出しないように指定している。

②checkerrが0b 0001 0000 かつ Status Registerのbit5(DFフラグ)が0
ハードディスクドライブの障害エラーだけを検出しようとして、ハードディスクドライブの障害エラーが生じていない。

③checkerrが0b 0000 0001 かつ Status Registerのbit0(ERRフラグ)が0
その他のエラーだけを検出しようとして、その他のエラーが生じていない

④checkerrが0b 0001 0001 かつ Status Registerのbit5(DFフラグ)が0 かつ Status Registerのbit0(ERRフラグ)が0
ハードディスクドライブの障害エラーとその他のエラーを検出しようとして、ハードディスクドライブの障害エラーも、その他のエラーも、生じていない


checkerr && (r & (IDE_DF|IDE_ERR)) != 0 が真となる場合は、if文内の処理に入って、-1を戻り値として処理を終了します。
checkerr && (r & (IDE_DF|IDE_ERR)) != 0 が真となる場合は、以下の3通りになります。

①checkerrが0b 0001 0000 かつ Status Registerのbit5(DFフラグ)が1
ハードディスクドライブの障害エラーだけを検出しようとして、ハードディスクドライブの障害エラーが生じた。

②checkerrが0b 0000 0001 かつ Status Registerのbit0(ERRフラグ)が1
その他のエラーだけを検出しようとして、その他のエラーが生じた。

③checkerrが0b 0001 0001 かつ (Status Registerのbit5(DFフラグ)が1 または Status Registerのbit0(ERRフラグ)が1)
ハードディスクドライブの障害エラーとその他のエラーを検出しようとして、ハードディスクドライブの障害エラーが生じた、または、その他のエラーが生じた。