続 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 (ウェブサーバ)を動かしつつ音楽が聴ける。