このページは「24環境」の情報です

第4回 Linux-2.4.19を使おう

海老原祐太郎
2002/8/17

2002年8月現在の安定版最新カーネル 2.4.19 を使ってみます。
テーマとして irq_demux() を外す改造にも取り組みます。

ダウンロード

カーネルソース linux-2.4.19 は近くの ftp.kernel.org からダウンロードします。

ftp://ftp.kernel.org/pub/linux/kernel/v2.4/linux-2.4.19.tar.gz (32,219,641 bytes)

GNUツールズ

本稿を書いているときは以下のパッケージを利用しました

ftp://ftp.m17n.org/pub/dodes/debian/crosstools/
gcc-sh3-linux_3.0.3-dodes.2_i386.deb
binutils-sh3-linux_0.dodes.20011207-1_i386.deb

# dpkg -i gcc-sh3-linux_3.0.3-dodes.2_i386.deb
# dpkg -i binutils-sh3-linux_0.dodes.20011207-1_i386.deb

クロスコンパイラを利用して開発機にてクロスでコンパイルを行います。
筆者はDebian Woody / Intel Celeron 466 x2 マシンにて開発を行っています。

カーネルへの改造

適当な作業ディレクトリでカーネルを展開します。

$ tar xzfv /どこか/linux-2.4.19.tar.gz
$ cd linux-2.4.19

以下の2個のパッチを当てます。
パッチが読める人は何をやっているかわかると思います。
せっかくですからパッチが読めるようになっておきましょう。
先頭行−印は、その行を削除。+印はその行を追加です。これだけわかっていれば十分です。

kernelpatch_2.4.19_sh.diff

diff -urN linux-2.4.19/Makefile linux-2.4.19-cat68701/Makefile
--- linux-2.4.19/Makefile Sat Aug 3 09:39:46 2002
+++ linux-2.4.19-cat68701/Makefile Tue Aug 13 21:59:08 2002
@@ -5,7 +5,8 @@

KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)

-ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
+#ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
+ARCH=sh
KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g")

CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
@@ -19,7 +20,7 @@
HOSTCC = gcc
HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer

-CROSS_COMPILE =
+CROSS_COMPILE = sh3-linux-

#
# Include the make variables (CC, etc...)
@@ -78,6 +79,7 @@
# relocations required by build roots. This is not defined in the
# makefile but the arguement can be passed to make if needed.
#
+INSTALL_MOD_PATH=/mnt

MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB
diff -urN linux-2.4.19/include/asm-sh/mc146818rtc.h linux-2.4.19-cat68701/include/asm-sh/mc146818rtc.h
--- linux-2.4.19/include/asm-sh/mc146818rtc.h Thu Jun 28 05:55:29 2001
+++ linux-2.4.19-cat68701/include/asm-sh/mc146818rtc.h Tue Aug 13 22:37:11 2002
@@ -5,12 +5,9 @@
#define _ASM_MC146818RTC_H

#include <asm/rtc.h>
+#include <asm/irq.h>

#define RTC_ALWAYS_BCD 1
-
-/* FIXME:RTC Interrupt feature is not implemented yet. */
-#undef RTC_IRQ
-#define RTC_IRQ 0

#if defined(__sh3__)
#define RTC_PORT(n) (R64CNT+(n)*2)
diff -urN linux-2.4.19/include/asm-sh/page.h linux-2.4.19-cat68701/include/asm-sh/page.h
--- linux-2.4.19/include/asm-sh/page.h Sun Sep 9 04:29:09 2001
+++ linux-2.4.19-cat68701/include/asm-sh/page.h Tue Aug 13 22:10:17 2002
@@ -87,6 +87,8 @@
#endif

#define virt_to_page(kaddr) phys_to_page(__pa(kaddr))
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)

#ifndef __ASSEMBLY__

diff -urN linux-2.4.19/include/asm-sh/segment.h linux-2.4.19- cat68701/include/asm-sh/segment.h
--- linux-2.4.19/include/asm-sh/segment.h Thu Jan 1 09:00:00 1970
+++ linux-2.4.19-cat68701/include/asm-sh/segment.h Tue Aug 13 22:06:45 2002
@@ -0,0 +1,6 @@
+#ifndef _ASM_SEGMENT_H
+#define _ASM_SEGMENT_H
+
+/* Only here because we have some old header files that expect it.. */
+
+#endif /* _ASM_SEGMENT_H */

kernelpatch_2.4.19_cat68701.diff

diff -urN linux-2.4.19/arch/sh/kernel/io_cat68701.c linux-2.4.19-cat68701/arch/sh/kernel/io_cat68701.c
--- linux-2.4.19/arch/sh/kernel/io_cat68701.c Mon May 21 04:11:38 2001
+++ linux-2.4.19-cat68701/arch/sh/kernel/io_cat68701.c Tue Aug 13 22:00:17 2002
@@ -181,12 +181,10 @@
{
return (void *) P2SEGADDR(offset);
}
-EXPORT_SYMBOL(cat68701_ioremap);

