昔作ったサインはVGAのLinuxカーネルパッチを供養する


はじめに

その昔、NAS組み立てキットの玄箱HGがあり、有志のDebian化キットで普通のLinuxとして動作しました。玄箱HGはディスプレイ出力端子がないのでリモート接続しかできなかったのですが同じ時期にUSBをVGA出力に変換するサインはVGAが出たのでこの2つを組み合わせてデスクトップPC化を目指したのでした。

何が問題だったのか

サインはVGAが出た時は既にsisusbとしてLinuxドライバがあったのですが、以下の問題により動作しませんでした。

  1. 複数のデバイスIDに未対応
  2. ppc(big endian)未対応

1つ目は製品のカラーバリエーションでデバイスIDが異なり、ドライバに定義されていないものは認識されません。
2つ目は玄箱HGのCPUはppcでbig endianなのでデータの格納順番が異なり正常にディスプレイ表示できません。

2つ目はどうやって見付けたのか忘れてしまったのですがグラフィックドライバなのでprintkとカーネルログだけで調べた記憶があります。

パッチ本体

パッチ対象のカーネルはDebian/etchの2.6.18-rc4です。
これでコンソールとX Window Systemは表示されたのですが一部のカラーモードで表示がおかしかったので不完全かXのドライバにも問題あったのかもしれません。

diff -ru a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
--- a/drivers/usb/misc/sisusbvga/sisusb.c   2006-07-30 15:15:36.000000000 +0900
+++ b/drivers/usb/misc/sisusbvga/sisusb.c   2006-07-31 00:08:10.000000000 +0900
@@ -76,6 +76,16 @@

 DEFINE_MUTEX(disconnect_mutex);

+#ifdef __BIG_ENDIAN
+static void
+correct_endianness_buffer(u16* data, const int length)
+{
+   int i;
+   for (i = 0; i < length; i++)
+       *(data+i) = cpu_to_le16(*(data+i));
+}
+#endif
+
 static void
 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
 {
@@ -411,6 +421,10 @@
            memcpy(buffer, kernbuffer, passsize);
            kernbuffer += passsize;

+#ifdef __BIG_ENDIAN
+           if ((len & 3) == 0)
+               correct_endianness_buffer((u16 *)buffer, thispass/2);
+#endif
        }

        retry = 5;
@@ -906,9 +920,13 @@
            if (userbuffer) {
                if (get_user(swap32, (u32 __user *)userbuffer))
                    return -EFAULT;
-           } else
+           } else {
                swap32 = *((u32 *)kernbuffer);

+#ifdef __BIG_ENDIAN
+               swap32 = ((swap32 << 16) & 0xffff0000) | ((swap32 >> 16) & 0xffff);
+#endif
+           }
            ret = sisusb_write_memio_long(sisusb,
                            SISUSB_TYPE_MEM,
                            addr,
@@ -1259,7 +1277,11 @@

                    userbuffer += 4;
                } else {
+#ifdef __BIG_ENDIAN
+                   *((u32 *)kernbuffer) = ((swap32 << 16) & 0xffff0000) | ((swap32 >> 16) & 0xffff);
+#else
                    *((u32 *)kernbuffer) = swap32;
+#endif
                    kernbuffer += 4;
                }
                addr += 4;
@@ -3435,6 +3457,9 @@

 static struct usb_device_id sisusb_table [] = {
    { USB_DEVICE(0x0711, 0x0900) },
+   { USB_DEVICE(0x0711, 0x0901) },
+   { USB_DEVICE(0x0711, 0x0902) },
+   { USB_DEVICE(0x0711, 0x0920) },
    { USB_DEVICE(0x182d, 0x021c) },
    { USB_DEVICE(0x182d, 0x0269) },
    { }

玄箱HGとサインはVGAでコンソール出力したもの

リンク