ドライバサービスは、カードサービスのクライアントドライバと cardmgr
の
ようなユーザモードのユティリティを結び付けます。カードサービスの
「スーパクライアント」といってもよいでしょう。ドライバサービスは、
BindDevice
関数を使って、他のクライアントドライバをそれぞれの PCMCIA
カードと結び付けます。他のクライアントとは異なり、ドライバサービスは、
カードの抜き差しが行われても、ずっと全部のソケットに拘束されたまま残
ります。
ドライバサービスは、導入されていてソケットに結合できる状態になっている すべてのクライアントドライバを把握しています。クライアントドライバに は、デバイスの「実体」の作成と削除をするための項目がなければなりませ ん。ここで言うデバイスの実体とは、ある PCMCIA カードを制御するために 必要なすべてを意味します。
各デバイスは、cs_types.h
に定義された特別な型 dev_info_t
を持つ、
ユニークな1 6 文字のタグで識別されます。各デバイスの実体は、
dev_link_t
構造体で記述されます。
dev_link_t
のデータ構造体は次のとおり:
#include "ds.h"
typedef struct dev_node_t {
char dev_name[8];
u_char major, minor;
struct dev_node_t *next;
}
typedef struct dev_link_t {
dev_node_t *dev;
u_long state, open;
struct wait_queue *pending
struct timer_list release
client_handle_t handle;
io_req_t io;
irq_req_t irq;
config_req_t conf;
window_handle_t win;
void *priv;
struct dev_link_t *next;
} dev_link_t;
dev_link_t
構造体の dev
変数はリンクリストの dev_node_t
構造体をポイントしています。dev_node_t
の
dev_name
変数は、ドライバによって、このデバイスをアクセスするための
ファイル名が書き込まれます(可能な場合のみ)。例えば、serial_cs
は
「ttyS1
」の様な名前を使います。major
と minor
の変数は、
このデバイス
をアクセスするためのメジャー番号とマイナー番号です。ドライバサービス
は、これらの変数を DS_GET_DEVICE_INFO
ioctl でユーザモードプログラム
に返します。
dev_link_t
の state
変数は、現在のデバイスの状態を把握する
ために使われます。次のフラグが定義されています。:
DEV_PRESENT
カードが存在することを示します。このビットは、ドライバのイベント ハンドラによって、カードの抜差しのイベントに対応してセットまたは クリアされます。
DEV_CONFIG
カードが設定済みであることを示します。
DEV_CONFIG_PENDING
カードの設定作業が実行中であることを示します。
DEV_SUSPEND
カードが一時的に使用できないことを示します。
DEV_BUSY
入出力動作が実行中であることを示します。このビットは、アクセスの 衝突を防ぐためのインターロックとして使うこともできます。
DEV_STALE_CONFIG
ドライバによっては、実行中のカードが抜かれた時には、そのカード に対応するすべてのデバイスが閉じるまでは、ソケットを解放すべき ではありません。このフラグは、デバイスがク閉じた時にソケットを 解放しなければならないことを示します。
DEV_STALE_LINK
ドライバの実体は、そのすべての PCMCIA リソースが解放されるまで 削除されてはなりません。このフラグは、ソケットが解放されたら すぐにドライバの実体が削除されなければならないことを示します。
open
変数は、このデバイスが何重に使われているかを数えます。
デバイスは、このカウントがゼロになるまで解放されてはなりません。
pending
変数は、このデバイスを使うために待っているプロセスの待ち行列
を管理するために使うことができます。
release
変数は、カードが抜かれた時に、デバイスのシャットダウン処理を
予定に入れるために使われます。カードの引抜きのイベントは高い優先度で
実行されなければなりません。ドライバのイベントハンドラは、通常デバイス
状態の DEV_PRESENT
ビットをリセットし、その時シャットダウン処理が後で
実行されるように予定することでイジェクトの処理をします。
handle
、io
、irq
、conf
および win
の各変数は、
通常の PCMCIA 入出力カードを組み込むために必要な普通の PCMCIA データ
構造に対応します。
priv
変数は、デバイスを管理するために必要などんな私的なデータ構造の
目的のためにでも使うことができます。next
変数は、複数の実体を扱う
ことのできるドライバで、dev_link_t
構造体の結合リストを作るために
使うことができます。
int register_pcmcia_driver(dev_info_t *dev_info,
dev_link_t *(*attach)(void),
void (*detach)(dev_link_t *));
register_pcmcia_driver
は、ドライバサービスに、クライアントドライバが
存在していてソケットに結び付けられる状態であることを知らせます。
ドライバサービスがこのドライバの dev_info
文字列に等しい
DS_BIND_REQUEST
ioctl を受け取ると、ドライバサービスはドライバの
attach()
関数を呼び出します。DS_UNBIND_REQU EST
ioctl を
受け取ったときは、detach()
を呼び出します。
int unregister_pcmcia_driver(dev_info_t *dev_info);
この関数は、ドライバサービスに、指定されたクライアントドライバには ソケットを結び付けてはならないことを知らせます。
ドライバサービスは、ユーザモードの PCMCIA ユティリティと通信する
ために疑似デバイスを作ります。このデバイスのメジャー番号は動的に
選ばれ、PCMCIA ユティリティは /proc/devices
を読んでその値
を得なければなりません。マイナー番号は 0 から始まるソケットの番号に対応
します。
ただ一つのプロセスだけが、あるソケットを読書きのためにオープンする
ことができます。他のプロセスは、読出し専用モードでのみ、このソケット
をオープンできます。読出しのみの接続では、一部の ioctl
機能だけが
使えます。読書き両方の接続では、すべての ioctl
機能が使え、カード
サービスからのイベントの通知を受け取ることができます。
ドライバサービスは、イベントの通知のために read()
と select()
の
関数を実装しています。ある PCMCIA デバイスから読出しを行うと、前回の
read()
以降ドライバサービスが受信したすべてのイベントが
unsigned long の値として返されます。もしイベントが何も発生していなけれ
ば、イベントが発生するまで、呼出しは封鎖します。select()
を使って、
複数のソケットの新規のイベントを監視することができます。
ドライバサービスは、次のイベントを監視します。:
CS_EVENT_CARD_INSERTION
, CS_EVENT_CARD_REMOVAL
,
CS_EVENT_RESET_PHYSICAL
, CS_EVENT_CARD_RESET
と
CS_EVENT_RESET_COMPLETE
.
ほとんどのドライバサービスの ioctl
の動作は、カードサービスの関数に
直接対応します。ioctl
の呼出しは、次の形式です。:
int ioctl(int fd, int cmd, ds_ioctl_arg_t *arg);
ds_ioctl_arg_t
の構造体は次のとおり:
typedef union ds_ioctl_arg_t {
servinfo_t servinfo;
adjust_t adjust;
config_info_t config;
tuple_t tuple;
tuple_parse_t tuple_parse;
client_req_t client_req;
status_t status;
conf_reg_t conf_reg;
cisinfo_t cisinfo;
region_info_t region;
bind_info_t bind_info;
mtd_info_t mtd_info;
} ds_ioctl_arg_t;
次の ioctl
のコマンドは、対応するカードサービスの関数を実行します。:
DS_GET_CARD_SERVICES_INFO
CardServices(GetCardServicesInfo, ..., &arg->servinfo)
を呼び出します。
DS_ADJUST_RESOURCE_INFO
CardServices(AdjustResourceInfo, ..., &arg->adjust)
を呼び出します。
DS_GET_CONFIGURATION_INFO
CardServices(GetConfigurationInfo, ..., &arg->config)
を呼び出します。
DS_GET_FIRST_TUPLE
CardServices(GetFirstTuple, ..., &arg->tuple)
を呼び出します。
DS_GET_NEXT_TUPLE
CardServices(GetNextTuple, ..., &arg->tuple)
を呼び出します。
DS_GET_TUPLE_DATA
CardServices(GetTupleData, ..., &arg->tuple_parse.tuple)
を呼び出します。
タプルデータが arg->tuple_parse.data
の中に返ります。
DS_PARSE_TUPLE
CardServices(ParseTuple, ..., &arg->tuple_parse.tuple, &arg->tuple_parse.parse)
を呼び出します。
DS_RESET_CARD
CardServices(ResetCard, ...)
を呼び出します。
DS_GET_STATUS
CardServices(GetStatus, ..., &arg->status)
を呼び出します。
DS_ACCESS_CONFIGURATION_REGISTER
CardServices(AccessConfigurationRegister, ..., &arg->conf_reg)
を呼び出します。
DS_VALIDATE_CIS
CardServices(ValidateCIS, ..., &arg->cisinfo)
を呼び出します。
DS_SUSPEND_CARD
CardServices(SuspendCard, ...)
を呼び出します。
DS_RESUME_CARD
CardServices(ResumeCard, ...)
を呼び出します。
DS_EJECT_CARD
CardServices(EjectCard, ...)
を呼び出します。
DS_INSERT_CARD
CardServices(InsertCard, ...)
を呼び出します。
DS_GET_FIRST_REGION
CardServices(GetFirstRegion, ..., &arg->region)
を呼び出します。
DS_GET_NEXT_REGION
CardServices(GetNextRegion, ..., &arg->region)
を呼び出します。
次の ioctl
のコマンドは、特別なドライバサービスの関数を呼び出します。
これらのコマンドは、bind_info_t
構造体に作用します。:
typedef struct bind_info_t {
dev_info_t dev_info;
u_char function;
struct dev_info_t *instance;
char name[8];
u_char major, minor;
void *next;
} bind_info_t;
DS_BIND_REQUEST
このコマンドは、ソケットをクライアントドライバに接続します。
指定されたデバイス識別子の dev_info
が、登録されたドライバの
リストから検索されます。もしこのカードが多機能カードの場合は、
function
変数がどのカード機能を接続するかを指定します。もし
ドライバが見つかると、ドライバはこのソケットと機能を、
BindDevice
を呼び出すことによって接続されます。その後、
ドライバサービスはドライバの attach()
項目を呼び出して
デバイスの実体を作成します。新しい dev_link_t
が
instance
の中に返されます。
DS_GET_DEVICE_INFO
このコマンドは、instance
が指し示す dev_link_t
構造体から、
dev_name
、major
、 minor
の項目を検索します。
DS_UNBIND_REQUEST
このコマンドはドライバと instance を指定した detach()
関数
を呼び出してデバイスをシャットダウンさせます。
最後に DS_BIND_MTD
要求は、引き数に mtd_info_t
の型をとります。:
typedef struct mtd_info_t {
dev_info_t dev_info;
u_long Attributes;
u_long CardOffset;
} mtd_info_t;
この呼び出しは、dev_info
によって識別される MTD と Attributes
と
CardOffset
によって記述されるメモリ範囲を関連づけます。
Attributes
と CardOffset
は、カードサービスの BindMTD
の呼出しのときと同じ意味です。