ハードウェアを意識したプログラミングの基礎(後編)

荘司靖

tag: 組み込み

技術解説 2008年5月 1日

2.Linuxデバイス・ドライバの例

● The Linux Driver Model

 Linux 2.6から入ったDriver Modelには,良い点がいろいろとあります.筆者はその中でも,デバイス,バス,ドライバの定義を分けて記述できるところが気に入っています.これだけでも,多くのシステムにデバイス・ドライバを移植する人にはとても便利な機能だと思います.

 Driver Modelが標準化される前は,デバイス・ドライバにデバイスのことも接続方法も記述する必要がありました.しかしこれらをきれいに分離することで,アドレスや割り込みのようにシステム依存の部分と機能を提供するドライバの部分に分けることができるようになりました.

 それではここからは実際のコードを使って説明します.参考に使っているのは,アットマークテクノから発売されているSUZAKU-V注4というCPUボードです.このボードで使用しているEthernet MAC/PHYの処理を行うLSIを例に説明します.バスとデバイス,そしてドライバの三つを意識して読んでください.

注4;以下のURLを参照.http://www.atmark-techno.com/suzaku-v

 このLSIはプラットホーム固有のバスにつながっているため,プラットホーム・デバイスという仕組みを使用します.

137: #define SMC91111_BASE_ADDR 0xf0e00300
138: #define SMC91111_REG_SIZE 16
139: #define SMC91111_IRQ 1
140:
141: static struct resource smc91x_resources[] = {
142:   [0] = {
143:     .start = SMC91111_BASE_ADDR,
144:     .end = SMC91111_BASE_ADDR + SMC91111_REG_SIZE - 1,
145:     .flags = IORESOURCE_MEM,
146:   },
147:   [1] = {
148:     .start = SMC91111_IRQ,
149:     .end = SMC91111_IRQ,
150:     .flags = IORESOURCE_IRQ,
151:   },
152: };
153:
154: static struct platform_device smc91x_device = {
155:   .name = "smc91x",
156:   .id = -1,
157:   .num_resources = ARRAY_SIZE(smc91x_resources),
158:   .resource = smc91x_resources,
159: };
160:


リスト9 SMSC9111の情報を定義する (arch/ppc/platforms/4xx/suzaku-v.c)

 リスト9の137行目から139行目にSUZAKU-Vで使用している SMSC9111の情報が定義されています.この情報を141行目から始まる struct resourceに入れます.リソース情報はさらに,struct platform_deviceの resourceメンバ変数に代入されます.名前を入れ,SUZAKU-Vで使われているSMSC91111の情報がすべてまとまりました.この情報は,ほかのプラットホーム・デバイスと一緒にまとめられます(リスト10)

187: static struct platform_device *sv_devices[] __initdata = {
:
(中略)
:
189: &smc91x_device,
:
(中略)
:
194: };
195:
196: static int __init sv_device_init(void)
197: {
198: return platform_add_devices(sv_devices, ARRAY_SIZE(sv_devices));
199: }


リスト10 ほかのデバイスと一緒にまとめる (arch/ppc/platforms/4xx/suzaku-v.c)

 まとめられたシステム固有の情報は,システムの初期化時に登録されます.ここまでで,プラットホーム・バスにデバイスが登録されたことになります.

 さて,このデバイスを動かすためのデバイス・ドライバが必要になります.デバイス・ドライバは,

  drivers/net/smc911x.c

です.もちろんこのデバイス・ドライバはプラットホーム・バス用になっています.platform_driver構造体を自分自身の情報で初期化し(リスト11),ドライバの初期化関数で自分自身の情報をカーネルに登録します(リスト12).これでデバイスとデバイス・ドライバが結び付けられ,動作するようになります.

105: #define CARDNAME "smc911x"
:
(中略)
:
2326: static struct platform_driver smc911x_driver = {
2327:   .probe = smc911x_drv_probe,
2328:   .remove = smc911x_drv_remove,
2329:   .suspend = smc911x_drv_suspend,
2330:   .resume = smc911x_drv_resume,
2331:   .driver = {
2332:     .name = CARDNAME,
2333:   },
2334: };


リスト11 smc911xデバイス・ドライバ初期化部(drivers/net/smc911x.c)

2336: static int __init smc911x_init(void)
2337: {
2338:   return platform_driver_register(&smc911x_driver);
2339: }
2340:


リスト12 自分自身の情報をカーネルに登録する(drivers/net/smc911x.c)

● 具体的にどうやって結ばれるのか

 以下ではデバイスとデバイス・ドライバが結び付けられるまでの過程を説明していきます.

 デバイス・ドライバを書く上でフレームワークの中まですべて知る必要はありませんが,中味を知っているとデバイス・ドライバに対する理解が深まるでしょう.

 まずは,デバイス・ドライバの中で呼ばれたplatform_driver_register()から始めます(リスト13)

442: int platform_driver_register(struct platform_driver *drv)
443: {
444:   drv->driver.bus = &platform_bus_type;
445:   if (drv->probe)
446:     drv->driver.probe = platform_drv_probe;
447:   if (drv->remove)
448:     drv->driver.remove = platform_drv_remove;
449:   if (drv->shutdown)
450:     drv->driver.shutdown = platform_drv_shutdown;
451:   if (drv->suspend)
452:     drv->driver.suspend = platform_drv_suspend;
453:   if (drv->resume)
454:     drv->driver.resume = platform_drv_resume;
455:   return driver_register(&drv->driver);


リスト13 関数platform_driver_register()(drivers/base/platform.c)

組み込みキャッチアップ

お知らせ 一覧を見る

電子書籍の最新刊! FPGAマガジン No.12『ARMコアFPGA×Linux初体験』好評発売中

FPGAマガジン No.11『性能UP! アルゴリズム×手仕上げHDL』好評発売中! PDF版もあります

PICK UP用語

EV(電気自動車)

関連記事

EnOcean

関連記事

Android

関連記事

ニュース 一覧を見る
Tech Villageブログ

渡辺のぼるのロボコン・プロモータ日記

2年ぶりのブログ更新w

2016年10月 9日

Hamana Project

Hamana-8最終打ち上げ報告(その2)

2012年6月26日