メッセージ欄

2012年3月の日記

一覧で表示する

USBディスプレイ LCD-8000Uをudl(4)で使う (X Window System編)
2012/03/21(水) 16:06 NetBSD はてブ情報 はてブに登録 はてブ数

ZBOXを持ち出すときに小さなディスプレイがあると便利そうなのでCenturyのLCD-8000Uを購入しました。こいつはudl(4)で動くことが報告されているので安心です。

udlはすでにNetBSDに取り込まれているのでテキストコンソールであれば何もしなくても動くのだそうです。

ところが、i386では内臓のVGAがwsdisplay0で先に使われてしまい、あれこれ試してみたのですが、やり方がまずいらしく動かすことができませんでした。

ずいぶん前にudlを試したときにはうまく動いて満足したと記憶しているのですが、その時も確かテキストコンソールは試さず、Xが動いて喜んでいた気がします。

今回も、いっそのことX Window Systemを動かした方が楽なんじゃないかと思い、そっちに方針変更することにしました。

Xを動かすためには標準のNetBSDにいくつか修正が必要になります。基本的には、ふかうみさんのhttp://www.naobsd.org/udl/にあるものを使えば良いだけです。

修正点は大きく、kernelに対する修正とudl用のディスプレイドライバの追加になります。

kernelについては圧縮・展開を司るmicrocodeの追加とudlに対するioctlの追加です。

追加・修正説明
src/sys/dev/microcode/Makefileudlのmicrocodeを追加
src/sys/dev/microcode/udl新規追加するディレクトリ
src/sys/dev/microcode/udl/*ふかうみさんのkern.diffからそのまま
src/sys/dev/usb/Makefileioctlを定義したudlio.hの追加
src/sys/dev/usb/udl.c無効化されているioctlを有効化する定義を追加 (#define notyet 1)
src/sys/dev/usb/udlio.hioctlを定義したudlio.hの実体 (kern.diffより)

Xのドライバに関する修正はsrcとxsrcの両方に必要になります。

追加・修正説明
src/external/mit/xorg/server/drivers/Makefilexf86-video-wsudlの記述を追加
src/external/mit/xorg/server/drivers/xf86-video-wsudl新規作成
src/external/mit/xorg/server/drivers/xf86-video-wsudl/Makefileふかうみさんのsrc.diffそのまま
src/share/mk/bsd.own.mkwsudlの記述を追加

xsrc

追加・修正説明
xsrc/external/mit/xf86-video-wsudl新規追加
xsrc/external/mit/xf86-video-wsudl/*ふかうみさんのxsrc.diffをベースにwsudl_driver.cを少し修正
xsrc/external/mit/xorg-server/dist/hw/xfree86/os-support/bsd/bsd_init.cふかうみさんのxsrc.diffに含まれるパッチそのまま

基本はふかうみパッチベースで良いのですが、wsudl_driver.cについては最新のxsrcへの追従が必要でした。

--- wsudl_driver.c	2012-03-24 05:47:46.000000000 +0000
+++ wsudl_driver.c.new	2012-03-21 19:36:45.000000000 +0000
@@ -67,6 +67,7 @@
 
 #include "xf86.h"
 #include "xf86_OSproc.h"
+#include "xf86_OSlib.h"
 
 #include "mipointer.h"
 #include "mibstore.h"
@@ -76,8 +77,10 @@
 
 #include "fb.h"
 
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
 #include "xf86Resources.h"
 #include "xf86RAC.h"
+#endif
 
 #include "damage.h"
 
@@ -354,8 +357,10 @@
 
 	fPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
 
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
 	pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
 	pScrn->racIoFlags = pScrn->racMemFlags;
+#endif
 
 	/* open wsdisplay device */
 	dev = xf86FindOptionValue(fPtr->pEnt->device->options, "device");

上記の修正をhttp://www.tokuda.net/NetBSD/udl/6.99.3/にとりあえず置きました。パッチはバラバラでいまいちですけど。