void cat68701_iounmap(void *addr)
{
}
-EXPORT_SYMBOL(cat68701_iounmap);

unsigned long cat68701_isa_port2addr(unsigned long offset)
{
@@ -205,16 +203,6 @@
return offset + 0xb4000000; /* other I/O (EREA 5)*/
} 

-
-int cat68701_irq_demux(int irq)
-{
- if(irq==13) return 14;
- if(irq==7) return 10;
- return irq;
-}
-
-
-
/*-------------------------------------------------------*/

void setup_cat68701(){
@@ -222,8 +210,8 @@
}

void init_cat68701_IRQ(){
- make_imask_irq(10);
- make_imask_irq(14);
+ make_imask_irq(7); /* CS8900 */
+ make_imask_irq(13); /* CompactFlash(IDE) */
}

#ifdef CONFIG_HEARTBEAT
diff -urN linux-2.4.19/arch/sh/kernel/mach_cat68701.c linux-2.4.19-cat68701/arch/sh/kernel/mach_cat68701
.c
--- linux-2.4.19/arch/sh/kernel/mach_cat68701.c Thu Apr 12 13:24:52 2001
+++ linux-2.4.19-cat68701/arch/sh/kernel/mach_cat68701.c Tue Aug 13 22:00:33  2002
@@ -57,7 +57,6 @@
mv_iounmap: cat68701_iounmap,

mv_isa_port2addr: cat68701_isa_port2addr,
- mv_irq_demux: cat68701_irq_demux,

