カーネル2.6的プリンタポートドライバ

受託案件絡みなので詳しく書けないのが歯がゆいが,守秘性が高い部分を取り除いて,書けるだけ書いてみる.

手元の環境(vPro Q35の普通のPC)では,register_region / register_irq / outb で作るトラディショナルなプリンタポートドライバは動かなかった.具体的には熊谷先生のところにあるようなもの
熊谷先生のコードは2.2時代のものなので,カーネル2.6上では細かい手直しをしなければビルドも通らないのだが.そういった表面上の変更を加えても動かない.

I/Oポートにアクセスできない?

悩んだのは,ユーザランド上に作った下記のコードの挙動.

#include <stdio.h>
#include <sys/io.h>

#define PIOADDR 0x378

main()
{
int b;
int i;
int r;

r = iopl(3);
if (r) perror("iopl");

for (i = 0; i < 3; i++) {
 b = inb_p(PIOADDR+i);
 printf(" %02x", b & 0xff);
}
puts("");

}

lp ppdev parport_pc parport を rmmod し,自作のパラレルポートドライバをinsmodした状態でこれを実行する.
すると,結果はどういうわけか

$ ./parport_look
ff ff ff

となる.outbしても値は変わらない.


parport_pc モジュールを組込んだ状態で実行すると,出力はソレらしい値になるし,outb にも反応する.


別の経路ではどうよ? ということで,下記を試してみたが,結果は ff だった.

#include <fcntl.h>
#include <unistd.h>

int
main(void)
{
	int fd;
	char c;

	fd = open("/dev/port", O_RDONLY);

	lseek(fd, 0x378, SEEK_CUR);
	read(fd, &c, 1);
	printf("%x", c);
}

カーネルモジュール内でもダメ?

モジュールの初期化ルーチンで inb してみても,結果は ff.えー!? なんか,どこかでトラップされているのではないかという疑惑が.カーネルモジュールって,リング0で実行されているのではないの???

/proc/

I/Oポートが書き変わらないとすると,当然IRQ7も立ち上がらない.ていうか,現状だと,IRQ7が有効になっているのかも判らない.
真っ先に request_irq や request_region を疑ってみたが,実行時のエラーは出ていないようだし,/proc/ioport や /proc/interrupt を見ると,それらしく登録されている.わからねぇ.

書籍

日曜日にも関わらず,開店直後のヨドバシに駆け込み.本を漁る.

Linuxデバイスドライバプログラミング

Linuxデバイスドライバプログラミング

Linuxカーネル2.6解読室

Linuxカーネル2.6解読室

ざっと読んだけれども,気になる点は無いっぽい.ポートマップドI/Oは近いうちに無くなると踏んでいるようで,両方とも記述が無茶苦茶あっさりしている.組込みではそうは行かないのだけれどもなぁ.残念ながら今回の役には立たなかった*1

解法

(後で書く)

*1:でも両方とも良い本です.買って正解.