アドホックに作業していたので、src/share/mk/bsd.own.mkの修正を入れ忘れて、ドライバ単体のコンパイル時に/configureなんて実行できねぇ、とか怒られたりしながらなんとかkernelとwsudl_drv.soを作ることができました。

openchromeドライバでの教訓をいかして、OBJディレクトリではlibwsudl_drv.soになっているのをwsudl_drv.soに忘れずリネームして/usr/X11R7/lib/modules/driversに置きます。

次のようなxorg.confを書いてstartxします。

Section "ServerLayout"
	Identifier     "X.org Configured"
	Screen      0  "Screen0" 0 0
	InputDevice    "Mouse0" "CorePointer"
	InputDevice    "Keyboard0" "CoreKeyboard"
EndSection

Section "Files"
	ModulePath   "/usr/X11R7/lib/modules"
	FontPath     "/usr/X11R7/lib/X11/fonts/misc/"
	FontPath     "/usr/X11R7/lib/X11/fonts/TTF/"
	FontPath     "/usr/X11R7/lib/X11/fonts/Type1/"
	FontPath     "/usr/X11R7/lib/X11/fonts/100dpi/"
	FontPath     "/usr/X11R7/lib/X11/fonts/75dpi/"
EndSection

Section "Module"
	Load  "dbe"
	Load  "dri"
	Load  "dri2"
	Load  "extmod"
	Load  "glx"
EndSection

Section "InputDevice"
	Identifier  "Keyboard0"
	Driver      "kbd"
	Option	    "Protocol" "wskbd"
	Option	    "Device" "/dev/wskbd"
EndSection

Section "InputDevice"
	Identifier  "Mouse0"
	Driver      "mouse"
	Option	    "Protocol" "wsmouse"
	Option	    "Device" "/dev/wsmouse"
EndSection

Section "Monitor"
	Identifier   "Monitor0"
	VendorName   "Monitor Vendor"
	ModelName    "Monitor Model"
EndSection

Section "Device"
	Identifier  "Card0"
	Driver      "wsudl"
	Option      "device" "/dev/wsdisplay1"
EndSection

Section "Screen"
	Identifier "Screen0"
	Device     "Card0"
	Monitor    "Monitor0"
	DefaultDepth 16
	SubSection "Display"
		Viewport   0 0
		Depth     16
	EndSubSection
EndSection

あれぇ、起動しません。

[    52.840] (EE) wsudl(0): We are not attached to the udl driver

こんなエラーを吐いてモジュールをアンロードするメッセージに続いています。

不思議に思いながらこのエラーメッセージでソースを追いかけてみます。

        /* open wsdisplay device */
        dev = xf86FindOptionValue(fPtr->pEnt->device->options, "device");
        fPtr->fd = wsudl_open(dev);
        if (fPtr->fd == -1)
                return (FALSE);

        /* check if we are attached to the right device driver */
        r = ioctl(fPtr->fd, WSDISPLAYIO_GTYPE, &wstype);
        if (r == -1) {
                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                    "ioctl WSDISPLAYIO_GTYPE: %s\n", strerror(errno));
                return (FALSE);
        }
        if (wstype != WSDISPLAY_TYPE_DL) {
                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                    "We are not attached to the udl driver\n");
                return (FALSE);
        }

うーん、なんだかなー、と思いながら上の方を見ると"device"という文字列が。

あー、そういえばxorg.confのOptionでdeviceを/dev/wsdisplay1に設定していたなー。

ん?! そういえば、http://www.naobsd.org/udl/README.txt

# cd /dev
# mknod -m 600 wsdisplay1 c wsdisplay 256
# mknod -m 600 wsdisplay1cfg c wsdisplay 511
# wsconscfg -f /dev/wsdisplay1cfg 0

って書いてあったけど、作ったっけ? ていうか、前に作ったけど起動するたびに消えちゃうんで困ってたんだったよなー。もしかしてデバイスをopenできないんじゃないの?

っていうことで、wsdisplay1とwsdisplay1cfgをmknodして、いざ、startx!

おー、ちゃんと動きましたぞ。

IMG_20120324_001517.jpg

