090320

|



まったりと車体を組み中。ちょこっと作業してはマクガイバー見たり、ちょう
どamazonで注文しておいたマイアミバイスがやってきたので、まだそれを見て
で進まない。

マイアミバイスは実は見たことがない。ちょこっと見たことはあるのだけれど、 居間のテレビで見るにはちょっと刺激が強いシーンも多いので、見れなかった ^^。
残念なことに、今回僕が買ったマイアミバイスは吹き替えがなかった。それに これレンタル用だし。
VIPPER刑事物語 やる夫とやらない夫 」このやる夫 版は、原作を噛みくだいた上で、ストーリーに乗りながら、いいアレンジでと てもいい。というか、こっちの方がストーリーとしては好きかな。日本人向け なのか。
あと「ダウリング神父」がもう一度見たい。残念ながらDVD化されてないようだ。 シスター・ステファニー、好きだったんだ。神父の下の男が吹き替えだと、確 か美味しんぼの富井副部長。ネーティブの声は結構渋くてギャップがすごかっ たのが忘れられない。

それはともかく。フォークオイルが真っ黒でした。あれ...なんでだと思ったら、 前にフォークをバラしたのは予備のフォークで(10月)、このフォークは去年の 8月以来だった。お恥かしい...。

x86続き。
嫌なバグに悩まされた。0x0:0x8000に二段目をロードした後、メモリが破壊
されるのだ。つきとめていったところ、スタックの設定を間違えていた。
今迄
	movw	_stack_start,	%sp
になっていた。これでは_stack_startのアドレスにある値がspになってしまう。
	movw	$_stack_start,	%sp
じゃないといけなかった。_stack_startはldscriptで設定。
偶然、_stack_startには0xfff6が入っていたので、そこそこ動いていた。
リアルモードなら16bitだし、0xfff6でも動きそうなものだけど、どうも4byte
アラインじゃないとだめみたい。

昨日のような実験を元に保護モードのデスクリプタの設定は普通に設定して
先に進めます。ベースは0から。スタックセグメントもデータセグメントと
同じ設定で。

保護モードに入ってしまうと、そのままBIOSコールは呼びだせない(BIOSはリア
ルモードで呼ばれるのを前提としているので)。なのでデバッグ用にprintfを作
りました。これはH8で作ったやつをコピペで。

やっとA20のテスト。QEMUはデフォルトでA20は有効なので何もすることがない。
ので、あえて無効にしてテスト。

#define	inb(addr, val)	__asm volatile \
("inb %1, %0" : "=a"(val) : "d"((uint16_t)addr))
#define	outb(addr, val)	__asm volatile \
("outb %0, %1" :: "a"((uint8_t)val), "d"((uint16_t)addr))

x86はオペランドにレジスタの制限があるのでgasでもコンストレイントを
指定できるようになっている。幅はキャストで効く。

void
a20_test ()
{
  uint32_t m0, m1;

  uint8_t r0;
  // make sure that i/o buffer is empty.
  do
    {
      inb (0x60, r0);	// drain buffer
      inb (0x64, r0);	// get status
    }
  while (r0 & 0x01);	// output(i8042) buffer full
  do
    {
      inb (0x64, r0);
    }
  while (r0 & 0x02);	// input(i8042) Buffer Full

  outb (0x64, 0xd0);	// output port read command.
  inb (0x60, r0);	// read output port.

  printf1 ("i8042 output port:%x\n", r0);

  outb(0x64, 0xd1); // output port write command.
  outb(0x60, 0x01); // write to output port.	ここでA20を無効に。
  // bit 0 ... RESET if set 0.
  // bit 1 ... A20 disabled if set 0.

  printf1 ("%x\n", r0);

  // 0x200なのはリアルモードの割り込みハンドラのその先を設定。一応。
  m0 = *(uint32_t *)0x200;

  //A20が無効なら、この操作で0x200も書き変わるはず。
  *(uint32_t *)((1 << 20) + 0x200) = m0 ^ 0xa5a5a5a5;
  //  __asm volatile ("wbinvd");

  m1 = *(uint32_t *)0x200;

  printf1 ("%x %x\n", m0, m1);
  if (m1 != m0)
    {
      printf1 ("A20 disabled\n");これが表示されればA20は無効だ。
      *(uint32_t *)0x200 = m0;	// restore.
    }
  else
    {
      printf1 ("A20 enabled\n");
    }

}

これでA20のスイッチをテスト。これはQEMU上では想定通りの動き。これを
ML115 G5の実機で動かしてみたところ、A20は有効のままだった。

さすがに今はもうこのあたりは削ったようだ。