続 ES1370問題 解決

QEMU で virtio-net を有効にすると、なぜか ES1370(サウンドカード)の音質が悪くなる現象の原因がやっと分かった。


結論としては Mona の ES1370 ドライバの初期化処理が良くなかったようだ。
元のコードでは以下のように、コントロールレジスタからステータスを読み取り、そのステータスも含めてコントロールレジスタに書き込んで初期化している。

    ctrl = inp32(d->baseIO+ES1370_REG_CONTROL);
    ctrl |= ES1370_CDC_EN;
    ctrl &= ~ES1370_SERR_DISABLE;
    ctrl |= pclkdiv;
    outp32(d->baseIO+ES1370_REG_CONTROL, ctrl);


音質がおかしくなるときは、読み込まれたステータスが意味をなさない値なので、結果的に誤った初期化をしてしまっている。
FreeBSD の ES1370 ドライバを見ると以下のように初期化するのが良いみたい。

    ctrl = 0;
    ctrl |= ES1370_CDC_EN;
    ctrl &= ~ES1370_SERR_DISABLE;
    ctrl |= pclkdiv;
    outp32(d->baseIO+ES1370_REG_CONTROL, ctrl);

なぜ今までうまくいっていたか?

今まではおそらく読み出した値が *たまたま* 0 だったのだと思う。virtio-net を有効にする事で PCI のデバイスが増えたので QEMU 内での PCI 関連のメモリの使われ方が変わり、おかしな値を参照するようになったと。

どうやって調べたか?

QEMU の es1370.c の全ての関数の頭でログを吐いて、うまくいく場合と、そうでない場合のログを見比べて気づいた。何とも泥臭い。
これで uIP (ウェブサーバ)を動かしつつ音楽が聴ける。