残された課題としては、テキストコンソールはどうやるのか、/devにいつもwsdisplay1関連のデバイスが追加されるようにするにはどうするのか、があるので、少しづつ解決していきたいと思います。

ZBOX nano VD01でBluetoothを使う
2012/03/18(日) 28:50 NetBSD はてブ情報 はてブに登録 はてブ数

ZBOX nano VD01にはBluetoothが装備されているらしく、せっかくだから使ってみましょうと思い立ちました。

The NetBSD Guide Chapter 21 Bluetooth on NetBSDという文書を発見。

ほー、これは助かる。と思いつつ読みはじめて、まずデバイスを認識してなきゃ話になりませんなー、ということでubtがあるのか確認です。

...

ubtはありませんでした。なんだかな。うーんと思いつつbtで検索すると次のようなメッセージが。
aubtfwl0 at uhub3 port 1
aubtfwl0: ath3k-1.fw open fail 2
man aubtfwlしても何も出てきません。とはいえ、これまで見たこともないデバイス名ですし、なんだか気になるので調べてみるとどうやらAtherosのBluetoothのためのドライバのようです。おぉ、なんとかとっかかりを見つけることができたようです。

しかし、Atherosといえば無線LANとばかり思っていましたが、いわれてみればBluetoothも同じ無線ですからAtherosの製品があったとしても不思議ではないですね。

さて、どうやらaubtfwlはath3k-1.fwをファームウェアとして必要としているらしく、そのopenに失敗しているようです。

fail 2の2って何かといえばENOENTですからNo such file or directoryということのようです。確かにath3k-1.fwなんてファイルはシステムのどこにも存在しません。

じゃぁ、ath3k-1.fwはどこにあるのさ、と思って探してみるとhttp://git.kernel.org/?p=linux/kernel/git/firmware/linux-firmware.gitにあるようです。ここにあるLICENCE.atheros_firmwareを見て、今回の用途においては問題がないと判断したので、ここのath3k-1.fwを使わせてもらうことにしました。

では、どこにファームウェアを置けば良いのでしょう。
ファームウェアを開いている firmware_open -> firmware_path_first -> firmware_paths -> FIRMWARE_PATHS と追っかけていくと、
     75 #define	FIRMWARE_PATHS		\
     76 	"/libdata/firmware:/usr/libdata/firmware:/usr/pkg/libdata/firmware:/usr/pkg/libdata"
     77 #endif
という記述にたどり着きました。どうやらsysctlのhw.firmware.pathで見ればわかったようですね。しらんがな。

じゃぁ、/libdata/firmwareに置くことにしましょう。といって、どう置けば良いのでしょう。先のfirmware_path_firstからfirmware_path_nextに読み進めると、drvnameつまりドライバ名をディレクトリとしてファームウェアファイルを読み込むわけです。

今回だとdrvnameはaubtfwlですから/libdata/firmware/aubtfwl/ath3k-1.fwというファイルの置き方をすれば良いということになります。

あれ?

あいかわらず、
aubtfwl0: ath3k-1.fw open fail 2
のようです。

おっかしーな、と思ってもう一度aubtfwl.cを見てみると、
    104 	error = firmware_open("ubt", "ath3k-1.fw", &fwh); /* XXX revisit name */
なんと、ubtって書いてあるじゃないですか!!! 直接書くなよ。

あらためて、/libdata/firmware/ubt/ath3k-1.fwで起動してみると、
aubtfwl0 at uhub3 port 1
aubtfwl0: beginning firmware load
aubtfwl0: firmware load complete
aubtfwl0: detached
aubtfwl0: at uhub3 port 1 (addr 2) disconnected
aubtfwl0 at uhub3 port 1
aubtfwl0: beginning firmware load
aubtfwl0: firmware load complete
aubtfwl0: detached
aubtfwl0: at uhub3 port 1 (addr 2) disconnected
ubt0 at uhub3 port 1
ubt0: vendor 0x0cf3 product 0x3005, rev 1.10/0.01, addr 2
何度かaubtfwlがattachとdetachを繰り返して、見事ubt0が生えてきたのでありました。

