次のページ 前のページ 目次へ

7. ドライバサービスインタフェース

ドライバサービスは、カードサービスのクライアントドライバと cardmgr の ようなユーザモードのユティリティを結び付けます。カードサービスの 「スーパクライアント」といってもよいでしょう。ドライバサービスは、 BindDevice 関数を使って、他のクライアントドライバをそれぞれの PCMCIA カードと結び付けます。他のクライアントとは異なり、ドライバサービスは、 カードの抜き差しが行われても、ずっと全部のソケットに拘束されたまま残 ります。

7.1 他のクライアントドライバへのインタフェース

ドライバサービスは、導入されていてソケットに結合できる状態になっている すべてのクライアントドライバを把握しています。クライアントドライバに は、デバイスの「実体」の作成と削除をするための項目がなければなりませ ん。ここで言うデバイスの実体とは、ある PCMCIA カードを制御するために 必要なすべてを意味します。

各デバイスは、cs_types.h に定義された特別な型 dev_info_t を持つ、 ユニークな1 6 文字のタグで識別されます。各デバイスの実体は、 dev_link_t 構造体で記述されます。

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_tdev_name 変数は、ドライバによって、このデバイスをアクセスするための ファイル名が書き込まれます(可能な場合のみ)。例えば、serial_cs は 「ttyS1」の様な名前を使います。majorminor の変数は、 このデバイス をアクセスするためのメジャー番号とマイナー番号です。ドライバサービス は、これらの変数を DS_GET_DEVICE_INFO ioctl でユーザモードプログラム に返します。

dev_link_tstate 変数は、現在のデバイスの状態を把握する ために使われます。次のフラグが定義されています。:

DEV_PRESENT

カードが存在することを示します。このビットは、ドライバのイベント ハンドラによって、カードの抜差しのイベントに対応してセットまたは クリアされます。

DEV_CONFIG

カードが設定済みであることを示します。

DEV_CONFIG_PENDING

カードの設定作業が実行中であることを示します。

DEV_SUSPEND

カードが一時的に使用できないことを示します。

DEV_BUSY

入出力動作が実行中であることを示します。このビットは、アクセスの 衝突を防ぐためのインターロックとして使うこともできます。

DEV_STALE_CONFIG

ドライバによっては、実行中のカードが抜かれた時には、そのカード に対応するすべてのデバイスが閉じるまでは、ソケットを解放すべき ではありません。このフラグは、デバイスがク閉じた時にソケットを 解放しなければならないことを示します。

DEV_STALE_LINK

ドライバの実体は、そのすべての PCMCIA リソースが解放されるまで 削除されてはなりません。このフラグは、ソケットが解放されたら すぐにドライバの実体が削除されなければならないことを示します。

open 変数は、このデバイスが何重に使われているかを数えます。 デバイスは、このカウントがゼロになるまで解放されてはなりません。 pending 変数は、このデバイスを使うために待っているプロセスの待ち行列 を管理するために使うことができます。

release 変数は、カードが抜かれた時に、デバイスのシャットダウン処理を 予定に入れるために使われます。カードの引抜きのイベントは高い優先度で 実行されなければなりません。ドライバのイベントハンドラは、通常デバイス 状態の DEV_PRESENT ビットをリセットし、その時シャットダウン処理が後で 実行されるように予定することでイジェクトの処理をします。

handleioirqconfおよび win の各変数は、 通常の PCMCIA 入出力カードを組み込むために必要な普通の PCMCIA データ 構造に対応します。

priv 変数は、デバイスを管理するために必要などんな私的なデータ構造の 目的のためにでも使うことができます。next 変数は、複数の実体を扱う ことのできるドライバで、dev_link_t 構造体の結合リストを作るために 使うことができます。

register_pcmcia_driver

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() を呼び出します。

unregister_pcmcia_driver

int unregister_pcmcia_driver(dev_info_t *dev_info);

この関数は、ドライバサービスに、指定されたクライアントドライバには ソケットを結び付けてはならないことを知らせます。

7.2 ユーザモードの PCMCIA ユティリティとのインタフェース

ドライバサービスは、ユーザモードの 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_RESETCS_EVENT_RESET_COMPLETE.

ioctl の説明

ほとんどのドライバサービスの 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_tinstance の中に返されます。

DS_GET_DEVICE_INFO

このコマンドは、instance が指し示す dev_link_t 構造体から、 dev_namemajorminor の項目を検索します。

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 と AttributesCardOffset によって記述されるメモリ範囲を関連づけます。 AttributesCardOffset は、カードサービスの BindMTD の呼出しのときと同じ意味です。


次のページ 前のページ 目次へ