  Linux PCMCIA プログラマの手引き
  David Hinds, dhinds@allegro.stanford.edu
  v1.35, 1997/11/14 08:25:25
  Kazuyuki Okamoto, ikko-@pacific.rim.or.jp
  Hiroshi Kawashima (kei@sm.sony.co.jp)
  Hiro Sugawara, hiro@arkusa.com
  JF project
  v1.35, 1997/12/11 01:00:00

  この文書は Linux PCMCIA カードサービスインターフェースの為のカーネルデ
  バイスドライバの書き方を説明しています。また、カードサービスの利用者用
  ユーティリティの書き方も説明します。この文書(text,html,sgml) の最新は
  hyper.stanford.edu の /pub/pcmcia/doc にあります。 HTML 版は
  http://hyper.stanford.edu/HyperNews/get/pcmcia/home.html にあります。
  ______________________________________________________________________

  目次

  1. 概説
     1.1 著作権表示と放棄声明
     1.2 謝辞

  2. 基本的な PCMCIA の概念
     2.1 PCMCIA ソケットインタフェース
     2.2 PCMCIA ソケット制御装置

  3. カードサービス関数解説
     3.1 クライアント管理関数
        3.1.1 RegisterClient
        3.1.2 DeregisterClient
        3.1.3 SetEventMask
        3.1.4 BindDevice
     3.2 ソケット状態管理
        3.2.1 GetStatus
        3.2.2 ResetCard
        3.2.3 SuspendCard
        3.2.4 ResumeCard
        3.2.5 EjectCard
        3.2.6 InsertCard
     3.3 入出力カードの設定関数
        3.3.1 RequestIO
        3.3.2 ReleaseIO
        3.3.3 RequestIRQ
        3.3.4 ReleaseIRQ
        3.3.5 RequestConfiguration
        3.3.6 ModifyConfiguration
        3.3.7 ReleaseConfiguration
        3.3.8 GetConfigurationInfo
     3.4 カード情報構造体 (CIS) 使用法
        3.4.1 GetFirstTuple, GetNextTuple
        3.4.2 GetTupleData
        3.4.3 ParseTuple
        3.4.4 ValidateCIS
     3.5 メモリ領域制御
        3.5.1 RequestWindow
        3.5.2 ModifyWindow
        3.5.3 MapMemPage
        3.5.4 ReleaseWindow
     3.6 大容量メモリサービス
        3.6.1 RegisterMTD
        3.6.2 GetFirstRegion, GetNextRegion
        3.6.3 OpenMemory
        3.6.4 CloseMemory
        3.6.5 ReadMemory, WriteMemory
        3.6.6 RegisterEraseQueue
        3.6.7 DeregisterEraseQueue
        3.6.8 CheckEraseQueue
     3.7 各種呼び出し
        3.7.1 GetCardServicesInfo
        3.7.2 AccessConfigurationRegister
        3.7.3 AdjustResourceInfo
        3.7.4 ReportError

  4. カード情報構造体 (CIS) の定義
     4.1 CIS タプルの定義
        4.1.1 CISTPL_CHECKSUM
        4.1.2 CISTPL_LONGLINK_A, CISTPL_LONGLINK_C, CISTPL_LINKTARGET, CISTPL_NOLINK
        4.1.3 CISTPL_LONGLINK_MFC
        4.1.4 CISTPL_DEVICE, CISTPL_DEVICE_A
        4.1.5 CISTPL_VERS_1
        4.1.6 CISTPL_ALTSTR
        4.1.7 CISTPL_JEDEC_C, CISTPL_JEDEC_A
        4.1.8 CISTPL_CONFIG
        4.1.9 CISTPL_CFTABLE_ENTRY
        4.1.10 CISTPL_MANFID
        4.1.11 CISTPL_FUNCID
        4.1.12 CISTPL_DEVICE_GEO
        4.1.13 CISTPL_VERS_2
        4.1.14 CISTPL_ORG
     4.2 CIS 構成レジスタ
        4.2.1 Configuration Option Register
        4.2.2 カードの構成情報と状態レジスタ
        4.2.3 ピン代替レジスタ
        4.2.4 ソケットとコピーレジスタ
        4.2.5 拡張状態レジスタ

  5. カードサービスイベントの扱いについて
     5.1 イベントハンドラの操作
     5.2 イベントの説明
     5.3 クライアントドライバのイベント操作の役割について

  6. メモリテクノロジドライバ
     6.1 MTD 要求の処理
     6.2 MTD 支援関数
        6.2.1 MTDRequestWindow, MTDReleaseWindow
        6.2.2 MTDModifyWindow
        6.2.3 MTDSetVpp
        6.2.4 MTDRDYMask

  7. ドライバサービスインタフェース
     7.1 他のクライアントドライバへのインタフェース
        7.1.1 dev_link_t 構造体
        7.1.2 register_pcmcia_driver
        7.1.3 unregister_pcmcia_driver
     7.2 ユーザモードの PCMCIA ユティリティとのインタフェース
        7.2.1 カードサービスのイベント通知
        7.2.2 ioctl の説明

  8. カードサービスクライアントドライバの解剖
     8.1 モジュールの初期化とリセット
     8.2 *_attach() と *_detach() 関数
     8.3 *_config() と *_release() 関数
     8.4 PCMCIA イベントハンドラ
     8.5 ロックと同期について
     8.6 現有の Linux のドライバで PCMCIA デバイスをアクセスする方法

  9. さらなる情報はどこにあるか？

  ______________________________________________________________________

  1.  概説

  Linux Kernel PCMCIA システムは 3 つの部分に分かれています。最下位のイ
  ンターフェースはソケットドライバです。次はカードサービスモジュールで
  す。特定のカード用のドライバはカードサービスの上位に位置しています。あ
  る特定のカードサービスクライアントはドライバサービスと呼ばれ、利用者用
  PCMCIA ユーティリティとカーネル PCMCIA 機能との間を結びます。

  ソケットドライバ層はソケットサービス API を大体利用しています。 2 つの
  ソケットドライバモジュールがあります。tcic モジュールは PCMCIA コント
  ローラの TCIC-2 系列のデータブックをサポートしています。i82365 モジュ
  ールは Intel i82365sl 系列と Cirrus, VLSI, Ricoh, Vadem チップのインテ
  ル互換のコントローラをサポートしています。

  カードサービスは PCMCIA パッケージの最も大きな単独の構成要素です。この
  サービスの API は DOS のカードサービスと似ており Unix 環境に適応してい
  ます。Linux への実装は Solaris PCMCIA のインターフェース仕様に準拠して
  います。この仕様は pcmcia_core モジュールに実装しています。バージョン
  2.1 の殆んどといくつかの PC Card 95 の仕様を実装しました。
  ドライバサービス層は PCMCIA ユーティリティから呼ばれるいくつかのカード
  サービス関数をアクセスする利用者用疑似ドライバとして実装しています。こ
  の実装は全ての PCMCIA クライアントドライバを見失わないようにするのと、
  物理ソケットとドライバを引き当てるのを確実にしています。ds モジュール
  内に実装しています。

  この文書はカードサービスとドライバサービスモジュールとドライバサービス
  へのユーザインターフェースのカーネルインターフェースについて説明してい
  ます。PCMCIA デバイスドライバの開発者の為に書いています。 Linux
  PCMCIA-HOWTO はどのように導入するかと Linux で PCMCIA をどのように使う
  かについて説明しています。この文書は cb-iris.stanford.edu の
  /pub/pcmcia にあります。

  1.1.  著作権表示と放棄声明

  Copyright (c) 1996, 1997 David A. Hinds

  この文書は著者の許可なしに如何なる形で複写または配布してかまいません。
  この文書を他の言語に翻訳など変更したものを含んで、変更点を明確に名乗っ
  て、この著作権表示をそのままに添付して自由に配布してください。

  私の同意無しに商用配布に利用可能です。必須ではありませんが、商用利用に
  あたり、私に通知して下さい。出版物に統合したいと思っている場合、最新の
  ものを使う必要がありますので私に連絡して下さい。

  この文書は明示的または暗黙的保証無しに``ありのまま''提供しています。こ
  の文書にある情報は御自身の責任で利用して下さい。

  1.2.  謝辞

  この PCMCIA ソフトウェアとドライバの開発のテストとデバッグを手伝ってく
  れた Linux ユーザの皆さんに感謝したいと思います。そしてカーネル開発を
  助けてくれた Linus Torvalds, Donald Becker, Alan Cox, と Bjorn Ekwall
  に感謝します。特に Solaris PCMCIA の実装について多くの助言となった打ち
  合せを行なった Michael Bender に感謝します。

  2.  基本的な PCMCIA の概念

  2.1.  PCMCIA ソケットインタフェース

  PCMCIA カードバスには 2 つの基本操作モードがあります。それは ``メモリ
  のみ''と``メモリと入出力''です。最初のモードは元々の第 1 版の仕様で定
  義されて単にメモリカードをサポートするものでした。次のモードは第 2 版
  で定義され、少しのメモリカードの制御信号が IO ポートと入出力割り込み信
  号を扱えるように再定義しています。

  PCMCIA カードは 2 つのメモリ空間があります。それは``属性メモリ''と
  ``一般メモリ''です。PCMCIA インタフェースはそれぞれの形式のメモリの
  16MB 以上のメモリを使えます。属性メモリは一般に種類の情報や構成するレ
  ジスタを保持するのに使用します。一般メモリはメモリカードの殆んどの領域
  か IO カードの場合はバッファ領域に使用します。PCMCIA 仕様 第2版に適合
  している全てのカードはカードがどのように構成されているかのカード情報構
  造(Card Information Structure (つまり ``CIS'')) を属性メモリに格納しま
  す。

  カードは分離制御信号を使って操作状況をホストに知らせます。この制御信号
  はカードの探知、レディ/ビジー状態、書き込み保護、電池不足と電池切れで
  構成しています。

  ``メモリと入出力''型のインターフェースモードのカードは 64K 以上の入出
  力ポートにアクセスできます。このモードでは入出力割り込みとカードの出力
  をホストシステムのスピーカへの経路を提供します。このモードではいくつか
  のメモリカード制御信号は特別な入出力カード信号を伝達するのにこれらのピ
  ンを使っているので使用できません。いくつかのカードでは制御信号を属性メ
  モリから特別な構成レジスタを読み出す代わりに用います。これを``ピン代替
  レジスタ''型のカードと呼びます。

  2.2.  PCMCIA ソケット制御装置

  PCMCIA 制御装置を PCMCIA カードとシステムバスの間の橋渡しをします。制
  御装置にはいくつかの種類がありますが、基本機能は同じです。ソケットサー
  ビス層は PCMCIA 制御装置を如何に扱うかの詳細を処理しています。

  PCMCIA 制御装置はホストメモリのジョブ空間と入出力空間のアドレス領域と
  カードのアドレス領域の割りつけを行ないます。全ての制御装置は最低 4つの
  独立したメモリ領域と2つの入出力領域をソケット毎に持っています。

  それぞれのメモリ領域はホストアドレス空間の基底アドレス、カード空間の基
  底アドレスとその領域の大きさで定義されます。いくつかの制御装置ではメモ
  リ領域の境界調整に違いがありますが、全ての制御装置は最低 4K 、且つその
  2 のべき乗の大きさのメモリ領域と基底アドレスで領域の倍数の大きさの領域
  をサポートしています。それぞれの領域を属性メモリか一般メモリを指すよう
  にプログラム出来ます。

  ホストアドレス上の入出力領域のアドレスがカード上に渡っても変更されない
  事がメモリ領域と異なっています。実際に、ホストとカードの領域の基底アド
  レスはいつも同じです。入出力領域は通常、境界調整が無いか大きさの制限は
  ありません。入出力領域の境界の始点と終点は 64K 内のバイト境界です。

  PCMCIA カードバスはカードから制御装置への一つの割り込み信号を定義しま
  す。制御装置はこの時適切なインラプト要求(IRQ) を操る役目を負います。全
  ての制御装置はカード入出力割り込みを空いている割り込みに割り当てます。
  従って制御装置はカード自身どの割り込みを使うか事前には分かりません。

  全ての PCMCIA 制御装置はカードが返す状態変更の割り込みを生成します。こ
  の割り込みは入出力カードが生成した入出力割り込みと区別され、別の割り込
  み線を使います。この信号はカードの検知、レディ/ビジー、書き込み保護、
  電池不足、電池切れを含んでいます。

  3.  カードサービス関数解説

  カードサービスは一般に次の形で呼びます。:

       #include "cs_types.h"
       #include "cs.h"

       int CardServices(int subfunc, void *arg1, void *arg2, ...);

  いくつかのカードサービス関数は #include 文を追加する必要があります。特
  殊な下位の関数は引数の数を認識します。CS_SUCCESS の戻り値は呼出が成功
  した事を示しています。その他の戻り値は失敗を示しています。

  3.1.  クライアント管理関数

  カードサービス関数を使うデバイスドライバを``クライアント''と呼びます。
  デバイスドライバは他のサービスを使用する前に RegisterClient を呼び出し
  てクライアントハンドルを取得しなければいけません。カードを抜く前にドラ
  イバを DeregisterClient を使用して抹消する必要があります。

  3.1.1.  RegisterClient

       int CardServices(RegisterClient, client_handle_t *client, client_reg_t *reg);

  client_reg_t データ構造体の定義は次のとおり:

       typedef struct client_reg_t {
               dev_info_t              *dev_info;
               u_long                  Attributes;
               u_long                  EventMask;
               int                     (*event_handler)(event_t event, int priority,
                                                       event_callback_args_t *args);
               event_callback_args_t   event_callback_args;
               u_long                  Version;
       } client_reg_t;

  RegisterClient はクライアントドライバとカードサービスの結合を確立しク
  ライアントに適切なソケットを接続します。 dev_info パラメタはソケットと
  関数をクライアントに合わせるのにカードサービスが使います。この対応を
  BindDevice を呼ぶ事を通してドライバサービスによって確立します。対応が
  確立したら、クライアントハンドルが client に返ります。

  次のフラグが属性に指定できます。:

     INFO_MASTER_CLIENT
        ドライバサービスクライアントだけが使用します。他に、ソケットから
        カードを抜いた時はクライアントが自動でなく解放しなければいけませ
        ん。

     INFO_IO_CLIENT
        クライアントが入出力カードドライバの場合に指定します。

     INFO_MEM_CLIENT
        クライアントがメモリテクノロジドライバの場合に指定します。

     INFO_MEM_CLIENT
        クライアントがメモリカードドライバの場合に指定します。

     INFO_CARD_SHARE
        互換性の為に入っています。何もしません。

     INFO_CARD_EXCL
        互換性の為に入っています。何もしません。

  EventMask はクライアントに何が起こっているか通知する時に指定します。
  event_handler の項目は EventMask で処理されるとカードサービスによって
  呼ばれます。event_handler_args 構造体はイベントハンドラに渡される構造
  体の雛型 (テンプレートr) です。Version パラメタはこのドライバが要求す
  るカードサービスのバージョンレベルを示します。これは現在無視されます。

  ドライバが RegisterClient を呼び出す前にカードサービスを扱う準備を行な
  う必要があります。この呼び出しはいつも CS_REGISTRATION_COMPLETE イベン
  トを生成し、ソケットが現在使用している場合は、わざと CS_CARD_INSERTION
  イベントを生成します。

  戻り値 :

     CS_OUT_OF_RESOURCE
        ドライバに必要な適切なドライバが見つかりません。

  3.1.2.  DeregisterClient

       int CardServices(DeregisterClient, client_handle_t client);

  DeregisterClient はクライアントとカードサービスの連結を行ないます。ク
  ライアントが割り当てられたリソースを解放した後で呼びます。連結が切れた
  ら、BindDevice を他のクライアントが呼ぶまで再確立出来ません。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効です。

     CS_IN_USE
        クライアントに入出力ポート領域や割り込みなどのリソースが割り当て
        られているかソケット構成がロックされています。

  3.1.3.  SetEventMask

       int CardServices(SetEventMask, client_handle_t client, eventmask_t *mask);

  eventmask_t 構造体の定義は次のとおり:

       typedef struct eventmask_t {
               u_long          Attributes;
               u_long          EventMask;
       } eventmask_t;

  SetEventMask はクライアントに通知されたイベントを認識するようにマスク
  を更新します。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効です。
  3.1.4.  BindDevice

       int CardServices(BindDevice, bind_req_t *req);

  bind_req 構造体の定義は次のとおり:

       typedef struct bind_req_t {
               socket_t        Socket;
               u_char          Function;
               dev_info_t      *dev_info;
       } bind_req_t;

  BindDevice でデバイスドライバと適切なソケットを関係づけます。通常、新
  規に挿入されたカードが認識できた後でデバイスサービスから呼ばれます。一
  旦、ドライバがソケットと接続されると、そのソケットのクライアントととし
  てドライバを登録するのに適格でしょう。この呼び出しは引数がクライアント
  ハンドルではないことに注意して下さい。カードサービス呼び出しだけはソ
  ケット番号を引数に用いています。

  Function 変数はドライバに結合したい多機能カードのうちの機能 (複数可 )
  を指定します。Function 番号はカードの CISTPL_LONGLINK_MFC タプルに相当
  します。Function を BIND_FN_ALL に設定した場合は、ドライバはカードの全
  ての機能を接続します。ドライバは CIS タプルに相当する機能に接続する事
  だけが可能です。

  戻り値 :

     CS_BAD_SOCKET
        指定したソケット番号は無効です。

  3.2.  ソケット状態管理

  これらの関数は多かれ少なかれ現在のソケットの状態の獲得と設定に関与して
  います。GetStatus は現在のソケット状態を返します。ResetCard はハードリ
  セット信号をソケットに送ります。SuspendCard と ResumeCard は電源オフと
  電源オンを現在接続しているドライバを切り離す事なしに行ないます。
  EjectCard と InsertCard は本質的に実際にカードの排出と挿入イベントを真
  似します。

  3.2.1.  GetStatus

       int CardServices(GetStatus, client_handle_t client, status_t *status);

  status_t データ構造体の定義は次のとおり:

  typedef struct status_t {
          u_char          Function;
          u_long          CardState;
          u_long          SocketState;
  } status_t;

  GetStatus はクライアントのソケットの現在の状態を返します。入出力モード
  に設定されているカードでは、GetStatus はピン代替レジスタと拡張状態レジ
  スタをカード状態を認識するのに使っています。通常のクライアントには
  Function 変数は無視されますが、 BIND_FN_ALL を指定しているクライアント
  ではこの変数で指定した機能の構成レジスタでソケット状態を決定するのに使
  用します。 CardState には次のフラグを定義しています。:

     CS_EVENT_CARD_DETECT
        指定したソケットを使用します。

     CS_EVENT_WRITE_PROTECT
        指定したカードを書き込み禁止にしました。

     CS_EVENT_BATTERY_LOW
        指定したカードの電池が不足しました。

     CS_EVENT_BATTERY_DEAD
        指定したカードは電池切れです。

     CS_EVENT_READY_CHANGE
        指定したカードは準備完了です。

     CS_EVENT_PM_SUSPEND
        指定したソケットは停止しました。

     CS_EVENT_REQUEST_ATTENTION
        指定した拡張状態レジスタ内の要求命令ビットを設定しました。

  SocketState は現在使われていませんが、原則的には CardState の状態変数
  の中に組み込まれていくでしょう。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。

  3.2.2.  ResetCard

       int CardServices(ResetCard, client_handle_t client);

  ResetCard はクライアントのソケットのリセットを要求します。この呼び出し
  が発生した時、カードサービスは全てのクライアントに
  CS_EVENT_RESET_REQUEST イベントを送ります。クライアントがこの要求を拒
  否した場合は、カードサービスクライアントを初期化する為に
  CS_EVENT_RESET_COMPLETE イベントを event_callback_args.info にクライア
  ントの要求拒否の返り値を設定してクライアントに送ります。

  全てのクライアントがこの要求に同意すると、カードサービスは
  CS_EVENT_RESET_PHYSICAL イベントを送り、ソケットをリセットします。ソ
  ケット信号が準備完了になると、CS_EVENT_CARD_RESET イベントを生成しま
  す。最後に CS_EVENT_RESET_COMPLETE イベントを event_callback_args.info
  にゼロを設定して初期化するクライアントに送ります。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。

     CS_NO_CARD
        クライアントに割り付けたソケットは現在使われていません。

     CS_IN_USE
        ソケットは現在リセットしています。

  3.2.3.  SuspendCard

       int CardServices(SuspendCard, client_handle_t client);

  カードサービスは全てのクライアントに CS_EVENT_PM_SUSPEND イベントを送
  ります。ソケットをシャットダウンと電源オフさせます。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。

     CS_NO_CARD
        クライアントに割り付けたソケットは現在使われていません。

     CS_IN_USE
        ソケットは既に中止しています。

  3.2.4.  ResumeCard

       int CardServices(ResumeCard, client_handle_t client);

  ソケットが電源オフした後、カードサービスは全てのクライアントに
  CS_EVENT_PM_RESUME イベントを送ります。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。

     CS_NO_CARD
        クライアントに割り付けたソケットは現在使われていません。

     CS_IN_USE
        ソケットは既に中止しています。
  3.2.5.  EjectCard

       int CardServices(EjectCard, client_handle_t client);

  カードサービスは全てのクライアントに 排出 (イジェクト) イベントを送り
  ます。ソケットをシャットダウンと電源オフさせます。全てのクライアントが
  ドライバサービスがソケットを切り離す為にイベントを受け取ります。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。

     CS_NO_CARD
        クライアントに割り付けたソケットは現在使われていません。

  3.2.6.  InsertCard

       int CardServices(InsertCard, client_handle_t client);

  カードサービスは挿入イベントを全てのソケットのクライアントに送ります。
  (通常、ドライバサービス限定です)

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。

     CS_NO_CARD
        クライアントに割り付けたソケットは現在使われていません。

     CS_IN_USE
        ソケットは既に設定しています。

  3.3.  入出力カードの設定関数

  普通のイベントの順番はドライバ用に入出力ポートと RequestIO と
  RequestIR を呼び出して割り込み線を予約します。そして、
  RequestConfiguration を呼び出して実際のソケットを設定します。これらの
  呼び出しに失敗したら、うまく予約ができるようにリソースを解放するように
  ドライバを確認して下さい。

  多機能カードはそれぞれの機能を分離して設定しましょう。しかしながら他の
  機能と調和している必要があります。それぞれのカード機能はその自身のレジ
  スタのセットを持ち、それぞれのソケットは一つの割り込み線と二つの連続し
  た入出力ポート番号を割り当てます。

  3.3.1.  RequestIO

       int CardServices(RequestIO, client_handle_t client, io_req_t *req);

  io_req_t 構造体の定義は次のとおり:

       typedef struct io_req_t {
               ioaddr_t        BasePort1;
               ioaddr_t        NumPorts1;
               u_long          Attributes1;
               ioaddr_t        BasePort2;
               ioaddr_t        NumPorts2;
               u_long          Attributes2;
               u_long          IOAddrLines;
       } io_req_t;

  RequestIO はカード用入出力領域を予約します。BasePort1 がゼロでない場合
  は、予約する領域の入出力ポートアドレスです。ゼロの場合は、カードサービ
  スが利用できる領域をみつけて、BasePort1 にそのアドレスを設定することで
  す。NumPorts2 がゼロでない場合は、2番目の入出力ポート領域も予約しま
  す。IOAddrLines は PCMCIA カードで実際にデコードするアドレス線の数を指
  定します。これは現在使われていません。

  多機能カードではこの呼び出しでそれぞれの物理ポートに対応する 2 つの低
  層入出力領域を割り付けそれぞれのカード機能に対応した全てのポートに入出
  力ポートを割り当てます。例えば、仮に4機能カードの場合 8 ポートを所有す
  る1つの入出力領域をドライバは割り当て、カードサービスは 1 つの連続した
  32-ポートブロックに統合します。

  この呼び出しは実際のソケットの入出力領域を設定するものではありません。
  続いて RequestConfiguration を呼び出して設定して下さい。

  次のフラグは Attributes1 と Attributes2 に指定します。:

     IO_DATA_PATH_WIDTH
        この変数は 16 ビットアクセス用の IO_DATA_PATH_WIDTH_16 もしくは
        8 ビットアクセス用の IO_DATA_PATH_WIDTH_8 もしくはアクセスするバ
        スの大きさに合わせた動的な領域の大きさを決める
        IO_DATA_PATH_WIDTH_AUTO のどちらか一方に設定します。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。

     CS_NO_CARD
        クライアントに割り付けたソケットは現在使われていません。

     CS_IN_USE
        ソケットの入出力領域は既に予約されています。

     CS_CONFIGURATION_LOCKED
        ソケットの構成は RequestConfiguration によってロックされていま
        す。

     CS_BAD_ATTRIBUTE
        サポートしていない属性フラグが指定されました。
  3.3.2.  ReleaseIO

       int CardServices(ReleaseIO, client_handle_t client, io_req_t *req);

  ReleaseIO は RequestIO が呼ばれる前に割り当てられていた入出力ポート領
  域を解放します。req 変数は RequestIO にそのまま渡します。いくつかのカ
  ードの機能が大きな入出力ポート領域を共有している場合、一つの機能がポー
  トを解放しても全てのカードの機能が入出力ポートを解放するまでは他が使っ
  ているポートを使えなくしてしまってはいけません。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。

     CS_CONFIGURATION_LOCKED
        ソケットの構成は RequestConfiguration によってロックされていま
        す。その構成は ReleaseIO を呼ぶ前に解放されています。

     CS_BAD_ARGS
        req に入っている変数が RequestIO に渡されたものと一致していませ
        ん。

  3.3.3.  RequestIRQ

       int CardServices(RequestIRQ, client_handle_t client, irq_req_t *req);

  irq_req_t 構造体の定義は次のとおり:

       typedef struct irq_req_t {
               u_long          Attributes;
               u_long          AssignedIRQ;
               u_long          IRQInfo1, IRQInfo2;
               void            *(Handler)(int, struct pt_regs *);
               void            *Instance
       } irq_req_t;

  RequestIRQ は PCMCIA カードが使用する割り込み線を予約します。 IRQInfo1
  と IRQInfo2 変数は CFTABLE_ENTRY タプル内の割り込み記述語と一致してい
  ます。IRQ_INFO2_VALID を IRQInfo1 に設定しているならば IRQInfo2 を割り
  込みの数値を考慮したビットマップマスクを設定しましょう。それぞれのビッ
  トは一つの割り込み線と一致しています。例えばビット 0 は割り込み 0 、
  ビット 1 は割り込み 1 などです。従って、 0x1100 というマスクは割り込み
  12 と割り込み 8 を使う事を意味しています。IRQ_INFO2_VALID を設定してい
  ない場合は、IRQInfo1 は割り込み番号を指定する必要があります。この呼び
  出しが成功した時は、AssignedIRQ に予約された割り込み番号が返ってきま
  す。

  IRQ_HANDLER_PRESENT フラグを設定すると、その時この呼び出しが割り込みが
  有効になっている時に割り込みハンドラを導入することを示していま
  す。RequestConfiguration が呼ばれた時、Handler で指定した割り込みハン
  ドラが導入されます。カーネル 2.0 以降では割り込みハンドラは Instance
  で与えられる ``実体'' のドライバと共に導入されます。カーネル 2.1.60 以
  前では、カーネルの irq2dev_map テーブルも更新するでしょう。多機能カー
  ドでは、割り込みは共有モードで割り当てられ、ハンドラは割り込みを受け
  取った時カードに機能を認識させる役割を負います。クライアントがカードサ
  ービスを迂回する為に独自の割り込みサービスルーチンを導入する場合は、ク
  ライアントが多機能カードと結合するには共有モードで割り当てましょう。

  Attributes で指定できるフラグは次のとおり:

     IRQ_FORCED_PULSE
        指定する割り込みは標準のレベルモードよりはパルスモードで設定しま
        しょう。

     IRQ_TYPE_TIME
        指定する割り込みは他のカードサービスドライバで時分割で行ないま
        しょう。一つのドライバではいつでも割り込み可能になります。

     IRQ_FIRST_SHARED
        IRQ_TYPE_TIME と組み合わせて、最初のドライバを共有割り込みするよ
        うに設定します。

     IRQ_HANDLER_PRESENT
        Handler 変数が導入済みの割り込みサービスルーチンを指すようにしま
        す。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。

     CS_NO_CARD
        クライアントに割り付けたソケットは現在使われていません。

     CS_IN_USE
        ソケットの入出力領域は既に予約されているか、要求した割り込みは使
        用できません。

     CS_CONFIGURATION_LOCKED
        ソケットの構成は RequestConfiguration によってロックされていま
        す。

     CS_BAD_ATTRIBUTE
        サポートしていない属性フラグが指定されました。

  3.3.4.  ReleaseIRQ

       int CardServices(ReleaseIRQ, client_handle_t client, irq_req_t *req);

  ReleaseIRQ はそれ以前に割り当てられている割り込みの予約解除をします。
  req 構造体は RequestIRQ に渡される構造体と同じものです。ハンドラを
  RequestIRQ 呼び出しで指定した場合は、この時点で登録解除されます。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。
     CS_CONFIGURATION_LOCKED
        ソケットの構成は RequestConfiguration によってロックされていま
        す。構成は ReleaseIRQ が呼ばれる前に解除されています。

     CS_BAD_IRQ
        req で指定したパラメータが RequestIRQ に渡されていたものと一致し
        ていません。

  3.3.5.  RequestConfiguration

       int CardServices(RequestConfiguration, client_handle_t client, config_req_t *req);

  config_req_t 構造体の定義は次のとおり:

       typedef struct config_req_t {
               u_long          Attributes;
               u_long          Vcc, Vpp1, Vpp2;
               u_long          IntType;
               caddr_t         ConfigBase;
               u_char          Status, Pin, Copy, ExtStatus;
               u_char          ConfigIndex;
               u_long          Present;
       } config_req_t;

  RequestConfiguration は実際にソケットの構成を行ないます。これは電圧の
  設定、 CIS 構成レジスタの設定、入出力ポート領域の設定、割り込みの設定
  を行ないます。

  IntType は使用するカードのインターフェースの型を指定します。その型は
  INT_MEMORY または INT_MEMORY_AND_IO のいずれかを指定します。 Voltages
  は 1/10 ボルトの単位で指定します。現在は、Vpp1 と Vpp2 は同じである必
  要があります．

  多機能カードではそれぞれのカード機能は別々に構成します。それぞれの機能
  は CIS 構成レジスタの組み合わせで行ないます。しかしながら、全ての機能
  は同じ電源とインタフェースで構成しなければいけません。

  次のフラグは Attributes で指定するものです。DMA とスピーカ制御は全ての
  システムでサポートはしていません。

     CONF_ENABLE_IRQ
        RequestIRQ 以前を入出力割り込みを予約可能にします。

     CONF_ENABLE_DMA
        ソケット用に DMA アクセスを有効にします。

     CONF_ENABLE_SPKR
        ソケットからスピーカ出力を有効にします。

  Present 変数はカードに実装している CIS 構成レジスタで指定するビット
  マップです。ConfigBase は属性メモリ内の構成レジスタのオフセットで与え
  ます。次のレジスタで指定します。:

     PRESENT_OPTION
        現在の構成オプションレジスタ(COR) を指定します。 COR レジスタは
        ConfigIndex 変数を使って指定します。

     PRESENT_STATUS
        現在のカード構成(CC) と 状態レジスタ(SR) を指定します。 CCSR は
        Status 変数で初期化します。

     PRESENT_PIN_REPLACE
        現在のピン代替レジスタ(PRR) を指定します。PRR は Pin 変数で初期
        化します。

     PRESENT_COPY
        現在のソケット(S) とコピーレジスタ(CR) を指定します。SCR は Copy
        変数で初期化します。

     PRESENT_EXT_STATUS
        現在の拡張状態レジスタ(ESR) を指定します。ESR は ExtStatus 変数
        で初期化します。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。

     CS_NO_CARD
        クライアントに割り付けたソケットは現在使われていません。

     CS_OUT_OF_RESOURCE
        カードサービスはカードの構成レジスタにアクセスするメモリ領域が割
        り当てできません。

     CS_CONFIGURATION_LOCKED
        カードの構成は RequestConfiguration によってロックされています。

     CS_BAD_VCC
        要求された Vcc 電圧はサポートしていません。

     CS_BAD_VPP
        要求された Vpp1/Vpp2 電圧はサポートしていません。

  3.3.6.  ModifyConfiguration

       int CardServices(ModifyConfiguration, client_handle_t client, modconf_t *mod);

  modconf_t 構造体の定義は次のとおり:

       typedef struct modconf_t {
               u_long          Attributes;
               u_long          Vcc, Vpp1, Vpp2;
       } modconf_t;

  ModifyConfiguration は RequestConfiguration を呼び出して設定したソケッ
  トの属性を変更します。

  Attributes で指定できるフラグは次のとおり:

     CONF_IRQ_CHANGE_VALID
        CONF_ENABLE_IRQ の設定を変更する事を表しています。

     CONF_ENABLE_IRQ
        ソケットに有効になっている入出力割り込みを指定します。

     CONF_VCC_CHANGE_VALID
        Vcc を変更することを表しています。

     CONF_VPP1_CHANGE_VALID
        Vpp1 を変更することを表しています。

     CONF_VPP2_CHANGE_VALID
        Vpp2 を変更することを表しています。

  現在、Vpp1 と Vpp2 は常に同じ値でなければいけません。従って、2つの値は
  同時に変更する必要があります。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルは無効です。

     CS_NO_CARD
        クライアントに割り付けたソケットは現在使われていません。

     CS_CONFIGURATION_LOCKED
        実際には、ソケットはロックされていません。

     CS_BAD_VCC
        要求された Vcc 電圧はサポートしていません。

     CS_BAD_VPP
        要求された Vpp1/Vpp2 電圧はサポートしていません。

  3.3.7.  ReleaseConfiguration

       int CardServices(ReleaseConfiguration, client_handle_t client, config_req_t *req);

  ReleaseConfiguration はそれ以前に設定されている構成の解除をします。
  req 構造体は ソケットを設定するときと同じものです。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効か、ソケットが設定されていません。

  3.3.8.  GetConfigurationInfo

       int CardServices(GetConfigurationInfo, client_handle_t client, config_info_t *config);

  config_info_t 構造体の定義は次のとおり:

       typedef struct config_info_t {
               u_char          Function;
               u_long          Attributes;
               u_long          Vcc, Vpp1, Vpp2;
               u_long          IntType;
               caddr_t         ConfigBase;
               u_char          Status, Pin, Copy, Option, ExtStatus;
               u_long          Present;
               u_long          AssignedIRQ;
               u_long          IRQAttributes;
               ioaddr_t        BasePort1;
               ioaddr_t        NumPorts1;
               u_long          Attributes1;
               ioaddr_t        BasePort2;
               ioaddr_t        NumPorts2;
               u_long          Attributes2;
               u_long          IOAddrLines;
       } config_info_t;

  GetConfigurationInfo は RequestIO, RequestIRQ と RequestConfiguration
  で設定した現在のソケットの構成を返します。完全に構成したソケットに対し
  て適応してください。単機能のカードに結合しているクライアントでは、
  Function 変数は無視され、クライアントが指定している機能のデータを返し
  ます。BIND_FN_ALL と結合しているクライアントではこの変数は指定した関数
  の構成データを返します。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効か、ソケットが設定されていません。

     CS_NO_CARD
        クライアントに割り付けたソケットは現在使われていません。

     CS_CONFIGURATION_LOCKED
        実際には、ソケットはロックされていません。

  3.4.  カード情報構造体 (CIS) 使用法

  カード情報構造体 (CIS) は PCMCIA 標準の中で最も分かりにくいところで
  す。全ての第 2 版の PCMCIA カードはここでどう設定するか説明する CIS を
  持っています。CIS はカードの属性メモリ空間の中の``タプル (tuples)''の
  連結リストです。タプルは識別コード、データ長と一連のデータからなりま
  す。いくつかのタプルでのデータの配置はことごとく全てのビットを使うよう
  な明らかな努力を必要とするほど、かなり複雑です。

  ValidateCIS 呼び出しは正当な CIS を使っているカードかどうか調べます。
  GetFirstTuple と GetNextTuple 呼び出しは CIS タプルリストを移動する方
  法です。GetTupleData はタプルからデータを取り出します。そして
  ParseTuple は特に重要な限られた数のタプルを解釈します。

  3.4.1.  GetFirstTuple, GetNextTuple

  #include "cistpl.h"

  int CardServices(GetFirstTuple, client_handle_t client, tuple_t *tuple);
  int CardServices(GetNextTuple, client_handle_t client, tuple_t *tuple);

  tuple_t データ構造体の定義は次のとおり:

       typedef struct tuple_t {
               u_long          Attributes;
               cis_data_t      DesiredTuple;
               u_long          Flags;
               cisdata_t       TupleCode;
               u_long          TupleLink;
               cisdata_t       TupleOffset;
               cisdata_t       TupleDataMax;
               cisdata_t       TupleDataLen;
               cisdata_t       *TupleData;
       } tuple_t;

  GetFirstTuple は DesiredTuple に一致する最初のタプルコードをカードの
  CIS から探します。特別な RETURN_FIRST_TUPLE コードはどんな種類のタプル
  に一致します。TupleCode を最初に一致したタプルのコードに設定しま
  す。TupleLink は属性メモリ内のタプルのアドレスです。

  GetNextTuple は事前に実行した GetFirstTuple が返す tuple_t 構造体を与
  えることを除いて GetFirstTuple に似ています。また、GetNextTuple は次に
  一致させたいタプルを DesiredTuple に返します。

  これらの関数は自動的に CIS 内のリンクタプルを全て手繰って調査します。
  多機能カードでは CISTPL_LONGLINK_MFC タプルを持っているのは、これらの
  関数がクライアントドライバの指している機能を指定した CIS だけを自動的
  に追跡できるようにするためです。クライアントが BIND_FN_ALL を結合して
  いる場合は、全てのタプルが返るでしょう。

  Attributes で指定できるフラグは次のとおり:

     TUPLE_RETURN_LINK
        リンクタプル (CISTPL_LONGLINK_A, CISTPL_LONGLINK_C,
        CISTPL_LONGLINK_MFC, CISTPL_NOLINK, CISTPL_LINKTARGET) を返すこ
        とを表しています。普通はこれらのタプルは暗黙のうちに処理されま
        す。

     TUPLE_RETURN_COMMON
        多機能 CIS の``共有'' CIS セクションのタプルを返すことを表してい
        ます。このフラグがない時は通常、カードサービスはクライアントに結
        合させる機能を表すタプルを返します．

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効です。

     CS_OUT_OF_RESOURCE
        カードサービスはメモリ領域をカードの CIS に割り付けできませんで
        した。

     CS_NO_MORE_ITEMS
        DesiredTuple に一致するタプルはありません。
  3.4.2.  GetTupleData

       #include "cistpl.h"

       int CardServices(GetTupleData, client_handle_t client, tuple_t *tuple);

  GetTupleData は一連のデータを事前に呼んだ GetFirstTuple または
  GetNextTuple の返してきた指定されたタプルから取り出します。
  TupleDataMax の最大長は TupleData バッファにコピーされて、 TupleOffset
  のオフセットから始まります。コピーされたバイト数は TupleDataLen に入っ
  ています。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効です。

     CS_OUT_OF_RESOURCE
        カードサービスはメモリ領域をカードの CIS に割り付けできませんで
        した。

     CS_NO_MORE_ITEMS
        タプルには何もデータが格納されていません。TuppleOffset はタプル
        の長さと等しいかより大きいです。

  3.4.3.  ParseTuple

       #include "cistpl.h"

       int CardServices(ParseTuple, client_handle_t client, tuple_t *tuple, cisparse_t *parse);

  cisparse_t データ 構造体は次のとおり:

       typedef union cisparse_t {
               cistpl_device_t         device;
               cistpl_checksum_t       checksum;
               cistpl_longlink_t       longlink;
               cistpl_longlink_mfc_t   longlink_mfc;
               cistpl_vers_1_t         version_1;
               cistpl_altstr_t         altstr;
               cistpl_jedec_t          jedec;
               cistpl_manfid_t         manfid;
               cistpl_funcid_t         funcid;
               cistpl_config_t         config;
               cistpl_cftable_entry_t  cftable_entry;
               cistpl_device_geo_t     device_geo;
               cistpl_vers_2_t         version_2;
               cistpl_org_t            org;
       } cisparse_t;

  ParseTuple は事前に呼んだ GetTupleData が返してきたタプルのデータを解
  釈します。返ってきた構造体は解析したタプルの型に依存します。これらの構
  造体の定義は cistpl.h ファイルを参照して下さい。そのうちのいくつかは大
  変複雑なものです。

  戻り値 :

     CS_BAD_TUPLE
        タプルの解析中にエラーが発生しました。タプルが不完全か、書式が正
        しくありません。

     CS_UNSUPPORTED_FUNCTION
        ParseTuple が指定されたタプルの型を解析できません。

  3.4.4.  ValidateCIS

       int CardServices(ValidateCIS, client_handle_t client, cisinfo_t *cisinfo);

  cisinfo_t 構造体は次のとおり:

       typedef struct cisinfo_t {
               u_long          Chains;
       } cisinfo_t;

  ValidateCIS はカードが妥当なカード情報構造体(CIS) を持っているか検証し
  ます。Chains に見つかったタプルの数が返ってきます。CIS が解釈不能だと
  思えたら、Chains を 0 に設定します。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効です。

     CS_OUT_OF_RESOURCE
        カードサービスはメモリ領域をカードの CIS に割り付けできませんで
        した。

  3.5.  メモリ領域制御

  それぞれのソケットは4つ以上のメモリ領域を持て、PCMCIA メモリの一部をホ
  ストのアドレス空間に割り付けます。PCMCIA 機器は一般メモリと属性メモリ
  の両方に 16MB 程度アクセスできます。領域は一般に 2 のべき乗の大きさを
  していますが、ホストとカードのアドレス空間では領域の大きさの倍数に境界
  調整しています。

  メモリ領域は RequestWindow を呼び出して初期化します。いくつかの領域属
  性は ModifyWindow を使用して変更を行ないます。領域に割り付けられたカー
  ドメモリの一部は MapMemPage を使用して変更します。領域は ReleaseWindow
  で解放します。他のカードサービス関数とは異なって、client_handle_t ハン
  ドルでなく window_handle_t ハンドルで動作します。

  3.5.1.  RequestWindow

       int CardServices(RequestWindow, client_handle_t *handle, win_req_t *req);

  win_req_t 構造体は次のとおり:

       typedef struct win_req_t {
               u_long          Attributes;
               caddr_t         Base;
               u_long          Size;
               u_long          AccessSpeed;
       } win_req_t;

  RequestWindow はカードメモリの領域をシステムメモリへ割り当てます。呼ぶ
  前に、handle 変数が有効なクライアントハンドルを指すようにします。返っ
  てきたら、この後呼ばれる ModifyWindow、MapMemPage と ReleaseWindow で
  使用する window_handle_t ハンドルで置き換えられます。

  Attributes で指定できるフラグは次のとおり:

     WIN_MEMORY_TYPE
        この変数は一般メモリでは WIN_MEMORY_TYPE_CM 、属性メモリでは
        WIN_MEMORY_TYPE_AM のいずれかになります。

     WIN_DATA_WIDTH
        16 ビットアクセスでは WIN_DATA_WIDTH_16 、8 ビットアクセスなら
        WIN_DATA_WIDTH_8 のいずれかになります。

     WIN_ENABLE
        これを設定すると、領域が使用可能になります。

     WIN_USE_WAIT
        制御装置がカードの MWAIT 信号を監視するように指定します。

  Base はシステムメモリでの領域の基底アドレスを指定します。NULL の場合
  は、カードサービスは最初に見つかった利用可能な領域のアドレスを設定しま
  す。Size は領域の大きさをバイト単位で指定します。AccessSpeed はメモリ
  アクセススピードをナノ秒単位で指定します。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効です。

     CS_NO_CARD
        クライアントに割り付けたソケットは現在使われていません。

     CS_BAD_ATTRIBUTE
        サポートしていない領域の属性が指定されました。

     CS_OUT_OF_RESOURCE
        そのソケットに対するメモリ領域の最大数は使用済みです。

     CS_IN_USE
        RequestWindow はシステムメモリのあき領域が見つけられません。

  3.5.2.  ModifyWindow

       int CardServices(ModifyWindow, window_handle_t, modwin_t *);

  modwin_t 構造体は次のとおり:

       typedef struct modwin_t {
               u_long          Attributes;
               u_long          AccessSpeed;
       } modwin_t;

  ModifyWindow は事前に呼んだ RequestWindow から返ってきた領域ハンドルの
  属性を変更します。変更できる属性は次のとおり:

     WIN_MEMORY_TYPE
        この変数は一般メモリでは WIN_MEMORY_TYPE_CM 、属性メモリでは
        WIN_MEMORY_TYPE_AM のいずれかになります。

     WIN_DATA_WIDTH
        16 ビットアクセスでは WIN_DATA_WIDTH_16 、8 ビットアクセスなら
        WIN_DATA_WIDTH_8 のいずれかになります。

     WIN_ENABLE
        これを設定すると、領域が使用可能になります。

  AccessSpeed はメモリアクセススピードをナノ秒単位で指定します。

  戻り値 :

     CS_BAD_HANDLE
        領域ハンドルは無効です。

  3.5.3.  MapMemPage

       int CardServices(MapMemPage, window_handle_t, memreq_t *);

  memreq_t 構造体は次のとおり:

       typedef struct memreq_t {
               u_long          CardOffset;
               page_t          Page;
       } memreq_t;

  MapMemPage は CardOffset で割り付けたメモリ領域の基底アドレスをカード
  メモリのアドレスに設定します。領域は RequestWindow を呼び出して作成し
  ておきましょう。Page 変数はこの版では実装していませんので、0 に設定し
  てください。

  戻り値 :

     CS_BAD_HANDLE
        領域ハンドルは無効です。

     CS_BAD_PAGE
        Page の値がゼロ以外です。

  3.5.4.  ReleaseWindow

       int CardServices(ReleaseWindow, window_handle_t handle);

  ReleaseWindow は事前に RequestWindow で割り当てたメモリ領域を解放しま
  す。

  戻り値 :

     CS_BAD_HANDLE
        領域ハンドルは無効です。

  3.6.  大容量メモリサービス

  大容量メモリサービスはメモリ領域サービスで提供しているインターフェース
  よりメモリ領域にアクセスするインターフェースはより高度になっています。
  大容量メモリ呼び出しを使用するクライアントは背後にあるメモリの機構やア
  クセス法についての知識は必要ありません。機器に依存したプログラムはメモ
  リテクノロジドライバ(MTD) と呼ばれる特殊なカードサービスに入れていま
  す。

  3.6.1.  RegisterMTD

       int CardServices(RegisterMTD, client_handle_t handle, mtd_reg_t *reg);

  mtd_reg_t データ 構造体は次のとおり:

       typedef union mtd_reg_t {
               u_long          Attributes;
               u_long          Offset;
               u_long          MediaID;
       } mtd_reg_t;

  RegisterMTD はカードサービスにクライアントの MTD が指定したメモリ領域
  を扱う要求を通知します。Offset 変数はメモリ領域の開始アドレスを指定し
  ます。Attributes で指定できる内容は次のとおり:

     REGION_TYPE
        一般メモリでは REGION_TYPE_CM もしくは 属性メモリでは
        REGION_TYPE_AM のどちらかを指定します。

  MediaID 変数はカードサービスが書き込みます。MTD にこのメモリ領域を参照
  する時の要求の一部として渡します。

  一旦、MTD がこの呼び出しでメモリ領域に結合すると、DeregisterClient を
  呼び出すまで結合しつづけます。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効です。

     CS_BAD_OFFSET
        有効なカードのメモリ領域とオフセットが一致しないか、他の MTD が
        既にこのメモリ領域を登録しています。

  3.6.2.  GetFirstRegion, GetNextRegion

       int CardServices(GetFirstRegion, client_handle_t handle, region_info_t *region);
       int CardServices(GetNextRegion, client_handle_t handle, region_info_t *region);

  region_info_t データ 構造体は次のとおり:

       typedef union region_info_t {
               u_long          Attributes;
               u_long          CardOffset;
               u_long          RegionSize;
               u_long          AccessSpeed;
               u_long          BlockSize;
               u_long          PartMultiple;
               u_char          JedecMfr, JedecInfo;
               memory_handle_t next;
       } region_info_t;

  GetFirstRegion と GetNextRegion はカードの CISTPL_DEVICE,
  CISTPL_JEDEC, と CISTPL_DEVICE_GEO タプルの情報を要約しま
  す。CardOffset は領域の開始アドレスを提供します。RegionSize は領域の大
  きさをバイト単位で提供します。 AccessSpeed は機器のサイクル時間をナノ
  秒単位で提供します。 BlockSize は消去ブロックの大きさをバイト単位で提
  供し、PartMultiple は区画の最小の大きさを BlockSize 単位で提供しま
  す。JedecMfr と JedecInfo は 領域が JEDEC に準拠している証明情報を提供
  します。

  Attributes で指定できる変数は次のとおり:

     REGION_TYPE
        一般メモリでは REGION_TYPE_CM もしくは 属性メモリでは
        REGION_TYPE_AM のどちらかを指定します。

  これらの呼び出しが MTD クライアントによって行なわれた時、BindMTD を呼
  び出したクライアントに BindMTD が返すメモリを結合させます。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効です。

     CS_NO_MORE_ITEMS
        メモリ領域が定義されていません。

  3.6.3.  OpenMemory

       int CardServices(OpenMemory, client_handle_t *handle, open_mem_t *req);

  pen_mem_t 構造体は次のとおり:

       typedef struct open_mem_t {
               u_long          Attributes;
               u_long          Offset;
       } open_mem_t;

  OpenMemory は他の大容量メモリサービス経由でメモリ領域をアクセスするハ
  ンドルを獲得します。Offset 変数はアクセスするメモリ領域の基底アドレス
  を指定します。うまくいったら、クライアントハンドル引数は新しいメモリハ
  ンドルに置き換わります。

  Attributes で指定できる変数は次のとおり:

     MEMORY_TYPE
        この引数は一般メモリでは MEMORY_TYPE_CM 、属性メモリでは
        MEMORY_TYPE_AM のいずれかになります。

     MEMORY_EXCLUSIVE
        クライアントがメモリ領域を排他的にアクセスする為に指定します。

  戻り値 :

     CS_BAD_HANDLE
        領域ハンドルが無効です。

     CS_BAD_OFFSET
        有効な領域のオフセットが指定されていないか、大容量メモリ要求と関
        連づける MTD の大容量メモリサービスに領域がありません。

  3.6.4.  CloseMemory

       int CardServices(CloseMemory, memory_handle_t handle);

  CloseMemory は 以前に呼び出した OpenMemory が返したメモリハンドルを解
  放します。クライアントは DeregisterClient を呼び出す前に全てのメモリハ
  ンドルを解放しましょう。

  戻り値 :

     CS_BAD_HANDLE
        メモリハンドルが無効です。

  3.6.5.  ReadMemory, WriteMemory

       int CardServices(ReadMemory, memory_handle_t handle mem_op_t *req, caddr_t buf);
       int CardServices(WriteMemory, memory_handle_t handle, mem_op_t *req, caddr_t buf);

  mem_io_t 構造体は次のとおり:

       typedef struct mem_op_t {
               u_long          Attributes;
               u_long          Offset;
               u_long          Count;
       } mem_op_t;

  ReadMemory と WriteMemory は以前に呼び出した OpenMemory が返した指定し
  たメモリハンドルで指定したカードメモリ領域を読み書きします。 Offset 変
  数はカードメモリ領域の開始アドレスを指定します。 Count 変数は転送する
  バイト数を指定します。buf 変数は ReadMemory 操作用の対象又は
  WriteMemory 操作の対象となるホストメモリのバッファを指します。

  Attributes で指定できる変数は次のとおり:

     MEM_OP_BUFFER
        ホストバッファがユーザメモリセグメントにある時は
        MEM_OP_BUFFER_USER もしくはホストバッファがカーネルメモリにある
        時は MEM_OP_BUFFER_KERNEL を指定します。

     MEM_OP_DISABLE_ERASE
        カード領域を書き込む前に消去しないように指定します。

     MEM_OP_VERIFY
        書き込みの時に検証するときに指定します。

  戻り値 :

     CS_BAD_HANDLE
        領域ハンドルが無効です。

     CS_BAD_OFFSET
        指定したカードオフセットがメモリ領域の終了アドレスを越えていま
        す。

     CS_BAD_SIZE
        指定した転送サイズがメモリ領域の終了アドレスを越えています。

  3.6.6.  RegisterEraseQueue

       int CardServices(RegisterEraseQueue, client_handle_t *handle, eraseq_hdr_t *header);

  eraceq_hdr_t 構造体は次のとおり:

       typedef struct erase_queue_header_t {
               int             QueueEntryCount;
               eraseq_entry_t  *QueueEntryArray;
       } eraseq_hdr_t;

  この呼び出しはカードサービスの消去キューを登録します。 eraseq_handle_t
  ハンドルは *handle に返ります。クライアントが CheckEraseQueue を呼び出
  した時、カードサービスがキューを調べて新しい要求の非同期処理を開始しま
  す。

  eraseq_entry_t 構造体は次のとおり:

       typedef struct eraseq_entry_t {
               memory_handle_t Handle;
               u_char          State;
               u_long          Size;
               u_long          Offset;
               u_long          *Optional;
       } eraseq_entry_t;

  消去キューの登録には、Header 変数は以前に呼ばれた OpenMemory が返した
  メモリハンドルを入れます。State 変数は消去キューの状態を示します。次の
  値が定義されています。:

     ERASE_QUEUED
        新規に要求をした時クライアントが設定します。

     ERASE_IDLE
        登録がアクティブでない時クライアントが設定します。

     ERASE_PASSED
        消去がうまく完了した時 MTD が設定します。

     ERASE_FAILED
        消去に失敗した時 MTD が設定します。

     ERASE_MEDIA_WRPROT
        領域が書き込み禁止になっている事を示しています。

     ERASE_NOT_ERASABLE
        領域が消去をサポートしていない事を示しています。

     ERASE_BAD_OFFSET
        消去が消去ブロックの境界で始まっていない事を示しています。

     ERASE_BAD_SIZE
        要求している消去の大きさが消去ブロックの倍数になっていない事を示
        しています。

     ERASE_BAD_SOCKET
        MTD がカードがない事を示しています。

  加えて、ERASE_IN_PROGRESS() マクロは処理している消去の State の値の真
  の状態を返します。

  Size 変数は消去要求を大きさをバイト単位で与えます。Offset 変数は領域の
  開始位置からのオフセットで与えます。大きさとオフセットは消去ブロック境
  界に境界調整しておきます。Optional 変数はカードサービスでは使われてい
  ませんが、クライアントドライバで使われています。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効です。

  3.6.7.  DeregisterEraseQueue

       int CardServices(DeregisterEraseQueue, eraseq_handle_t handle);

  DeregisterEraseQueue は以前に RegisterEraseQueue により登録されたキュ
  ーを解放します。指定されたキューに処理中のキューがある場合は、呼び出し
  は失敗します。

  戻り値 :

     CS_BAD_HANDLE
        消去キューハンドルが無効です。

     CS_BUSY
        消去キューが消去処理中です。

  3.6.8.  CheckEraseQueue

       int CardServices(CheckEraseQueue, eraseq_handle_t handle);

  この呼び出しは以前に RegisterEraseQueue で登録された新しい消去要求をカ
  ードサービスに通知します。

  例によって、クライアントは最初にそれぞれのキューに ERASE_IDLE 状態を割
  り当てます。キューに新しい要求が追加された時は、クライアントはキューの
  状態を ERASE_QUEUED にして、CheckEraseQueue を呼びます。クライアントが
  消去完了イベントを受け取った場合は、要求が成功したか状態変数を確認しま
  す。

  戻り値 :

     CS_BAD_HANDLE
        消去キューハンドルが無効です。

  3.7.  各種呼び出し

  3.7.1.  GetCardServicesInfo

       int CardServices(GetCardServicesInfo, servinfo_t *info);

  servinfo_t 構造体は次のとおり:

       typedef struct servinfo_t {
               char            Signature[2];
               u_long          Count;
               u_long          Revision;
               u_long          CSLevel;
               char            *VendorString;
       } servinfo_t;

  GetCardServicesInfo はこのカードサービスのバージョンの修正情報を返しま
  す。Signature は ``CS'' に設定します。Count は現状構成のソケットの数を
  設定します。 Revision にはカードサービスパッケージの修正レベルを設定し
  CSLevel は PCMCIA 標準に準じたレベルを設定します。BCD 数で表記していま
  す。VendorString は RCS 識別文字列へのポインタを設定します。

  この呼び出しは常に成功します。

  3.7.2.  AccessConfigurationRegister

       #include "cisreg.h"

       int CardServices(AccessConfigurationRegister, client_handle_t handle, conf_reg_t *reg);

       <tt/conf_reg_t/ 構造体は次のとおり:
       typedef struct conf_reg_t {
               u_char          Function;
               u_long          Action;
               off_t           Offset;
               u_long          Value;
       } conf_reg_t;

  あるカードの機能に割り当てられた一般的なクライアントでは、Function 変
  数は無視されます。BIND_FN_ALL に割り当てられたクライアントでは、この変
  数はアクセスする機能の構成レジスタを指定します。

  Action 変数は次の内の一つを指定します。

     CS_READ
        指定した構成レジスタを読み出して Value に値を返します。

     CS_WRITE
        指定した構成レジスタに Value の値を書き込みます。

  AccessConfigurationRegister は構成レジスタ領域の開始アドレスからの
  Offset 分のオフセットに CIS 構成レジスタの1バイトを読み書きします。
  RequestConfiguration で構成したソケットだけで使えます。

  cistpl.h で定義している Offset の値は次のとおり :

     CISREG_COR
        構成オプションレジスタ(COR)。

     CISREG_CCSR
        カード構成(CC) と状態レジスタ(SR)。

     CISREG_PRR
        ピン代替レジスタ(PRR)。

     CISREG_SCR
        ソケット(S) とコピーレジスタ(CR)。

     CISREG_ESR
        拡張状態レジスタ(ESR)。

     CISREG_IOBASE0..CISREG_IOBASE3
        入出力基底レジスタ。

     CISREG_IOSIZE
        入出力サイズレジスタ。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが無効です。

     CS_BAD_ARGS
        指定した Action はサポートされていません。

     CS_CONFIGURATION_LOCKED
        実際に構成がロックされている事を意味しています。

     CS_OUT_OF_RESOURCE
        カードサービスはカードの構成レジスタをアクセスするメモリ領域を割
        り当てを使えないようにします。

  3.7.3.  AdjustResourceInfo

       int CardServices(AdjustResourceInfo, client_handle_t handle, adjust_t *adj);

  adjust_t 構造体は次のとおり:

  typedef struct adjust_t {
          u_long          Action;
          u_long          Resource;
          u_long          Attributes;
          union {
                  struct memory {
                          caddr_t         Base;
                          u_long          Size;
                  } memory;
                  struct io {
                          ioaddr_t        BasePort;
                          ioaddr_t        NumPorts;
                          u_long          IOAddrLines;
                  } io;
                  struct irq {
                          u_long          IRQ;
                  } irq;
          } resource;
  } adjust_t;

  AdjustResourceInfo はカードサービスに資源を PCMCIA デバイスが割り当て
  るか割り当てないかを問い合わせます。通常の Linux の資源管理システム (
  *_region が呼び出す入出力ポート、割り込み割り当て)はカードサービスで管
  理していますが、この関数はユーザに他の管理レベルを提供します。

  Action 変数は次の内の一つを指定します。

     ADD_MANAGED_RESOURCE
        カードサービス管理下におく資源を指定します。従って PCMCIA デバイ
        スが割り当てるものです。

     REMOVE_MANAGED_RESOURCE
        カードサービス管理から削除する資源を指定します．

  初期化時に、カードサービス全ての使用可能な割り込みを使用できるようにし
  ますが、入出力ポートとメモリ領域は ADD_MANAGED_RESOURCE で明示的に指定
  する必要があります。

  Resource 変数は次の値をとります。:

     RES_MEMORY_RANGE
        adj->resource.memory で記述したメモリの範囲を指定します。

     RES_IO_RANGE
        adj->resource.io で記述した入出力ポートを指定します。

     RES_IRQ
        adj->resource.irq で記述した割り込みを指定します。

  Attributes で指定できる内容は次のとおり:

     RES_RESERVED
        PCMCIA ドライバ用に要求し，予約した資源を示しています。利用可能
        なカードサービスの問い合わせしたデバイス用の資源ではありません。
        これは未だ実装していません。

  戻り値 :

     CS_UNSUPPORTED_FUNCTION
        指定した Action と Resource はサポートしていません。

     CS_BAD_BASE
        指定した入出力アドレスは範囲外です。
     CS_BAD_SIZE
        指定したメモリまたは入出力領域のサイズは範囲外です。

     CS_IN_USE
        指定した割り込みは現在カードサービスクライアントが使用中です。

  3.7.4.  ReportError

       int CardServices(ReportError, client_handle_t handle, error_info_t *err);

  error_info_T 構造体の定義は次のとおり:

       typedef struct error_info_t {
              int             func;
              int             retcode;
       } error_info_t;

  ReportError は指定した prefix 文字列とカードサービスの機能コードと戻り
  値を含んだカーネルエラーメッセージを生成します。例を挙げると :

       error_info_t err = { RequestIO, CS_BAD_HANDLE };
       CardServices(ReportError, handle, &err);

  は次のメッセージを生成します。:

       serial_cs: RequestIO: Bad handle

  この呼び出しは常に正常終了します。

  4.  カード情報構造体 (CIS) の定義

  4.1.  CIS タプルの定義

  カードサービスタプル解析 (Card Services ParseTuple) 機能は、
  GetTupleData で得た生の CIS タプルを解析し、それぞれのタプルの種類に依
  存した形式でタプルの内容を返します。

  #include "cistpl.h"

  4.1.1.  CISTPL_CHECKSUM

  cistpl_checksum_t 構造体の定義は次のとおり:

       typedef struct cistpl_checksum_t {
               u_short         addr;
               u_short         len;
               u_char          sum;
       } cistpl_checksum_t;

  4.1.2.  CISTPL_LONGLINK_A, CISTPL_LONGLINK_C, CISTPL_LINKTARGET,
  CISTPL_NOLINK

  cistpl_longlink_t 構造体の定義は次のとおり:

       typedef struct cistpl_longlink_t {
               u_long          addr;
       } cistpl_longlink_t;

  これらのタプルは属性や、一般メモリなどへの他の CIS タプルチェーンへの
  ポインタになっています。それぞれの CIS タプルは、少なくとも 1 以上の長
  さのリンクです。CISTPL_LONGLINK_A タプルは、アトリビュートメモリへのポ
  インタであり、CISTPL_LONGLINK_C タプルは一般メモリへのポインタです。属
  性メモリのアドレス 0 から始まる標準 CIS チェーンは、同時に一般メモリの
  アドレス 0 へのリンクも意味しています。(@@) このようなデフォールトのリ
  ンクをキャンセルしたい場合には CISTPL_NOLINK というタプルを使います。

  ロングリンクによって指されるチェーンの最初のタプル
  は、CISTPL_LINKTARGET でなければなりません。CS タプルを扱うコードは自
  動的にロングリンクをたどり、リンク先を(ターゲット)を調べま
  す。GetNextTuple によって、 TUPLE_RETURN_LINK 属性が指定されていない限
  り、これらのタプルはユーザーからは見えません。

  4.1.3.  CISTPL_LONGLINK_MFC

  cistpl_longlink_mfc_t 構造体の定義は次のとおり:

  typedef struct cistpl_longlink_mfc_t {
          int     nfn;
          struct {
                  u_char  space;
                  u_long  addr;
          } fn[CISTPL_MAX_FUNCTIONS;
  } cistpl_longlink_mfc_t;

  このタプルはマルチファンクション(多機能)カードを識別するのに使われま
  す。それぞれの機能ごとの CIS チェーンへのロングリンクポインタを指定し
  ます。 space 変数は、属性の場合 CISTPL_MFC_ATTR が、一般メモリの場合に
  は CISTPL_MFC_COMMON が指定されます。

  4.1.4.  CISTPL_DEVICE, CISTPL_DEVICE_A

  cistpl_device_t 構造体の定義は次のとおり:

       typedef struct cistpl_device_t {
               int             ndev;
               struct device_info {
                       u_char          type;
                       u_char          wp;
                       u_long          speed;
                       u_long          size;
               } dev[CISTPL_MAX_DEVICES];
       } cistpl_device_t;

  CISTPL_DEVICE タプルはカードの一般メモリのアドレス領域に関して記述して
  います。CISTPL_DEVICE_A タプルは属性メモリ領域を記述しています。 type
  フラグはその領域に関するメモリデバイスの種類を示します。 wp フラグは、
  その領域がライトプロテクトされているかどうかを示します。 speed 変数は
  ナノ秒単位で、size はバイト単位で示されます。アドレス領域はアドレス 0
  番地から連続した領域であることが仮定されています。次のようなデバイスタ
  イプが定義されています。

     CISTPL_DTYPE_NULL
        なにもデバイスが存在しない、または、そのカードのアドレス空間の中
        で「穴」であることを示します。

     CISTPL_DTYPE_ROM
        マスク ROM です。

     CISTPL_DTYPE_OTPROM
        一度だけ書き込み可能な ROM です。(訳注:原文の 「One-type」は
        「One-time」の間違いであると思います。)

     CISTPL_DTYPE_EPROM
        紫外線消去可能な PROM です。(UV-EPROM)

     CISTPL_DTYPE_EEPROM
        電気的に消去可能な PROM です。

     CISTPL_DTYPE_FLASH
        フラッシュ EPROM です。

     CISTPL_DTYPE_SRAM
        スタティックまたは不揮発性の RAM です。

     CISTPL_DTYPE_DRAM
        ダイナミックまたは揮発性の RAM です。

     CISTPL_DTYPE_FUNCSPEC
        機能定義可能なデバイスであることを示します。つまり、汎用の記憶で
        はなくて、例えば メモリーマップドI/O デバイスやバッファのような
        ものです。

     CISTPL_DTYPE_EXTEND
        拡張型のデバイスタイプを示します。これは将来の拡張のために予約さ
        れています。

  4.1.5.  CISTPL_VERS_1

  cistpl_vers_1_t 構造体の定義は次のとおり:

       typedef struct cistpl_vers_1_t {
               u_char          major;
               u_char          minor;
               int             ns;
               int             ofs[CISTPL_VERS_1_MAX_PROD_STRINGS];
               char            str[254];
       } cistpl_vers_1_t;

  ns 変数は、このタプルの中に含まれている製品情報文字列の長さを示してい
  ます。文字列情報は str という配列に格納されています。それぞれの文字列
  はヌル文字で終っており、ofs はそれぞれの文字列の始まりへのオフセットを
  示しています。

  4.1.6.  CISTPL_ALTSTR

  cistpl_altstr_t 構造体の定義は次のとおり:

       typedef struct cistpl_altstr_t {
               int             ns;
               int             ofs[CISTPL_ALTSTR_MAX_STRINGS];
               char            str[254];
       } cistpl_altstr_t;

  ns 変数は、このタプルに含まれている代替用語文字列の数を示しています。
  実際の文字列は、str 配列に格納されています。それぞれの文字列はヌル文字
  で終っており、ofs はそれぞれの文字列の始まりへのオフセットを示していま
  す。

  4.1.7.  CISTPL_JEDEC_C, CISTPL_JEDEC_A

  cistpl_jedec_t 構造体の定義は次のとおり:

       typedef struct cistpl_jedec_t {
               int             nid;
               struct jedec_id {
                       u_char  mfr;
                       u_char  info;
               } id[CISTPL_MAX_DEVICES];
       } cistpl_jedec_t;

  jedec_id (JEDEC 識別子) は、PCMCIA メモリを実現するために使われる特定
  のデバイスタイプを記述しています。 nid 変数はこのタプルの中にいくつの
  jedec_id が含まれているかを示します。このjedec_id (JEDEC identifier)
  と、それに対応する CISTPL_DEVICE タプルの中のデバイス定義は、一対一の
  対応がとれていなければなりません。

  4.1.8.  CISTPL_CONFIG

  cistpl_config_t 構造体の定義は次のとおり:

       typedef struct cistpl_config_t {
               u_char          last_idx;
               u_long          base;
               u_long          rmask[4];
               u_char          subtuples;
       } cistpl_config_t;

  last_idx 変数は、構成情報テーブルの一番最後の項目のインデックスを示し
  ます。 base 変数は、属性メモリ中にあるカードの構成情報レジスタへのオフ
  セットを示します。 rmask 配列はどの構成情報レジスタが存在するのかを示
  すビットマスクです。 rmask[0] のビット 0 は、COR に対応し、ビット 1 は
  CCSR に対応する...  といった具合です。subtuple 変数は、通常のタプルの
  内容に続いて何バイトのタプルが存在するか、を示しています。

  4.1.9.  CISTPL_CFTABLE_ENTRY

  cistpl_cftable_entry_t 構造体の定義は次のとおり:

  typedef struct cistpl_cftable_entry_t {
          u_char          index;
          u_char          flags;
          u_char          interface;
          cistpl_power_t  vcc, vpp1, vpp2;
          cistpl_timing_t timing;
          cistpl_io_t     io;
          cistpl_irq_t    irq;
          cistpl_mem_t    mem;
          u_char          subtuples;
  } cistpl_cftable_entry_t;

  CISTPL_CFTABLE_ENTRY 構造体はそのカードに対する完全な動作モードを記述
  しています。多くの部分が省略可能です。index 変数はこの動作モードについ
  ての構成情報インデックスを示します。カードの Configuration Option
  Register にこの値を書き込むことでこのモードを選択することができま
  す。flags 変数には、次の値が定義されています:

     CISTPL_CFTABLE_DEFAULT
        デフォールトの構成情報テーブルの項目であることを示します。

     CISTPL_CFTABLE_BVDS
        この設定は ピン代替レジスタ 中で BVD1 と BVD2 信号を実装している
        ことを示します。

     CISTPL_CFTABLE_WP
        この設定は ピン代替レジスタ 中で 書き込み禁止を実装していること
        を示します。

     CISTPL_CFTABLE_RDYBSY
        この設定は ピン代替レジスタ 中で Ready/Busy 信号を実装しているこ
        とを示します。

     CISTPL_CFTABLE_MWAIT
        メモリーアクセス中に、WAIT 信号を使う必要があることを示します。

     CISTPL_CFTABLE_AUDIO
        この設定はオーディオ信号を発生し、ホストシステムのスピーカーに出
        力することができることを示します。

     CISTPL_CFTABLE_READONLY
        この設定ではカード中に読みだし専用のメモリ領域が存在することを示
        します。

     CISTPL_CFTABLE_PWRDOWN
        カード構成情報と状態レジスタ を通じて、パワーダウンモードをサポ
        ートしていることを示します。

  cistpl_power_t 構造体の定義は次のとおり:

       typedef struct cistpl_power_t {
               u_char          present;
               u_char          flags;
               u_long          param[7];
       } cistpl_power_t;

  present 変数はビットマップ形式になっており、この電源信号に関して、どの
  パラメータが存在しているか、を示します。次のようなインデックスが定義さ
  れています:

     CISTPL_POWER_VNOM
        標準的な電源電圧

     CISTPL_POWER_VMIN
        最低電源電圧

     CISTPL_POWER_VMAX
        最高電源電圧

     CISTPL_POWER_ISTATIC
        連続供給が必要な電源電流

     CISTPL_POWER_IAVG
        1 秒間を通じて平均した最大供給電流

     CISTPL_POWER_IPEAK
        10m 秒間を通じて平均した最大供給電流

     CISTPL_POWER_IDOWN
        パワーダウンモードで必要な供給電流

  電圧は 10 マイクロボルト単位、電流は 100 ナノアンペア単位で表されてい
  ます。

  cistpl_timing_t 構造体の定義は次のとおり:

       typedef cistpl_timing_t {
               u_long          wait, waitscale;
               u_long          ready, rdyscale;
               u_long          reserved, rsvscale;
       } cistpl_timing_t;

  それぞれの時間はナノ秒を基底とした値と、尺度乗数から構成されています。
  定義されていない(Unspecified) 時間の値は 0 です。

  cistpl_io_t 構造体の定義は次のとおり:

       typedef struct cistpl_io_t {
               u_char          flags;
               int             nwin;
               struct {
                       u_long          base;
                       u_long          len;
               } win[CISTPL_IO_MAX_WIN;
       } cistpl_io_t;

  nwin は 入出力領域の数を示します。それぞれの領域は基底アドレス: base、
  バイト単位での長さ: len で記述されます。 flags では、次のようなビット
  マップが定義されています:

     CISTPL_IO_LINES_MASK
        このカードでデコードされる入出力の本数。

     CISTPL_IO_8BIT
        このカードは 16 ビットの入出力レジスタに対して、独立した 8 ビッ
        トアクセスをサポートしていることを示す。

     CISTPL_IO_16BIT
        このカードは入出力レジスタに対して 16 ビットアクセスをサポートし
        ていることを示す。

  cistpl_irq_t 構造体の定義は次のとおり:

       typedef struct cistpl_irq_t {
               u_long          IRQInfo1;
               u_long          IRQInfo2;
       } cistpl_irq_t;

  IRQInfo1 では次のビットマップが定義されています:

     IRQ_MASK
        このカードが使うべき割り込み番号を示す。

     IRQ_NMI_ID, IRQ_IOCK_ID, IRQ_BERR_ID,
        IRQ_VEND_ID" IRQ_INFO2_VALID がセットされている時、これらのビッ
        トマップはそれぞれの特殊割り込みがこのカードに割り当てられている
        かどうかを示す。これら4つのフラグはそれぞれ、マスク不可能、 IO
        チェック、バスエラー、ベンダー特有の割り込みを意味します。

     IRQ_INFO2_VALID
        IRQInfo2 が、許可された、正しい割り込み番号を含んでいることを示
        す。

     IRQ_LEVEL_ID
        このカードはレベル割り込みをサポートしていることを示す。

     IRQ_PULSE_ID
        このカードはパルス割り込みをサポートしていることを示す。

     IRQ_SHARE_ID
        このカードは割り込み共有をサポートしていることを示す。

  IRQInfo1 が 0 の場合、割り込みに関する情報は存在しないことを意味しま
  す。

  cistpl_mem_t 構造体の定義は次のとおり:

       typedef struct cistpl_mem_t {
               u_char          nwin;
               struct {
                       u_long          len;
                       u_long          card_addr;
                       caddr_t         host_addr;
               } win[CISTPL_MEM_MAX_WIN;
       } cistpl_mem_t;

  nwin はメモリ領域の数を示す。それぞれの領域は、カードのメモリ空間中の
  アドレス: card_addr、ホストのメモリ空間中のアドレス: host_addr、バイト
  単位での長さ: len で定義される。ホストアドレスが 0 の場合、領域の位置
  は任意 (arbitrary) であることを意味する。

  4.1.10.  CISTPL_MANFID

  cistpl_manfid_t 構造体の定義は次のとおり:

       typedef struct cistpl_manfid_t {
               u_short         manf;
               u_short         card;
       } cistpl_manfid_t;

  manf 変数はそのカードの製造業者を表します。 card 変数はそれぞれのベン
  ダーによって定義され、カードの種類と、モデルを識別できるようにしなけれ
  ばなりません。

  4.1.11.  CISTPL_FUNCID

  cistpl_funcid_t 構造体の定義は次のとおり:

       typedef struct cistpl_funcid_t {
               u_char          func;
               u_char          sysinit;
       } cistpl_funcid_t;

  func 変数はそのカードの機能を表します。sysinit 変数はブート時にそのカ
  ードがどのように設定されるべきかをビットマップフラグで示してます。

  次の機能が定義されています:

     CISTPL_FUNCID_MULTI
        マルチファンクション(多機能)カード

     CISTPL_FUNCID_MEMORY
        単純なメモリデバイス

     CISTPL_FUNCID_SERIAL
        シリアルポートまたはモデムデバイス

     CISTPL_FUNCID_PARALLEL
        パラレルポートデバイス

     CISTPL_FUNCID_FIXED
        固定ディスクデバイス(ハードディスクなど)

     CISTPL_FUNCID_VIDEO
        ビデオインターフェース

     CISTPL_FUNCID_NETWORK
        ネットワークアダプタ

     CISTPL_FUNCID_AIMS
        自動増分機能のある大容量記憶装置

  sysinit では次のフラグが定義されている:

     CISTPL_SYSINIT_POST
        システムのパワーオン初期化時にこのカードの設定を試みる必要がある
        ことを示す。

     CISTPL_SYSINIT_ROM
        このカードは、ブート時に設定する必要のあるシステム拡張 ROM を含
        んでいることを示す。

  4.1.12.  CISTPL_DEVICE_GEO

  cistpl_device_geo_t 構造体の定義は次のとおり:

       typedef struct cistpl_device_geo_t {
               int             ngeo;
               struct geo {
                       u_char          buswidth;
                       u_long          erase_block;
                       u_long          read_block;
                       u_long          write_block;
                       u_long          partition;
                       u_long          interleave;
               } geo[CISTPL_MAX_DEVICES];
       } cistpl_device_geo_t;

  erase_block, read_block, write_block の大きさは、それぞれ buswidth の
  値に interleave の値を乗じたバイト数を単位として表される。 partition
  の大きさは、erase_block の大きさを単位として表される。

  4.1.13.  CISTPL_VERS_2

  cistpl_vers_2_t 構造体の定義は次のとおり:

       typedef struct cistpl_vers_2_t {
               u_char          vers;
               u_char          comply;
               u_short         dindex;
               u_char          vspec8, vspec9;
               u_char          nhdr;
               int             vendor, info;
               char            str[244];
       } cistpl_vers_2_t;

  vers 変数は常に 0 でなければなりません。comply 変数は標準への準拠の度
  合を示しますが、同じく 0 でなければなりません。 dindex 変数は一般メモ
  リの最初の何バイトが予約されているかを示します。vspec8 と vspec9 変数
  にはベンダー特有の情報が含まれている場合があります。nhdr 変数はこのカ
  ード上にいくつの CIS のコピーが存在しているかを示します。 str 配列は、
  二つの文字列を含んでいます: ベンダーの名前と、このカードについて記述し
  ているなんらかの情報です。ベンダー名の文字列へのオフセットは vendor で
  示され、製品情報の文字列へのオフセットは info で示されます。

  4.1.14.  CISTPL_ORG

  cistpl_org_t 構造体の定義は次のとおり:

       typedef struct cistpl_org_t {
               u_char          data_org;
               char            desc[30];

  このタプルはメモリパーティッションのデータの構成を定義します。
  data_org には次の値が定義されています:

     CISTPL_ORG_FS
        このパーティッションはファイルシステムを含んでいます。

     CISTPL_ORG_APPSPEC
        このパーティッションはアプリケーション特有の形式です。

     CISTPL_ORG_XIP
        このパーティッションは「その場で実行」(Execute-In-Place)仕様に従
        います。

  desc 変数には、データの構成についての文字による記述が含まれています。

  4.2.  CIS 構成レジスタ

  PCMCIA 標準規格は、カードの属性メモリ空間中に、いくつかの標準的な構成
  情報レジスタを定義しています。これらのレジスタのうち、どのレジスタが実
  装されているかは、カードの CONFIG タプルに記述されています。これらの定
  義を使う必要のあるプログラムは次をインクルードする必要があります:

       #include "cisreg.h"

  4.2.1.  Configuration Option Register

  このレジスタに書き込むことによって、構成情報テーブルの項目を選択し、カ
  ードの入出力機能が使えるようになります。

  次のビット変数が定義されています:

     COR_CONFIG_MASK
        構成情報テーブルインデックスは、カードの現在の動作モードを指して
        いることを示す。

     COR_LEVEL_REQ
        このカードはレベル(エッジトリガー)割り込みを生成することを示しま
        す。これはデフォールトです。

     COR_SOFT_RESET
        このビットをセットすることで、「ソフト」リセット動作を実行しま
        す。カードをリセットしたい時には、ドライバはこのレジスタに直接に
        書き込むのではなく、ResetCard 呼び出しを使うべきです。

  4.2.2.  カードの構成情報と状態レジスタ

  次のビット変数が定義されています:

     CCSR_INTR_ACK
        このビットが設定されている場合、CCSR_INTR_PENDING ビットは陽にク
        リアされるまでセットされたままになります。

     CCSR_INTR_PENDING
        このカードが現在割り込み要求をしていることを示す。この信号は割り
        込み共有を目的として使われることもあります。

     CCSR_POWER_DOWN
        このビットをセットすると、カードに対してパワーダウンモードに入る
        ことを要求します。

     CCSR_AUDIO_ENA
        このビットをセットすると、カードのオーディオ出力を可能にします。

     CCSR_IOIS8
        このビットをセットすることで、このホストは 8 ビット入出力しか行
        なえないので、16 ビットの入出力は二回に分けた 8 ビット入出力で実
        行することを通知します。

     CCSR_SIGCHG_ENA
        このビットをセットすることで、カードが WP, READY, BVD1, BVD2 信
        号の変化を、SIGCHG 信号を通じて伝えるように要求します。

     CCSR_CHANGED
        このビットがセットされることで、ピン代替レジスタのいずれかのビッ
        トの状態が変化したことがホストに通知されます。

  4.2.3.  ピン代替レジスタ

  ソケットがメモリ/入出力モードで動作する時に使えなくなってしまう(ピン
  の) 信号をこのレジスタの中の信号で置き換えることができます。 (訳注: ピ
  ンが足りなくなってしまって、ソケット経由で引き出すことができなくなった
  信号をソフトウエア的にこのレジスタを通じて読み出すことができるという意
  味でしょう) このレジスタの中の信号のどれかが変化した時には通常、カード
  は SIGCHG 信号をアサートし、ドライバはこのレジスタを読み出すことで、何
  が起きたのかを知ることができます。

  次のビット変数が定義されています:

     PRR_WP_STATUS
        書き込み信号の現在の状態。

     PRR_READY_STATUS
        レディ信号の現在の状態。

     PRR_BVD2_STATUS
        電池警告信号の現在の状態。

     PRR_BVD1_STATUS
        電池切れ信号の現在の状態。

     PRR_WP_EVENT
        最後に PRR レジスタが読み出されてから、書き込み禁止信号が変化し
        たことを示す。

     PRR_READY_EVENT
        最後に PRR レジスタが読み出されてから、レディ信号が変化したこと
        を示す。

     PRR_BVD2_EVENT
        最後に PRR レジスタが読み出されてから、電池警告信号が変化したこ
        とを示す。

     PRR_BVD1_EVENT
        最後に PRR レジスタが読み出されてから、電池切れ信号が変化したこ
        とを示す。

  このレジスタは書き込みも可能です。この場合には STATUS ビットはマスクと
  して機能します。つまり、その STATUS ビットがセットされている場合には、
  対応するEVENT のビットが書き込みによって更新されます。

  4.2.4.  ソケットとコピーレジスタ

  このレジスタは、いくつかの同じカードが同じ範囲の入出力ポートを共有する
  ような設定を可能にするような場合や、いくつかのデバイスを制御する ISA
  バスのカードをエミュレートする場合に使われます。例えば、一枚の ISA ハ
  ードディスクコントローラは、入出力ポートにドライブ番号を書き込むことで
  複数のドライブを制御することができます。何枚かの PCMCIA ドライブカード
  によってこのようなコントローラをエミュレートするためには、どの入出力操
  作がどれに対するものであるかを識別できるように、それぞれのカードが自分
  がどのドライブであるかを「知る」必要があります。

  次のビット変数が定義されています:

     SCR_SOCKET_NUM
        カードの位置するソケット番号を表している必要があります。

     SCR_COPY_NUM
        複数の同じカードがシステムに存在する時には、この変数はそれらのカ
        ードのどれであるのかを識別するための特有な番号に設定されている必
        要があります。

  4.2.5.  拡張状態レジスタ

  次のビット変数が定義されています:

     ESR_REQ_ATTN_ENA
        セットされると、ESR_REQ_ATTN ビットがセットされた時に
        CCSR_CHANGED ビットもセットされるのと同様にどうしても状態変化割
        り込みが発生します。

     ESR_REQ_ATTN
        モデムへ着信があったときなど、なんらかのカードイベントが発生した
        ことを示します。

  5.  カードサービスイベントの扱いについて

  カードサービスイベントはいくつかの情報源を持っています。:

  o  カードの状態変更が下位のソケットドライバから報告されました。

  o  カードサービス自身が人為的なイベントを発生させました。

  o  アドバンスドパワーマネージメント(APM) のイベント。

  o  その他のカードサービスクライアントが発生させたイベント。

  ソケットドライバのイベントは割り込み駆動またはポーリングのどちらかとな
  ります。

  5.1.  イベントハンドラの操作

  カードサービスがイベントが発生した事を認識した時に、それぞれのクライア
  ントがイベント通知を受けたかイベントマスクを調査します。カードサービス
  にクライアントか登録された時、イベントハンドラの回収(callback)関数を指
  定します。このハンドラは次の様式をしています。:

       int (*event_handler)(event_t event, int priority, event_callback_args_t *args);

  priority 変数は通常のイベント用の CS_EVENT_PRI_LOW か即時応答要求のイ
  ベント用の CS_EVENT_PRI_HIGH なのかを設定します。高優先順位のイベント
  のみ CS_EVENT_CARD_REMOVAL を設定します。クライアントイベントハンドラ
  はこの高優先順位のイベントを特に出来るだけ速くカードサービスが他のクラ
  イアントに通知出来るように処理します。

  event_callback_args_t 構造体の定義は次のとおり:

       typedef struct event_callback_args_t {
               client_handle_t         client_handle;
               void                    *info;
               void                    *mtdrequest;
               void                    *buffer;
               void                    *misc;
               void                    *client_data;
       } event_callback_args_t;

  client_handle メンバはイベントに対応するソケットのクライアントのハンド
  ラを設定します。この方法はドライバがいくつかのソケットと結合している場
  合に有益です。info 変数は現状では ResetCard へ渡す呼出しの終了状態を返
  すのに使われるだけです。client_data 変数は該当するデバイスと関連するロ
  ーカルなデータ構造体を指すのにドライバが使います。他の変数は使われてい
  ません。

  5.2.  イベントの説明

     CS_EVENT_CARD_INSERTION
        カードが挿入された事を表すイベント信号。ドライバが使用中のソケッ
        トに結合されている場合は、カードサービスはドライバに人為的に挿入
        イベントを送出します。

     CS_EVENT_CARD_REMOVAL
        カードが抜かれた事を表すイベント信号。このイベントはカードサービ
        スが全てのクライアントに可能な限り速く通知する為に最小の遅延時間
        で取り扱います。

     CS_EVENT_BATTERY_LOW
        ``電池不足''状態に変化した事を表すイベント信号。

     CS_EVENT_BATTERY_DEAD
        ``電池切れ''状態に変化した事を表すイベント信号。

     CS_EVENT_READY_CHANGE
        ``準備完了''状態に変化した事を表すイベント信号。

     CS_EVENT_WRITE_PROTECT
        ``書き込み禁止''状態に変化した事を表すイベント信号。

     CS_EVENT_REGISTRATION_COMPLETE
        RegisterClient の呼び出しが成功した後にドライバに送るイベント。

     CS_EVENT_RESET_REQUEST
        クライアントが ResetCard を呼んだ時に送るイベント。イベントハン
        ドラは呼び出しが失敗したらリセット操作を拒否できます。

     CS_EVENT_RESET_PHYSICAL
        リセット信号をカードに送る直前に全てのクライアントに送ります。

     CS_EVENT_CARD_RESET
        リセット操作が終了したら送るイベント信号。リセットが成功したか失
        敗したかは GetStatus を使用して認識します。

     CS_EVENT_RESET_COMPLETE
        ResetCard を呼んでリセット処理の完了したことをクライアントに通知
        するイベント。

     CS_EVENT_PM_SUSPEND
        カードサービスがユーザの初期化または APM サスペンド要求を受け
        取った事を表すイベント信号。イベントハンドラは呼び出しが失敗した
        らサスペンドを拒否できます。

     CS_EVENT_PM_RESUME
        サスペンド/リジューム命令の後でシステムが停止したことを表す信
        号。

     CS_EVENT_MTD_REQUEST
        MTD メモリ操作の初期化に使います。要求の種類は callback 引数の
        mtdrequest 変数の中に渡されます。ホストのバッファアドレスは
        buffer 変数に渡されます。

     CS_EVENT_ERASE_COMPLETE
        キューに入れた消去操作が終了した事をクライアントに通知するのに使
        用します。消去キューへのポインタは callback 引数の info 変数に返
        ります。

  5.3.  クライアントドライバのイベント操作の役割について

  クライアントドライバはソケットが設定されたか解除されたかによって発生す
  る CS_EVENT_CARD_INSERTION イベントと CS_EVENT_CARD_REMOVAL イベントに
  応答します。従ってカードの除去は高い優先度のイベントなのでドライバは即
  時にソケットとの入出力を遮断し、device 構造体にフラグを設定し、その他
  全ての処理を後で発生する時間割り込みを使用して中止するように予定に組み
  込みます。

  CS_EVENT_PM_RESET_REQUEST イベントを受け取った時は、ドライバは入出力を
  遮断しロックしたソケットの設定を解放し、ドライバはソケットの設定と遮断
  前の入出力を格納します。CS_EVENT_CARD_RESET を受け取った時は、ドライバ
  構成を格納し入出力の封鎖を解きます。

  入出力が遮断されかつソケットの構成が解放された場合に
  CS_EVENT_PM_SUSPEND イベントは大体 CS_EVENT_PM_RESET_REQUEST イベント
  のように扱われます。 CS_EVENT_PM_RESUME イベントを受け取った時はドライ
  バがカードの再設定の準備が出来ている場合を除いて、CS_EVENT_CARD_RESET
  イベントを受け取った時と同様です。

  6.  メモリテクノロジドライバ

  メモリテクノロジドライバ (``MTD'') は、ある種のメモリデバイスでさまざ
  まなメモリサービスを実現するために、カードサービスが使用します。 MTD
  は、RegisterClient を呼び出して、通常のカードサービスのクライアントと
  して登録しなければなりません。カード挿入のイベントを受け取ったら、管理
  するメモリの範囲を知るために、GetFirstRegion と GetNextRegion を呼び出
  します。そうしたら、RegisterMTD を使ってそれらの範囲を制御します。MTD
  の読み出し、書き込み、消去の要求は、カードサービスによって
  CS_EVENT_MTD_REQUEST にパッケージ化され、MTD のイベントハンドラに渡さ
  れて処理されます。

  6.1.  MTD 要求の処理

  MTD は、カードサービスからの要求を CS_EVENT_MTD_REQUEST イベントとして
  受け取ります。カードサービスは、要求の内容をイベントコールバックの引き
  数の mtdrequest 変数に入れて渡します。データをホストと受け渡しする要求
  については、ホストのバッファのアドレスが buffer 変数に渡されます。

  mtd_request_t 構造体の定義は次のとおり:

       typedef struct mtd_request_t {
               u_long          SrcCardOffset;
               u_long          DestCardOffset;
               u_long          TransferLength;
               u_long          Function;
               u_long          MediaID;
               u_long          Status;
               u_long          Timeout;
       } mtd_request_t;

  Function の変数はビットマップで、この要求で実行される動作を示していま
  す。

     MTD_REQ_ACTION
        MTD_REQ_ERASE, MTD_REQ_READ, MTD_REQ_WRITE, MTD_REQ_COPY のいず
        れか。

     MTD_REQ_NOERASE
        ブロックの境界と大きさがにぴったりはまるような書込みコマンドのと
        き、消去が不要なことを示します。

     MTD_REQ_VERIFY
        書き込み確認(verify) を指定します。

     MTD_REQ_READY
        この要求が、前回の要求がカードが準備完了を返すまで延期された後の
        再試行であることを示します。

     MTD_REQ_TIMEOUT
        この要求が、前回の要求が時間切れで延期された後の再試行であること
        を示します。

     MTD_REQ_FIRST
        この要求が、一連の要求の最初のものであることを示します。

     MTD_REQ_LAST
        この要求が、一連の要求の最後のものであることを示します。

     MTD_REQ_KERNEL
        読み書きコマンドのホストバッファが、ユーザメモリでなくカーネルメ
        モリ中にあることを示します。

  MediaID 変数は、このメモリ範囲を表わすために RegisterMTD 要求の中で指
  定された値です。Status 変数は、デバイスが何らかの処理を実行中で要求に
  応えることができなかったことを表わすために MTD が使います。MTD 要求
  は、通常は封鎖しません。要求が通常は封鎖するような場合でも、実際には封
  鎖せず、エラーコードとして CS_BUSY を返し、Status に次のいずれかの値を
  設定するはずです。訳注：「封鎖」は「block」の訳語です。「塊」の意味の
  「ブロック」 (「データブロック」など) との混同を避けるために使っていま
  す。使用例：宇津宮孝一・福田晃共訳「オペレーティングシステムの概念」
  (1987年・倍風館)

     MTD_WAITREQ
        現在実行中の別の要求の処理が正常終了した後に、要求を再試行すべき
        であることを示します。

     MTD_WAITTIMER
        timeout 変数で示される時間が経過した後に、要求を継続すべきである
        ことを示します。

     MTD_WAITRDY
        カードが準備完了状態になるか，あるいは timeout 変数で示される時
        間が経過するか、どちらかが先に起った後に、要求を継続すべきである
        ことを示します。

     MTD_WAITPOWER
        ソケットの電源の供給に影響する何事かが起った後に、要求を再試行す
        べきであることを示します。

  MTD_WAITTIMER と MTD_WAITRDY では、Timeout 変数の値はミリ秒単位のタイ
  ムアウトの時間です。

  6.2.  MTD 支援関数

  MTD はカードサービスが発生する要求を処理するので、MTD のイベントハンド
  ラから安全に実行できるカードサービス呼び出しの種類には制限があるかもし
  れません。 MTD の支援関数は、MTD が必要とするかもしれないが通常のカー
  ドサービス呼び出しを使って実現するとすると扱いにくいであろう特別なサー
  ビスを、限定されたセットとして提供します。 Linux における PCMCIA の実
  装では、ほとんどのカードサービス呼び出しは MTD から安全に呼び出すこと
  ができますが、互換性のために MTD の支援インターフェイスが含まれていま
  す。

  #include "cs_types.h"
  #include "cs.h"
  #include "bulkmem.h"

  int MTDHelperEntry(int subfunc, void *arg1, void *arg2);

  6.2.1.  MTDRequestWindow, MTDReleaseWindow

       int MTDHelperEntry(MTDRequestWindow, client_handle_t *handle, win_req_t *mod);
       int MTDHelperEntry(MTDReleaseWindow, window_handle_t handle);

  These services are identical to the standard Card Services
  RequestWindow and ReleaseWindow calls.

  6.2.2.  MTDModifyWindow

       int MTDHelperEntry(MTDModifyWindow, memory_handle_t handle, mtd_mod_req_t *mod);

  mtd_mod_req_t の構造体は次のとおり:

       typedef struct mtd_mod_req_t {
               u_long          Attributes;
               u_long          AccessSpeed;
               u_long          CardOffset;
       } mtd_mod_req_t;

  MTDModifyWindow は、通常の ModifyWindow と MapMemPage の呼出しを使うの
  と本質的に同じです。

  Attributes で指定できる内容は次のとおり。:

     WIN_MEMORY_TYPE
        WIN_MEMORY_TYPE_CM で一般メモリを示すか、または
        WIN_MEMORY_TYPE_AM で属性メモリを示します。

     WIN_USE_WAIT
        コントローラがカードの MWAIT 信号を監視する必要があることを示し
        ます。

  MTDModifyWindow で設定された領域は常に使用可能であり、16 ビットのデー
  タ幅を持ちます。

  戻り値 :

     CS_BAD_HANDLE
        メモリハンドルが不正です。

  6.2.3.  MTDSetVpp

       int MTDHelperEntry(MTDSetVpp, client_handle_t client, mtd_vpp_req_t *req);

       typedef struct mtd_vpp_req_t {
               u_char          Vpp1, Vpp2;
       } mtd_vpp_req_t;

  MTDSetVpp はソケットのプログラム電圧を変更します。Vpp1 と Vpp2 は 1/10
  ボルト単位で与えられます。現在のところ、Vpp1 と Vpp2 は常に等しくなけ
  ればなりません。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが不正です。

     CS_BAD_VPP
        指定された Vpp が正しくないか、または Vpp1 と Vpp2 が等しくな
        い。

  6.2.4.  MTDRDYMask

       int MTDHelperEntry(MTDRDYMask, client_handle_t client, mtd_rdy_req_t *req);

       typedef struct mtd_rdy_req_t {
               u_long          Mask;
       } mtd_rdy_req_t;

  MTDRDYMask は、CS_EVENT_READY_CHANGE イベントを使用できるようにするか
  どうかを選択します。クライアントは、RegisterClient 又は SetEventMask
  のいずれかの呼出しを使って、カードサービスに対してこれらのイベントを受
  け取ることを表明しておかなければなりません。Mask 引き数の
  CS_EVENT_READY_CHANGE ビットがセットされていると、イベントの変更ができ
  るようになります。

  戻り値 :

     CS_BAD_HANDLE
        クライアントハンドルが不正です。

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

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

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

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

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

  7.1.1.  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 構造体の結合リストを作るために使うことが
  できます。

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

  7.1.3.  unregister_pcmcia_driver

       int unregister_pcmcia_driver(dev_info_t *dev_info);

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

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

  ドライバサービスは、ユーザモードの PCMCIA ユティリティと通信するために
  疑似デバイスを作ります。このデバイスのメジャー番号は動的に選ば
  れ、PCMCIA ユティリティは /proc/devices を読んでその値を得なければなり
  ません。マイナー番号は 0 から始まるソケットの番号に対応します。

  ただ一つのプロセスだけが、あるソケットを読書きのためにオープンすること
  ができます。他のプロセスは、読出し専用モードでのみ、このソケットをオー
  プンできます。読出しのみの接続では、一部の ioctl 機能だけが使えます。
  読書き両方の接続では、すべての ioctl 機能が使え、カードサービスからの
  イベントの通知を受け取ることができます。

  7.2.1.  カードサービスのイベント通知

  ドライバサービスは、イベントの通知のために 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.

  7.2.2.  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_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 の呼出しのときと同じ意味です。
  8.  カードサービスクライアントドライバの解剖

  Linux PCMCIA パッケージのそれぞれの版は、最初から新規にドライバを書け
  るように良く文書化された``雛型''のクライアントドライバと一緒に提供して
  います。 modules/skeleton.c に置いています。

  8.1.  モジュールの初期化とリセット

  全てのローダブルモジュールは init_module() と cleanup_module() 関数を
  備えなければいけません。それはモジュールを着脱するときにモジュールを支
  援するプログラムが必要とするからです。PCMCIA クライアントドライバの初
  期化関数は register_pcmcia_driver() 呼び出し経由でドライバサービスに
  よってドライバを登録します。再初期化(cleanup) 関数は
  unregister_pcmcia_driver() を使用してドライバサービスによって登録解除
  します。ドライバによっては、再初期化関数はシャットダウン時に存在するデ
  バイスの構造体を解放する為にも呼ばれるかもしれません。

  8.2.  *_attach() と *_detach() 関数

  *_attach() 関数はドライバの ``実体'' を作成し、1つの PCMCIA カードの管
  理に必要なデータ構造体の設定を行なう役目があります。*_attach() 関数は
  dev_link_t 構造体の割り当てと初期化を行ない、RegisterClient を呼び出し
  てカードサービスとの結合を確立します。RegisterClient は新しく出来た
  dev_link_t 構造体へのポインタを返し、作成できなかった時は NULL を返し
  ます。

  *_detach() 関数は以前に発行した *_attach が作成したドライバの実体を削
  除します。また、カードサービスとの結合も DeregisterClient を使って解除
  します。

  *_attach() 関数は DS_BIND_REQUEST ioctl() で一致するドライバが識別で
  き、割り付けがうまくいった時にドライバサービスによって呼ばれます。
  *_detach() 関数は DS_UNBIND_REQUEST ioctl() を呼ぶことに応答し起動しま
  す。

  8.3.  *_config() と *_release() 関数

  *_config() 関数はカードに対する入出力の準備の為に呼ばれます。殆んどの
  ドライバは詳細な情報はカード自身から読み出しますが、どのようにデバイス
  を設定するかの最小限の知識はドライバに組み込まれています。例えば、シリ
  アルカードのドライバはカードの CFTABLE_ENTRY タプルから一致する入出力
  ポートの基底アドレスと一致する設定指標を読み込みますが、 CIS 内の割り
  込み情報は無視します。*_config 関数はカードの CIS の関連する部分を解析
  します。そして RequestIO, RequestIRQ や RequestWindow を呼び出せます。
  それから RequestConfiguration を呼びます。

  カードの設定がうまくいったら、*_config() ルーチンが dev_link_t 構造体
  の dev_name, major と minor 変数に書き込みます。これらの変数は
  DS_GET_DEVICE_INFO ioctl () の応答としてドライバサービスがユーザプログ
  ラムに返します。

  *_release() 関数は以前に呼んだ *_config() が割り当てたリソースを解放
  し、デバイスの dev_name 変数を空白にします。

  *_config() と *_release 関数は通常カード状態の変更イベントまたはタイマ
  ー割り込みに反応して呼ばれます。この時、これらの関数はスリープ出来な
  く、他のカーネル関数から呼ばれないように遮断しておきます。

  8.4.  PCMCIA イベントハンドラ

  *_event() 関数はカードサービスからカード状態次変更イベントを通知する為
  に呼ばれます。

  8.5.  ロックと同期について

  設定したソケットは全ての関連したデバイスが閉じられた時にのみ解放されま
  す。ソケットの解放はソケットのシステム資源を他のデバイスで使用出来るよ
  うにします。解放された資源が元のデバイスで入出力に使用している場合は、
  元のドライバは新しいデバイスを使用してします。

  ドライバの実体は一致するソケットの構成が解放された後のみ解放されます。
  カードサービスは DeregisterClient が成功する為にはクライアントが明らか
  に割り当てた資源を解放する必要があります。

  全てのローダブルモジュールは安全にモジュールを解放する時にシステムが使
  用する ``使用回数(use count)'' を持っています。PCMCIA クライアントドラ
  イバの慣習はデバイスをオープンすると使用回数を増加させ、デバイスをクロ
  ーズすると使用回数を減少させます。従ってドライバを解放するには全ての関
  連するデバイスは閉じている必要があります。特に、ソケットが接続している
  時にドライバを解放出来ます。モジュール再初期化プログラムは適切な解放で
  きる既に割当済みの資源を必要とします。これは使用回数がゼロで、全てのデ
  バイスが閉じていて、つまり全てのソケットが解放できる状態で全てのデバイ
  スが外せる場合に安全な方法です。

  デバイスが開いている状態で *_release() 関数が呼ばれたら、デバイス状態
  の DEV_STALE_CONFIG フラグが設定され close() 関数が呼ばれた時にデバイ
  スを解放するように通知します。構成したデバイスを*_detach() 関数で呼び
  出したら、DEV_STALE_LINK フラグは *_release() 関数が呼ばれた時に実体が
  解放されるように通知するように設定されます。

  8.6.  現有の Linux のドライバで PCMCIA デバイスをアクセスする方法

  現在の PCMCIA クライアントドライバは現有の Linux のドライバをデバイス
  の入出力操作を行ないます。カードサービスクライアントモジュールはカード
  の構成とカード状態の変更イベントの監視を行ないますが、通常の ISA バス
  のカードのドライバと互換性のある入出力を行ないます。いくつかの場合で
  は、普通のドライバを変更無しに使う事が出来ます。しかしながら、活線抜去
  やパワーマネージメントのような PCMCIA の機能はすべてはサポートされてい
  ませんので、PCMCIA クライアントプログラムとデバイス入出力プログラムの
  間で通信をする必要があります。

  殆んどのドライバはブート時にデバイスを探知するのと着脱出来るデバイスを
  扱うように設計されています。ドライバのモジュール化の副作用は通常着脱可
  能なデバイスを扱うのにモジュラー化したドライバは簡単に受け入れられると
  いうことです。

  重要な事は、適切でない時にデバイスを取り去ってしまいデバイスドライバが
  使えなくなる事です。最善の方法はドライバが入出力操作や入出力割り込みを
  行なう前にデバイスを事前に確認する事です。デバイスの状態の確認の繰返し
  は時間切れになってしまい、結局デバイスが応答しない場合は終了します。

  9.  さらなる情報はどこにあるか？

  Michael Johnson が書いた Linux カーネルハッカーの手引き (Linux Kernel
  Hackers' Guide) は Linux のデバイスドライバを書く為の良い一般的な情報
  源です。一般の Linux の FTP サイトにまとめられた Linux 文書とともにお
  いてあります。

  本物の PCMCIA 標準は PCMCIA 協会それ自身だけが発行してますが途方もなく
  高価です。新しい PC Card 95 標準は 399 ドルですが古い 2.1 標準はかなり
  値引きが出来ると思います。

       Personal Computer Memory Card International Association
       1030 East Duane Avenue, Suite G
       Sunnyvale, CA 94086 USA
       (408) 720-0107, (408) 720-9416 FAX, (408) 720-9388 BBS
       http://www.pc-card.com

  その代わりにMichael Mori が書いた PCMCIA 開発者の手引き (PCMCIA
  Developer's Guide) は Sycard Technology から発行され、 ISBN
  0-9640342-1-2 で、およそ 89.95 ドルです。

       Sycard Technology
       1180-F Miraloma Way
       Sunnyvale, CA 94086 USA
       (408) 749-0130, (408) 749-1323 FAX

  Dana Beatty, Steven Kipisz と Brian Moore が書いた PCMCIA ソフトウェア
  開発者のハンドブック (PCMCIA Software Developer's Handbook) はPCMCIA
  標準の概要とクライアントドライバの書き方の説明をしています。ま
  た、Linux PCMCIA プログラマの手引きを付録に添付しています。発行は
  Peer-to-Peer Communications で ISBN 1-57398-010-2 です。

  Larry Levine はより一般的な PCMCIA への紹介文である 1995 年の夏に書店
  に並んだ PCMCIA 入門(PCMCIA Primer)を書いています。 M & T Books が出版
  し、ISBN 1-55828-437-0 です。

  各種の PCMCIA 制御装置に関するプログラム情報は該当するチップベンダーか
  ら取り寄せましょう。：

       Intel Corporation
       (800) 628-8686

       Cirrus Logic
       (510) 623-8300

       Vadem
       (408) 943-9301

       Databook Inc.
       (716) 889-4204

  [EOF]