やっとスタートラインに立てたようです。まずは、ここまで。

KOZOSの書き込みに使うkz_h8writeをNetBSDで動作させる
2012/03/18(日) 19:50 未分類 はてブ情報 はてブに登録 はてブ数

昨日、OSC2012 Tokyo springにてkozosのブースで作者の坂井さんとお話させていただきました。

リンカ・ローダ実践開発テクニックを2FのCQ出版社のブースで購入したので、サインをもらったりしました。例の魚の絵を描いてもらってうれしい。

それはそれとして、例のOS自作本を読み進める中でつまづくのは7章、8章と1章なのだそうです。7章、8章は内容的な難しさで1章は物理的なトラブルに起因する難しさだそうです。

つまり、シリアルをつかったボードとの通信ということですね。

坂井さんも秋月のUSBシリアルを貸し出したり、あれこれ工夫されているということですが、いざ自身のUSBシリアルでうまくいかなかったりと、作者すら巻き込んだ状態で困ったチャンということのようです。坂井さんの場合だとボードがヘタっているのかも疑わなければならないそうですから大変です。

このあたりのトラブルに巻き込まれて1章で挫折している人がたくさんいるのではないかとお話されていました。

ということで、例に漏れず、シリアル経由でボードに書き込めないトラブルに遭遇していたので、すこしその辺を記録しておきます。

まず、そもそもNetBSDで動かそうというところからして、想定環境とは違うのですが、まぁ、そこもふくめて楽しむのがホビーというものだろうと思いまして、あえてNetBSDで挑戦です。

自作本ではh8writeを使っていますが、イマドキはWebページも合わせて読み進めるのが常識でして、その辺の情報を見るかぎり、h8writeがだめだったらkz_h8writeを試してみてねという話になっていて、実装の確かさからkz_h8writeでがんばろうとしたようです。

したようです、と書いたのは理由があって、ずいぶん昔にはkz_h8writeでうまくいっていたのですが、長いブランクのあと試してみると、なぜかうまくいかないという事象にぶつかったからなのです。

で、技術がなければ根性で、をモットーにfprintfデバッグをしていたところ、どうやらシリアルポートを開いているところで止まっているみたいだなということがわかったので、man openして、待ってるんだから待たなきゃいいじゃん、ということでO_NONBLOCKを加え、NetBSDでは意味ないよとかかれているO_NOCTTYを削ってみると、うまく書き込みができるようになりました。
--- serial_linux.c.orig	2012-01-02 06:06:36.000000000 +0000
+++ serial_linux.c	2012-03-18 09:21:24.000000000 +0000
@@ -89,7 +89,7 @@
      * ポートを開く.
      */
     strcpy(s->devfile, devfile);
