FastTrakのドライバを静的リンク
(2006.01.24)
Linuxのカーネルから起動されるAmithlonはinitrd(=Init RAM Disk)の中にある/linuxrcというバイナリをカーネルから直接起動して初めて動作します。通常なら/linuxrcをnashのスクリプトにしてその中でモジュール化してあるFastTrakのドライバをロードするとプログラムを起動する際にはドライバが動作しているので間に合う訳です。カーネルソースを修正する以外に/linuxrcを起動する前にドライバをロードする方法がないのでカーネルに静的リンクして起動前に動作させておく必要があります。「おまえはもうロードされている。」(正しくは「おまえはもう死んでいる。」by ケンシロウ from 北斗の拳)といったところ。
PROMISE社が公開しているドライバはモジュールだけなので静的リンクできません。そこでモジュール用ドライバソースを入手して静的リンクできるように修正しました。FastTrakのドライバを静的リンクする必要はほとんどないハズですけれど私のようにどうしても必要な方のために説明します。
ドライバソースの入手先は
株式会社ゲメックス - SERVER THE BOX→ソフトウエア→FastTrak driver→gcc2かgcc3を選択してダウンロードです。展開したファイルはdrivers/scsi/ftに格納します。ftはFastTrakの略です。
Makefileを今風に作り直しました。特徴は末尾の2行でftlib.oはPROMISE社のソース非公開オブジェクトですからftlib_promise.oというファイルにコピーしてリンクします。ftlib.oをそのままリンクするように記述するとmakeがftlib.oを作成できなくて停止してしまいますのでftlib_promise.oをコピーすることで作成してもらえばmakeも納得です。
#
# drivers/scsi/ft/Makefile
#
# Makefile for the Linux FastTrak SCSI driver.
#
EXTRA_CFLAGS += -I$(TOPDIR)/drivers/scsi
O_TARGET := dummy.o
list-multi := ft.o
ft-objs := wrapper.o fasttrak.o ftlog.o ftlib_promise.o
obj-$(CONFIG_SCSI_FT) += ft.o
include $(TOPDIR)/Rules.make
ft.o: $(ft-objs)
$(LD) -r -o $@ $(ft-objs)
ftlib_promise.o: ftlib.o
cp ftlib.o ftlib_promise.o
カーネルへの静的リンクですからカーネルのmakeでここのドライバをコンパイルさせなくてはなりません。scsiのドライバは既にコンパイルさせるようになっていますから更にFastTrakのドライバをコンパイルさせるようdrivers/scsi/Makefileにftを追加します。追加位置がわかるように前後も含めてあります。
subdir-$(CONFIG_PCMCIA) += pcmcia
subdir-$(CONFIG_SCSI_FT) += ft
obj-$(CONFIG_SCSI) += scsi_mod.o
コンパイルの後はリンクです。drivers/scsi/Makefileにft.oを追加します。オブジェクトのリンク順に初期化関数が呼ばれるのでSCSIの基幹ドライバと各種の細かいドライバの間に挟みました。追加位置がわかるように前後も含めてあります。
ifeq ($(CONFIG_SCSI_AIC7XXX),y)
obj-$(CONFIG_SCSI_AIC7XXX) += aic7xxx/aic7xxx_drv.o
endif
ifeq ($(CONFIG_SCSI_FT),y)
obj-$(CONFIG_SCSI_FT) += ft/ft.o
endif
obj-$(CONFIG_SCSI_AIC7XXX_OLD) += aic7xxx_old.o
静的リンクしてみたけれどドライバが動作していなかったのでfasttrak.cを修正しました。ドライバの初期化関数init_fasttrakが#ifdef MODULE〜#endifで囲まれていて静的リンク時には消えてるので手直しを。__this_moduleは静的リンク時に未定義になってるので代入しないようにしました。(大丈夫か?)
Scsi_Host_Template driver_template = FASTTRAK;
#include
int init_fasttrak(void) {
#ifdef MODULE
driver_template.module = &__this_module;
#endif
scsi_register_module(MODULE_SCSI_HA, &driver_template);
if (driver_template.present) {
return 0;
}
free_pages((ulong)ENGINE,5);
free_pages((ulong)P_BVIR,1);
scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
return -1;
}
終了処理関数cleanup_fasttrakに特に気になる点はなくそのままにしてカーネルへの関数登録を今風なマクロに変更しました。この方法は静的リンクとモジュール化の両方に通用するそうです。ただしモジュールでのコンパイルは未確認です。
module_init(init_fasttrak);
module_exit(cleanup_fasttrak);
ドライバが無事に動作してAmithlonが起動されてAmigaが動作したのですけれど/proc/scsi/FastTrak/xが「P」しか出ません。改行すら出ないのでプロンプトの左に1文字ゴミが出てしまいました。おそらくPROMISEの1文字目が出て終わりになったと思います。そこで/procの正しい返し方を調査してfasttrak.cの関数fasttrak_proc_infoを作り直しました。ただし何回表示させても1回目と同一の表示しかしませんのでリビルド中の経過を見たい人はもっと改善してください。
int fasttrak_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int func)
{
static char FirstBuffer[512];
static int isFirst = 1;
static int procsize = 0;
if (isFirst)
{
ft_proc_t proc;
isFirst = 0;
proc.buffer = FirstBuffer;
proc.length = sizeof(FirstBuffer);
proc.offset = 0;
proc.position = 0;
GetProcInfo(&proc);
procsize = proc.position;
}
if (func == FALSE)
{
int i;
for (i = 0; i < procsize && i - offset < length; ++i)
{
if (0 <= i - offset)
{
buffer[i - offset] = FirstBuffer[i];
}
}
if (start)
{
*start = buffer;
}
return i - offset;
}
return 0;
}
修正したファイルを公開したかったんだけどPROMISE社のドライバソースはGNU LGPL(=GNU Lesser General Public License)になっていて「変更版もソフトウエアライブラリ」というのが再配布の条件みたいだから公開できません。ライブラリの体裁を用意できないので。残念。LGPLをご存知で公開のための面倒な作業をやってくれる方がいらっしゃれば更新したファイルを全部お渡しします。私はAmigaユーザであってLinuxユーザではないのでこれでおしまい。