PC カードマネージャは、PCMCIA コントローラに対応したドライバであり、 PCMCIA カード ( 以後 PC カードと呼ぶ ) を対象とするデバイスドライバに対して、 コントローラやマシンに依存しない統一的なインタフェースを提供する。

カードマネージャは以下に示す機能を持つ。
PC カードを対象とするデバイスドライバは、 通常のドライバ機能に加えて、以下の機能が必要となる。
カードマネージャの制限事項を以下に示す。
CR_SHARE は未サポートとする。
LONG_LINK
によるコモンメモリ上の CIS タプル情報は未サポートとする。
pcmcia.h )
/* カードイベント種別 */
#define CE_INSERT 1 /* カード挿着 */
#define CE_EJECT 2 /* カード脱着 */
#define CE_BATTERY 3 /* カードバッテリ状態変化 */
/* カードイベントの応答コード */
#define CR_NONE 0 /* 対象カードでない */
#define CR_OWN 1 /* 対象カード:占有する */
#define CR_SHARE 2 /* 対象カード:共有する */
/* カード種別:FUNCID タプルのコード */
#define CK_MULTI 0 /* マルチファンクション */
#define CK_MEMORY 1 /* メモリ */
#define CK_SERIAL 2 /* シリアルポート */
#define CK_PARALLEL 3 /* パラレルポート */
#define CK_FIXED 4 /* 固定ディスク */
#define CK_VIDEO 5 /* ビデオ */
#define CK_NETWORK 6 /* ネットワーク */
#define CK_AIMS 7 /* AIMS */
#define CK_SCSI 8 /* SCSI */
#define CK_ANY 255 /* 任意(不正) */
#define CK_NONE (-1) /* なし(登録削除) */
/* カード状態 */
typedef struct {
UW kind:8; /* カード種別 : CK_xxx */
UW battery:2; /* バッテリ状態:メモリカードのみ */
/* 0:OK, 1:警告, 2,3:異常(デッド)*/
UW wprotect:1; /* 書き込み禁止:メモリカードのみ */
UW power:1; /* 電源供給状態 */
UW client:1; /* 使用中状態 */
UW rsv:19; /* 予約 */
} CardStat;
/* マップ / メモリ属性 */
#define CA_IONOCHK 0x10000 /* IO 空間のリソース管理なし */
#define CA_IOMAP 0x8000 /* IO 空間のマップ */
#define CA_ATTRMEM 0x4000 /* 属性メモリ指定 */
#define CA_WPROTECT 0x2000 /* 書き込み禁止 */
#define CA_16BIT 0x0800 /* 16 ビットアクセス指定*/
#define CA_IOCS16 0x0400 /* IOCS16 ソース */
#define CA_WAIT0 0x0100 /* 追加 WAIT 0 指定 */
#define CA_WAIT1 0x0101 /* 追加 WAIT 1 指定 */
#define CA_WAIT2 0x0102 /* 追加 WAIT 2 指定 */
#define CA_WAIT3 (CA_WAIT1 | CA_WAIT2) /* 追加 WAIT 3 指定 */
#define CA_ZWAIT 0x0104 /* ゼロ WAIT 指定 */
#define CA_SPEED 0x00FF /* 50 ns 単位のアクセス速度指定 */
/* 電源制御 */
#define CP_POWEROFF 0x00 /* 電源 OFF */
#define CP_POWERON 0x01 /* 電源 ON */
#define CP_SUSPEND 0x10 /* サスペンド ( 電源 OFF ) */
#define CP_RESUME 0x11 /* レジューム ( 電源 ON ) */
#define CP_SUSRIRES 0x12 /* サスペンド ( RI レジューム ) */
#define CP_POFFREQ(tm) (((tm) << 16) + 0x99) /* 指定時間 ( 秒 ) 後電源 OFF */
/* 特殊カード ID */
#define TEST_CARDID 0x12345678 /* テスト用特殊カード ID */
/* タプルデータの最大サイズ */
#define MAX_TUPLESZ (255 + 2)
登録したデバイスドライバに対しては、 デバイスドライバへの要求受け付けランデブポートに対して、 カードイベントの呼び出しが行なわれる。
デバイスドライバは、 どのような時点でもカードイベント呼び出しを速やかに受け付け、 対応した処理を行なったのち応答を戻さなくてはいけない。
カードイベント呼び出し / 応答は、 通常のデバイス要求 / 応答のデータ形式を使用して以下の内容で行なわれる。
DevReq: devid カード ID
cmd.cmd = DC_CARDEVENT
datano イベント種別 (CE_xxxx)
datacnt カード状態 = CardStat
taskid 予約(0)
memptr 予約(0)
DevRsp: devid カード ID
cmd.cmd = DC_CARDEVENT
datano 予約
datacnt 予約
error 応答コード (CR_NONE / CR_OWN)
CE_INSERT イベント ( カード挿入 )
カードを挿入した時点で、登録されているデバイスドライバのうち、
以下の条件を満たすドライバに対して順番に発行され、
ドライバからの応答コードとして CR_OWN が得られた場合、
そのドライバがカードに対応づけられて、
イベントの発行はその時点で終了する。
CE_INSERT イベントの発行の順番は、初期は登録された順番であるが、
最後に排出されたカードに対応づけられていたドライバが、
最初になるように順番は変更されていく
( この順番の変更は、
不正排出された場合の再挿入に対応するために行なわれる )。
また、ドライバの登録時点で、すでにカードが挿入されており、
そのカードがまだドライバに対応づけられていない場合も、
CE_INSERT イベントが発生する。
CE_INSERT イベントを受けたドライバは、
そのカードが自分が対象とするカードかどうかを、
イベント内のカード状態 ( CardStat ) や、
pcGetTuple() を実行して CIS
タプル情報を取り出してチェックする。
このとき、イベント内のカード ID をパラメータとして使用する。
カード ID の下位 2 ビットは 物理的な PCMCIA のスロット ( 0 〜 3 ) を示しているので、 ドライバが特定のスロットのみを対象とする場合は、 カード ID の値により判断する。
チェックの結果、対象とするカードでない場合は、
CR_NONE の応答コードを戻し、以後、
カードマネージャやカードに対するアクセスを行なってはいけない。
チェックの結果、対象とするカードである場合は、
必要なカードのコンフィグレーション、メモリ / IO のマップ、
割り込みハンドラの登録などを行なったのち、CR_OWN の応答コードを戻す。
以後、カードへのアクセスを占有的に行なうことが許され、
カードマネージャのシステムコールには、
この時のカード ID をパラメータとして使用する。
CE_EJECT イベント ( カード排出 )
カードが排出された時点で、対応づけられたドライバにに対して、
CE_EJECT イベントが発行される。
CE_EJECT イベントを受けたドライバは、
対象とするカードが排出されたことに対応する処理を行ない応答を戻す。
このイベントの場合の応答コードは意味を持たない。
カードが排出されるとカードとドライバとの対応づけは解除されるため、
今まで使用していたカード ID は無効となる。
カードが排出されると、メモリ空間や IO 空間のマップは無効になるが、
マップ情報は残っているので、通常は、
pcUnMap() を実行してマップ情報を解放することになる。
ただし、同一のカードの再挿入が期待され、
マップ情報を変更したくないときは、pcUnMap() を実行せず、
再挿入された時点で、pcReMap()
を実行することによりマップを再度有効にすることができる。
CE_BATTERY イベント ( カードバッテリ警告 / 異常 )
メモリカードのバッテリ警告/異常が検出されると、
対応づけられたドライバにに対して、
CE_BATTERY イベントが発行される。
CE_BATTERY イベントを受けたドライバは、
イベント内のカード状態 ( CardStat ) によりバッテリの状態を確認し、
対応するデバイスイベントの発行などの処理を行なって応答を戻す。
このイベントの場合の応答コードは意味を持たない。
なお、カードの挿入時点ですでにバッテリ警告/異常のときは、CE_BATTERY
イベントは発行されない場合があるため、CE_INSERT
イベントの処理においても、カード状態 ( CardStat )
によりバッテリの状態を確認して、正常でない場合は、
対応する処理を行なう必要がある。
PC カードを使用しているデバイスドライバは以下のサスペンド / レジューム処理を行なわなくてはいけない。
pcPowerCtl ( cardid, CP_SUSPEND ) によりカード電源を OFF とする。
CP_SUSRIRES を指定する。
必要に応じて、pcUnMap() によるマップを解除する。
以後、カードへのアクセスを行なってはいけない。
pcPowerCtl ( cardid, CP_RESUME ) によりカードの電源を ON とし、
リターン値により以下の処理を行なう。
== 0 :- すでに 電源 ON (ありえない)
== 1 :- 電源を ON としたので、以下のような初期化処理を行なう。
- IO / メモリのマップ
- 割り込みハンドラの登録
- カードへのコンフィグレーションの設定
== ER_NODEV :- サスペンド中にカードが抜かれたか、 別のカードに替えられたので、 カードが抜かれた場合 (
CE_EJECTイベント ) と同様の処理を行なう。CE_EJECTイベントは発生しない。
この場合、CE_EJECTイベントの場合と異なり、 カード ID は既に無効となっている点に注意が必要となる。
マップID は有効のままなので必要に応じてアンマップを行なう。== ER_ERDEV :- 電源を ON してレディ状態にできなかった。
通常はあり得ないが、電源 OFF の状態のままとなる。
なお、サスペンド中のカードの出し入れに伴う処理は以下のようになる。
- カードの排出:
- ドライバのレジューム処理での
pcPowerCtl()でER_NODEVが戻る。- カードの入れ替え ( 同一カード ) :
- 入れ替えなしと同じ
ドライバのレジューム処理でのpcPowerCtl()で(1)が戻る。- カードの入れ替え ( 別カード ) :
- ドライバのレジューム処理での
pcPowerCtl()でER_NODEVが戻る。
レジューム完了後に入れ替えたカードに対するCE_INSERTイベントが発生する。- カードの新規挿入 :
- レジューム完了後に新規挿入したカードに対する
CE_INSERTイベントが発生する。
カードマネージャは、デバイスドライバに対して、 以下のサービスを拡張システムコールとして提供する。
|
ERR pcRegClient(ID portid, W kind)
portid | : カードイベント受け付け用ランデブポートID |
kind | : PC カード種別 |
| = 0 (ER_OK) | : 正常終了 |
| < 0 | : エラー (エラーコード) |
portid で指定した受け付け用ランデブポートを持つ、
デバイスドライバをクライアントとして登録する、または登録を削除する。
kind != CK_NONE のときは、
kind で指定した種別の PC カードを対象とするドライバであることを登録し、
kind == CK_NONE のときは登録を削除する。
複数の種別の PC カードを対象とするドライバの場合は、
kind == CK_ANY として登録する。
登録したドライバは、1枚の PC カードとの対応のみが許されるため、
同一のドライバで複数枚の PC カードを同時にサポートしたい時は、
複数回登録を行なう必要がある。ただし、登録の削除では、
指定したランデブポートでの登録をすべて削除するため 1 回の削除で良い
( 2 回目以降の削除では ER_NOEXS のエラーとなる)。
登録を削除したドライバが、 挿入されている PC カードと対応づけられていた場合は、 その対応は解除される。
ER_PAR | パラメータエラー ( portid, kind) |
ER_LIMIT | 登録数の制限を超えた |
ER_NOEXS | 登録されていない ( kind == CK_NONE のとき) |
|
WERR pcGetTuple(ID cardid, W tuple, W order, UB* buf)
cardid | カード ID | ||||||
tuple | 取り出すタプルコード(0 はすべてを対象) | ||||||
order | タプルコードの出現順の指定 (0 は最初タプル) | ||||||
buf | 取り出したタプルデータのバッファMAX_TUPLESZ バイト以上の大きさがなくてはいけない
|
| > 0 | 正常終了
(取り出したデータのバイト数
( = n + 2 <= MAX_TUPLESZ) ) |
| = 0 | 正常終了(該当のデータなし) |
| < 0 | エラー (エラーコード) |
cardid により対応づけられたカードの CIS タプル情報のうち、
tuple で指定したタプルコードの
order 番目のタプル情報を buf に取り出す。
order を 0 から順に増加させることにより、
同一のタプルコードの情報を順次取り出すことができる。
また、tuple == 0 とすることにより、
order で指定した位置の任意のタプル情報を取り出すことができる。
ER_ID | カード ID が不正 |
ER_ADR | アドレスが不正 ( buf ) |
|
WERR pcMap(ID cardid, W offset, W len, UW attr, VP *addr)
cardid | カード ID |
offset | マップするカード側のメモリ / IO 空間の開始アドレス |
len | マップするカード側のメモリ / IO 空間のバイト長さ |
attr | マップ属性
|
addr | マップされた CPU 側のメモリ / IO 開始アドレス(戻り値) |
| > 0 | 正常終了 (マップ ID) |
| < 0 | エラー (エラーコード) |
cardid により対応づけられたカードの、
offset と len で指定したカード側のメモリ空間、
または IO 空間を attr で指定した属性により CPU側のメモリ空間、
または IO 空間にマップして、マップした開始アドレスを *addr に戻す。
リターン値としてマップを識別するためのマップ ID が戻る。
メモリ空間のマップは、カードのコモンメモリのみ対象とし、
属性メモリはマップすることはできない。
実際のメモリ空間のマップは機種に依存した境界単位で行なわれ、
通常は 4 KB単位となる。
マップされる CPU
側のメモリ開始アドレスは使用可能メモリ空間の中から自動的に重複しないように割り当てられて
*addr に戻される。
一度にマップできる最大サイズは機種に依存するため、
できるだけ小さな単位 ( 64 KB 以下)でマップすることが望ましい。
IO 空間のマップでは、マップされたカード側の IO 開始アドレスに対応する
CPU 側の IO 開始アドレスが *addr に戻される。
CPU 側とカード側の IO 空間が一致している場合は、
offset で指定した値と同じ値が戻されるが、
一致していない場合は、offset とは異なる値が戻される。
マップ属性のうち、ウェイトに関しては、 以下のいずれかの方法により指定するが、機種に依存しない絶対指定が望ましい。
CA_SPEED ) :
CAZWAIT | ゼロウェイト |
CAWAIT0 | 追加ウェイトなし (標準) |
CAWAIT1 | 追加ウェイト 1 |
CAWAIT2 | 追加ウェイト 2 |
CAWAIT3 | 追加ウェイト 3 |
カードが排出されたり、カード電源が OFF された場合は、
そのカードに対するマップは無効になるが、
マップした情報は保存されているため、
pcReMap() により再度マップすることができる。
IO 空間のマップでは、
ハードウェアリソースマネージャを使用して IO
空間のチェック/登録が行われるが、
CA_IONOCHK 属性を付けたときはチェック/登録は行われない。
ER_ID | カード ID が不正 |
ER_PAR | パラメータエラー ( offset, len )指定した IO 空間は他で使用されている |
R_LIMIT | マップ数が制限を超えた |
ER_NOSPC | マップするメモリ空間、IO 空間が不足した |
ER_ADR | アドレスが不正 ( addr ) |
|
ERR pcReMap(ID cardid, ID mapid)
cardid | カード ID |
mapid | マップ ID |
= 0 ( ER_OK ) | 正常終了 |
| < 0 | エラー (エラーコード) |
cardid により対応づけられたカードに対して、
mapid で指定したマップを再度有効にする。
この機能は、カードが一度排出された後に、 再度挿入された場合に、 以前に行なったマップを再度有効にするために使用する。
リマップは、一度アンマップしてからマップすること機能的には同一であるが、 メモリ空間のマップでは、 一度アンマップすると以前と同じ CPU 側のメモリアドレスにマップされることは保証されない点に違いがある。
ER_ID | カード ID または マップ ID が不正 |
|
ERR pcUnMap(ID mapid)
mapid | マップ ID |
= 0 ( ER_OK ) | 正常終了 |
| < 0 | エラー (エラーコード) |
mapid で指定したマップを解除する。
| ER_ID | マップ ID が不正 |
|
ERR pcReadMem(ID cardid, W offset, W len, UW attr, VP buf)
cardid | カード ID |
offset | 読み込みバイトオフセット |
len | 読み込みバイト長さ |
attr | メモリ属性
|
buf | 読み込みデータバッファ |
= 0 ( ER_OK ) | 正常終了 |
| < 0 | エラー (エラーコード) |
cardid により対応づけられたカード上のメモリ
( コモンメモリ / 属性メモリ ) の offset から
len バイトを buf に読み込む。
カード上の属性メモリは、偶数アドレスのみ有効であるため、
偶数アドレスのバイトだけを連続して並べたバイト列として読み込まれる。
したがって offset としてはカード上の実際のオフセットの 1 / 2 の値を指定する必要がある。
ER_ID | カード ID が不正 |
ER_PAR | パラメータエラー ( offset, len ) |
ER_ADR | アドレスが不正 ( buf ) |
|
ERR pcWriteMem(ID cardid, W offset, W len, UW attr, VP buf)
cardid | カード ID |
offset | 書き込みバイトオフセット |
len | 書き込みバイト長さ |
attr | メモリ属性
|
buf | 書き込みデータバッファ |
= 0 ( ER_OK ) | 正常終了 |
| < 0 | エラー (エラーコード) |
cardid により対応づけられたカード上のメモリ
(コモンメモリ / 属性メモリ)の offset から
len バイトに buf の内容を書き込み。
カード上の属性メモリは、偶数アドレスのみ有効であるため、
偶数アドレスのバイトだけを連続して並べたバイト列として書き込まれる。
したがって offset としてはカード上の実際のオフセットの 1 / 2 の値を指定する必要がある。
| ER_ID | カード ID が不正 |
| ER_PAR | パラメータエラー(offset, len) |
| ER_ADR | アドレスが不正(buf) |
|
WERR pcGetStat(ID cardid)
cardid | カード ID |
| > 0 | 正常終了( カード状態 ( CardStat 構造体) ) |
| < 0 | エラー (エラーコード) |
cardid により対応づけられたカードの状態を取り出し、
リターン値として戻す。
戻される値は、CardStat 構造体の値を W に キャストした値となる。
| ER_ID | カード ID が不正 |
|
WERR pcDefInt(ID cardid, T_DINT *dint, IntVector vec, UW par)
cardid | カード ID |
dint | 割り込みハンドラ定義情報 |
vec | 割り込みベクトル (0 : 自動割り当て) |
par | 割り込みハンドラへ渡すパラメータ |
| >= 0 | 正常終了 (対応する割り込みベクトル) |
| < 0 | エラー (エラーコード) |
cardid により対応づけられたカードからの割り込みハンドラを定義する。
割り込みハンドラの属性は TA_HLNG 指定でなくてはいけない。
vec によりカードに対応する割り込みベクトルを指定する。
vec == 0 を指定した場合は自動的に利用可能な割り込みベクトルを割り当てる。
通常は、vec == 0 として使用する。
指定した vec が割り当てられない場合は、エラーとなる。
リターン値としてカードに割り当てられた割り込みベクトルの値を戻す。
割り込みのリセットなどは自動的に行わなれるため、割り込みハンドラ内で行なう必要はない。
割り込みハンドラは以下の形式となる。
VOID inthdr(UW par)
カードからの割り込みを使用しない場合も、
カードを I/O カードとして使用する場合は、
dint == NULL として pcDefInt() を実行しなければならない。
dint.inthdr == NADR とした場合は、
カードからの割り込みは発生させるが、
割り込みハンドラは登録しないので、
クライアントのデバイスドライバは、
リターン値として戻る割り込みベクトルに対応した割り込みハンドラを自分で定義する必要がある。
この場合、対応ベクトルの割り込みの許可、
発生した割り込みのリセットなどはデバイスドライバ側で行なわなくてはならない。
また par は無視される。
割り込みハンドラの削除は dint == NULL として実行する。
カードが排出されたり、
カードの電源を OFF したりしたは、
割り込みハンドラは自動的に解除されて割り込みは禁止される。
そのため、再挿入時や電源 ON 時には、再度、
pcDefInt() を実行して割り込みハンドラを設定する必要がある。
カードが排出された場合や、
pcDefInt(dint == NULL) として明示的に割り込みハンドラを削除した場合は、
割り当てられた割り込みベクトルも解放されるため、
再度 pcDefInt() を行なった場合に同一の割り込みベクトルが割り当てられることは保証されない。
ただし、電源を OFF した場合は、割り込みベクトルは解放されないため、
再度の pcDefInt() で、
割り当てされる割り込みベクトルは以前と同じとなることが保証される。
以下に動作をまとめる。
dint == NULL
dint.inthdr != NADR で割り込みハンドラを登録
していた場合は、割り込みハンドラを解除する。
対応ベクルの割り込みは禁止する。
dint.inthdr == NADR
dint.inthdr != NADR
ER_ID | カード ID が不正 |
ER_PAR | パラメータエラー ( dint->intatr, vec が不正) |
ER_BUSY | 割り込みベクトルの空きがない。vec は使用済み。 |
ER_ADR | アドレスが不正 ( dint ) |
|
ERR pcPowerCtl(ID cardid, UW power)
cardid | カード ID | ||||||||||||
power | 電源制御
|
| = 1 | 正常終了 (実際にカードの電源を ON / OFF した) |
| = 0 | 正常終了 (すでにカードは電源を ON / OFF されている(変化なし)) |
| < 0 | エラー (エラーコード) |
cardid により対応づけられたカードへの電源供給を制御する。
CP_POWEROFF :
CP_SUSPEND :
CP_POWEROFF と同様。
CP_POWERON :
ER_ERDEV を戻し、カードは電源 OFF の状態のままとなる。ER_NODEV が戻るので、
クライアントドライバはカードが抜かれたときに処理を行なう必要がある。
この場合、カードID は既に無効となっているため、
カードへのアクセスはできない。
ただし、マップ ID は有効なため、
不要であればアンマップしなくてはいけない。CE_EJECT のカードイベントは発生しない点に注意が必要である。CP_RESUME :
CP_POWERON と同様。
CP_SUSRISUS :
CP_POWEROFF と同様であるが、
レジュームを可能とするために実際のカード電源は ON のままとなる。
CP_POFFREQ ( tm ) :
CP_POWERON を行った時点で、まだ電源 OFF していなかったときは、
0 が戻り、すでに電源 OFF していたときは 1 が戻る。tm は秒単位であり、-0 〜 +2 秒以内の誤差となる。tm が 0 のとき、CP_POWEROFF と同じ動作となる。
カードが挿入された時点では、
カードへの電源は ON となっており、ドライバが pcPowerCtl()
により電源 OFF としない限り、電源は ON の状態のままとなる。
ER_ID | カード ID が不正 |
ER_PAR | パラメータエラー ( power ) |
ER_NODEV | カードが抜かれてた ( CP_POWERON / CP_RESUME 指定時) |
ER_ERDEV | カードの異常 ( CP_POWERON / CP_RESUME 指定時) |
|
VOID pcSuspend(Bool start)
start | True: サスペンド開始 |
| False: サスペンド終了 |
なし
システムのサスペンド処理をカードマネージャに通知する。
この関数はデバイス管理による、 サスペンド処理のために用意されており、 以下の通りに呼び出されなくてはいけない。
pcSuspend(True);
<各デバイスのサスペンド移行処理>
pcSuspend(False);
なし
|
VOID pcResume(Bool start)
start | True : レジューム開始 |
| False: レジューム終了 |
なし
システムのレジューム処理をカードマネージャに通知する。
この関数はデバイス管理による、 レジューム処理のために用意されており、 以下の通りに呼び出されなくてはいけない。
pcResume(True);
<各デバイスのレジューム移行処理>
( <デバイス管理の呼び出し許可> )
pcResume(False);
pcResume ( False ) の処理の結果、
デバイス管理の呼び出しが発生する可能性があるため、
デバイス管理の呼び出しは許可されていなくてはいけない。
なし