mv_init_arch: setup_cat68701,
mv_init_irq: init_cat68701_IRQ,
diff -urN linux-2.4.19/drivers/ide/ide.c linux-2.4.19-cat68701/drivers/ide/ide.c
--- linux-2.4.19/drivers/ide/ide.c Sat Aug 3 09:39:44 2002
+++ linux-2.4.19-cat68701/drivers/ide/ide.c Tue Aug 13 22:22:20 2002
@@ -3427,8 +3427,10 @@
* Cryptic check to ensure chipset not already set for hwif:
*/
if (i > 0 || i <= -11) { /* is parameter a chipset name? */
+#ifndef CONFIG_SH_CAT68701
if (hwif->chipset != ide_unknown)
goto bad_option; /* chipset already specified */
+#endif
if (i <= -11 && i != -18 && hw != 0)
goto bad_hwif; /* chipset drivers are for "ide0=" only */
if (i <= -11 && i != -18 && ide_hwifs[hw+1].chipset != ide_unknown)
diff -urN linux-2.4.19/drivers/net/cs89x0.c linux-2.4.19-cat68701/drivers/net/cs89x0.c
--- linux-2.4.19/drivers/net/cs89x0.c Sat Aug 3 09:39:44 2002
+++ linux-2.4.19-cat68701/drivers/net/cs89x0.c Tue Aug 13 22:03:57 2002
@@ -98,7 +98,7 @@
* Note that even if DMA is turned off we still support the 'dma' and 'use_dma'
* module options so we don't break any startup scripts.
*/
-#define ALLOW_DMA 1
+#define ALLOW_DMA 0

/*
* Set this to zero to remove all the debug statements via
@@ -166,7 +166,7 @@
#else
static unsigned int netcard_portlist[] __initdata =
{ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
-static unsigned int cs8900_irq_map[] = {10,11,12,5};
+static unsigned int cs8900_irq_map[] = {7,0,0,0};
#endif

#if DEBUGGING
diff -urN linux-2.4.19/drivers/net/cs89x0.h linux-2.4.19-cat68701/drivers/net/cs89x0.h
--- linux-2.4.19/drivers/net/cs89x0.h Sat Aug 3 09:39:44 2002
+++ linux-2.4.19-cat68701/drivers/net/cs89x0.h Tue Aug 13 22:04:13 2002
@@ -440,7 +440,7 @@
#ifdef CONFIG_SH_HICOSH4
#define CS8900_IRQ_MAP 0x0002 /* HiCO-SH4 board has its IRQ on #1 */
#else
-#define CS8900_IRQ_MAP 0x1c20 /* This IRQ map is fixed */
+#define CS8900_IRQ_MAP 0xffff /* This IRQ map is fixed */
#endif

#define CS8920_NO_INTS 0x0F /* Max CS8920 interrupt select # */
diff -urN linux-2.4.19/include/asm-sh/irq.h linux-2.4.19-cat68701/include/asm-sh/irq.h
--- linux-2.4.19/include/asm-sh/irq.h Sun Sep 9 04:29:09 2001
+++ linux-2.4.19-cat68701/include/asm-sh/irq.h Tue Aug 13 22:10:18 2002
@@ -321,11 +321,6 @@
extern int ec3104_irq_demux(int irq);
#define irq_demux ec3104_irq_demux

-#elif defined(CONFIG_SH_CAT68701)
-
-extern int cat68701_irq_demux(int irq);
-#define irq_demux cat68701_irq_demux
-
#elif defined(CONFIG_SH_DREAMCAST)

extern int systemasic_irq_demux(int irq);

実際にパッチを当てます。

$ pwd
/どこか/linux-2.4.19
$ patch -p1 < kernelpatch_2.4.19_sh.diff
$ patch -p1 < kernelpatch_2.4.19_cat68701.diff

サンプルとして筆者の .config ファイル(make menuconfig 等で YやNを選んだ結果を保存しているファイル)
を以下に用意します。

filedot-config-2.4.19.txt

make しましょう

$ cp dot-config-2.4.19.txt .config
$ make menuconfig
$ make dep
$ make zImage (SMPなマシンなら -j3を指定)

しばらく待って arch/sh/boot/zImage ができあがります。これがカーネルです。
sh-linux 機の /boot/vmlinuz にコピーしてから lilo を打ちます。
lilo については第3回 sh-lilo を参考にしてください。

モジュール

make menuconfig 時に 'M' としたものについてはモジュールになっていると思います。~モジュールもCompactFlashにインストールします。

Makefile が次のようになっていることを確認します。

# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
# relocations required by build roots. This is not defined in the
# makefile but the arguement can be passed to make if needed.
#
INSTALL_MOD_PATH=/mnt
$ make modules
$ su -
# mount /dev/hde1 /mnt  (CompactFlashをマウント)
# make modules_install 

irq_demux()って何?

もともと、 arch/sh/kernel/io_cat68701.c には次のような irq_demux()関数がありました。

int cat68701_irq_demux(int irq)
{
  if(irq==13) return 14;   /* CompactFlash (1st ide) */
  if(irq==7)  return 10;   /* cs8900 (network) */
  return irq;
}

CAT68701のハードウェアから通知されてくる割り込み ComactFlash=13, cs8900=7 を、
Linuxのデバイスドライバがデフォルトで知っているIRQ番号14,10に強引に変換していました。

ちなみに、CAT68701 の回路図にあるところの IRQ2 は論理反転して irq13, ~
同じくIRQ8は論理反転してirq7と読み替えてください。

ところが、このirq_demux()の仕組みでは、ハードウェアから通知される割り込みが13であるにもかかわらず、
後段で IRQ14を disable/enable しようとして、まれなタイミングで不具合がでることがわかりました。
従いまして 上の kernelpatch-2.4.19_cat68701.diff には irq_demux()関数そのものを削除するパッチが含まれています。

irq_demux()を削除してしまいましたので、 IDEデバイスドライバには「IRQ13だよ」と。cs8900デバイスドライバには
「IRQ7だよ」と教えてあげなければなりません。

IDEにIRQ番号を通知するには、カーネルパラメータで指定することができます。
/etc/lilo.conf (あるいは /mnt/etc/lilo.conf-cross で) ide= で指定します。
ブート時にカーネルに教えてあげます。

append="console=ttySC0,115200 mem=32M ide0=0x1f0,0x3f6,13"

cs8900デバイスドライバには、モジュールにした時は insmod 引数で教えてあげることができるのですが、
カーネルに組み込んでしまった時に教える方法がわからなかったので、コードを強引に書き換えました。

drivers/net/cs89x0.c

static unsigned int netcard_portlist[] __initdata =
{ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
static unsigned int cs8900_irq_map[] = {7,0,0,0};    ← ここで IRQ7を指定
#endif

drivers/net/cs89x0.h

#define CS8900_IRQ_MAP 0xffff /* This IRQ map is fixed */  ← 使用できるIRQのビットマスク=IRQ0-15全部

以上のように 2つのドライバに実際のIRQ番号を設定することによってirq_demux() を削除することができました。

セルフで!

CAT68701 の環境が整ってくればセルフでカーネルをコンパイルすることももちろんできます。
ハマリやすいのですが、make menuconfig のためには libncurses5-dev パッケージが必要になります。

# apt-get install libncurses5-dev

あとはCAT68701だからといって特に違う点はありませんので make dep zImage の順に実行してください。
ただし時間は相当覚悟してください。笑

$ time make zImage
real 151m42.678s
user 137m9.050s
sys 4m48.950s

時間はかかるけれど安定して最後までコンパイルできるのはたいしたもんです。
ちなみにまったく同じ .config 条件で、開発機 (Celeron 466MHz x2)では

$ time make zImage -j3
real 6m10.710s
user 11m21.250s
sys 0m43.130s
Last-modified: 2006-01-19 (木) 16:37:21 (4960d)