-    s->fd = open(devfile, O_RDWR | O_NOCTTY);
+    s->fd = open(devfile, O_RDWR | O_NONBLOCK);
     if (s->fd < 0) {
         free(s);
         return NULL;
という修正をしたのがkz_h8write 0.0.3です。

で、さっきWebをみるとgitリポジトリが公開されていることを発見しました。いまどきはgitなんですねぇ。

最新のserial_linux.cソースを見るとopenの引数にO_RDWR, O_NOCTTY, O_NDELAYが与えられています。

0.0.3には存在しなかったO_NDELAYがどうやら先ほどのO_NONBLOCKに相当するもののようですね。lxrで検索してちょろっと見るかぎり、x86ではO_NDELAYはO_NONBLOCKはまったく同じ定義、HP-UXでは別物として扱っていて、alphaはO_NONBLOCKしかなくて(なんでだろ)、sparcでも微妙に扱いを変えているみたいです。

ちなみにPOSIX.1-2008のopenをみるとO_NONBLOCKしか見当たらないので、ポータビリティの観点とx86の実装の観点からもO_NONBLOCKのほうが無難かなと思ったりする次第。

NetBSDではO_NOCTTYは無視されてO_NONBLOCKが有効に動くので上のようなパッチもいらないですね。

ZBOX nano VD01のHDDが遅い (4)
2012/03/10(土) 22:09 NetBSD はてブ情報 はてブに登録 はてブ数

さらにtsutsuiさんからdmesgのwd0が表示する内容でUDMAに関する表示が出ているはずなので確認してみてはどうか、というアドバイスを頂いたので早速確認。

まずは、UDMA 0 (sc->sc_wdcdev.sc_atac.atac_udma_cap = 0) です。
wd0 at atabus0 drive 0
wd0: <WDC WD1600BEVT-24A23T0>
wd0: drive supports 16-sector PIO transfers, LBA48 addressing
wd0: 149 GB, 310101 cyl, 16 head, 63 sec, 512 bytes/sect x 312581808 sectors
wd0: 32-bit data port
wd0: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 6 (Ultra/133)
wd0(viaide0:0:0): using PIO mode 4, DMA mode 2 (using DMA)
次はUDMA 6 (sc->sc_wdcdev.sc_atac.atac_udma_cap = 6) の場合です。
wd0 at atabus0 drive 0
wd0: <WDC WD1600BEVT-24A23T0>
wd0: drive supports 16-sector PIO transfers, LBA48 addressing
wd0: 149 GB, 310101 cyl, 16 head, 63 sec, 512 bytes/sect x 312581808 sectors
wd0: 32-bit data port
wd0: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 6 (Ultra/133)
wd0(viaide0:0:0): using PIO mode 4, Ultra-DMA mode 6 (Ultra/133) (using DMA)
ほとんど同じですが、最後の行が違いますね。比べてみましょう。
UDMAメッセージ
0wd0(viaide0:0:0): using PIO mode 4, DMA mode 2 (using DMA)
6wd0(viaide0:0:0): using PIO mode 4, Ultra-DMA mode 6 (Ultra/133) (using DMA)
なるほど。たしかに、変わっていますね。

これで/sys/dev/pci/viaide.c#604
    602 	sc->sc_wdcdev.sc_atac.atac_pio_cap = 4;
    603 	sc->sc_wdcdev.sc_atac.atac_dma_cap = 2;
    604 	sc->sc_wdcdev.sc_atac.atac_set_modes = via_setup_channel;
    605 	sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
    606 	sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS;
から/sys/dev/pci/viaide.c#via_setup_channelが呼ばれ、759行目でUDMA 6としての設定をレジスタにセットしているようですね。
    753 			case PCI_VENDOR_VIATECH:
    754 				if (sc->sc_wdcdev.sc_atac.atac_udma_cap == 6) {
    755 					/* 8233a */
    756 					udmatim_reg |= APO_UDMA_TIME(
    757 					    chp->ch_channel,
    758 					    drive,
    759 					    via_udma133_tim[drvp->UDMA_mode]);
    760 				} else if (sc->sc_wdcdev.sc_atac.atac_udma_cap == 5) {
via_udma133_timって何かと見てみると/sys/dev/pci/pciide_apollo_reg.h#149に次のように書かれています。
    149 static const int8_t via_udma133_tim[] __unused =
    150     {0x07, 0x07, 0x06, 0x04, 0x02, 0x01, 0x00};
先のdmesgのとおりdrvp->UDMA_modeは6ですから、えーと、0x00が設定されるってことですね。

うーん、この辺までくると、さっぱり中身がわからなくなってきしたが、何となくUDMAが6での転送に失敗したらUDMA 5に落とされて0x01が使われて... といったfall backに使われるんでしょうかねぇ。

ということで、ドライバとしてもUDMAのモードを意識した実装だということがわかった (ような気がする) ので、すっきりしました。

話は変わりますが、http://nxr.netbsd.orgってほんと便利ですよね。

ZBOX nano VD01のHDDが遅い (3)
2012/03/10(土) 15:00 NetBSD はてブ情報 はてブに登録 はてブ数

前回の日記を書いて、さらにtsutsuiさんからコメントを頂きました。

どうやら、昔のVIAチップの設計がイマイチで、それを回避するコードが入っていたそうです。

最近のVIAチップはそういう回避コードは不要になっているにもかかわらず、回避コードの下に慣習的に各々のVIA IDE個別の設定が追加されていったようです。

今回のケースではその回避コードが逆に悪さをしてうまく動いていないということですね。むしろ、最近のチップがちゃんと動いているのか心配になってしまいます。

じゃぁ、回避コードのルートに乗っかる前に、さっさと処理をしてしまえばよいということで、次のような修正を加えることにしました。
--- ./sys/dev/pci/viaide.c.orig 2011-12-29 05:25:40.000000000 +0000
+++ ./sys/dev/pci/viaide.c      2012-03-10 12:43:07.00000000
@@ -464,6 +469,11 @@
                        interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
                            PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
                        break;
+               case PCI_PRODUCT_VIATECH_VX900_IDE:
+                       aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev,
+                           "VIA Technologies VX900 ATA133 controller\n");
+                       sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
+                       break;
                default:
                        /*
                         * get a PCI tag for the ISA bridge.
起動すると期待どおりのメッセージが表示されました。
viaide0 at pci0 dev 15 function 0
viaide0: VIA Technologies VX900 ATA133 controller
viaide0: bus-master DMA support present
viaide0: primary channel configured to native-PCI mode
viaide0: using ioapic0 pin 21 for native-PCI interrupt
atabus0 at viaide0 channel 0
viaide0: secondary channel configured to native-PCI mode
atabus1 at viaide0 channel 1
やりましたね!

それでは、dbenchしてみましょう!
Throughput 60.1017 MB/sec 5 procs
あれ?! おかしいな。もう一回。
Throughput 62.8053 MB/sec 5 procs
おっ! 先ほどよりは良くなりましたね。って言っても前回の不完全パッチでも
Throughput 63.8846 MB/sec 5 procs
ということで、数値的にはほとんど変わらないという結果になりました。

dbehcnの数字が60MB/s程度だとして、これが何を意味するのかは他の結果と比較してみなければなりませんが、とても乱暴にUDMA 4 (66MB/s) 相当の速度と仮置きしておくことにしましょう。

せっかくUDMAを0から6にしたのに効果は得られていないようです。おかしいですね。

仮説としては三つくらいでしょうか。
  • 不完全パッチでもUDMA 0ではなくUDMA 4相当が使われていた
  • 今回の修正でもまだ不十分でUDMA 4相当で動いている
  • 実はちゃんと動いているけどdbenchがかけるワークロードではUDMAの差が数字として現れない
仮説の最初の二つを考える上で気になっているのは、VX900のSATAコントローラを使っているにもかかわらず、viaideドライバ上ではPATAとして処理されているっぽいというところです。OpenBSDでもPATAとして扱われているので、そういうもの、なのかもしれませんが気になってしまいます。

SATAコントローラがPATAコンパチモードで動くとUDMAの指定はともかく、そこそこの速度で動いてくれるという動作なのかもしれません。

じゃぁ、SATAで動かせばいいじゃないかという話になるのですが、実は試行錯誤をしていた段階で
        { PCI_PRODUCT_VIATECH_VX900_IDE,
          0,
          NULL,
          via_chip_map,
        },
のところを
          via_sata_chip_map_7,
にして動かしてみたのですが、起動時にpanicしてそれ以降深く追っかけていなかったのです。せっかくのSATAコントローラなのですからSATAで動かしたいものですね。

三つ目の仮説であるdbenchどうなの、という話は確かにあって、ベンチマークプログラムの選択はなかなか奥が深いですね。

このようなディスクの話であればiozoneが良いのではないかとお勧めされたりしているのですが、iozoneのオプションを見て、そっと閉じる、という情けない状態だったりします。

いくつか宿題は残っていますが、一定の結論がでたのでsend-prに向けて準備を進めたいと思います。

1: tsutsui 『dmesgのドライブ側の行で wd0: drive supports PIO mode 4, DMA mode 2, Ultra...』 (2012/03/10 15:53)