デバイス管理機能

デバイス管理機能は、T-Kernel上で動作するデバイスドライバを管理するための機能である。

デバイスドライバとは、主としてハードウェアのデバイスの操作や入出力を行うために、T-Kernel本体とは独立して実装されるプログラムである。アプリケーションやミドルウェアによるデバイスの操作や入出力を、デバイスドライバ経由で行うことにより、個々のデバイスの仕様の差異をデバイスドライバ側で吸収し、アプリケーションやミドルウェアのハードウェア非依存性や互換性を高めることができる。

デバイス管理機能には、デバイスドライバを定義するための機能、すなわちT-Kernelにデバイスドライバを登録するための機能と、登録済みのデバイスドライバをアプリケーションやミドルウェアから利用するための機能が含まれる。

デバイスドライバの登録は、システム起動時の初期化処理の中で行う場合が多いが、システムの通常の動作中に動的に行うことも可能である。デバイスドライバの登録は tk_def_dev() によって行われ、この拡張SVCのパラメータの一つであるデバイス登録情報(ddev)の中で、デバイスドライバの実際の処理を行うプログラムの関数(ドライバ処理関数)群を指定する。この中には、デバイスのオープン時に呼び出されるオープン関数(openfn)、読込み時や書込みの処理開始時に呼び出される処理開始関数(execfn)、読込み時や書込みの処理の完了を待つ完了待ち関数(waitfn)などがあり、これらのドライバ処理関数の中で、実際のデバイスの操作やデバイスとの入出力の処理を行う。

これらのドライバ処理関数は、準タスク部として保護レベル0で実行されるため、ハードウェアに直接アクセスすることも可能である。デバイスとの入出力などの処理は、これらのドライバ処理関数の中で直接行う場合もあるし、これらのドライバ処理関数の中から出された要求に応じて動作する別タスク等の中で行う場合もある。これらのドライバ処理関数が呼び出される際のパラメータ等の仕様は、デバイスドライバインタフェースとして規定される。デバイスドライバインタフェースは、デバイスドライバとT-Kernelのデバイス管理機能との間のインタフェースである。

デバイスドライバのプログラムは、その保守性や移植性を高めるために、インタフェース層、論理層、物理層の3段階の階層分けを意識して実装することが推奨される。インタフェース層はT-Kernelのデバイス管理機能とデバイスドライバとの間のインタフェースを処理する部分、論理層はデバイスの種類に応じて共通の処理を行う部分、物理層は実際のハードウェアや制御チップに依存した処理を行う部分である。ただし、インタフェース層、論理層、物理層の間のインタフェースについて、T-Kernelで仕様を規定しているわけではなく、実際の階層分けについては、個々のデバイスドライバにおいて最適な実装を行うことができる。インタフェース層については、個々のデバイスに依存しない共通の処理が多いため、インタフェース層の処理を行うプログラムがライブラリとして提供される場合がある。

一方、登録済みのデバイスドライバをアプリケーションやミドルウェアから利用するために、オープン(tk_opn_dev())、クローズ(tk_cls_dev())、読込み(tk_rea_dev())、書込み(tk_wri_dev())などが拡張SVCとして提供されている。これらの拡張SVCの仕様をアプリケーションインタフェースと呼ぶ。たとえば、アプリケーションがデバイスをオープンするために tk_opn_dev() を実行した場合、T-Kernelは、対応するデバイスドライバのオープン関数(openfn)を呼び出して、デバイスのオープンの処理を依頼する。

T-Kernelのデバイス管理機能の位置付けと構成を[図1]に示す。

図 1. デバイス管理機能

注意補足事項
 

デバイスドライバは、T-Kernel本体とは独立して実装され、T-Kernelの機能に対して拡張や追加を行うシステムプログラムであるという点で、サブシステムと共通の特徴を持つ。また、プログラムを共有空間にロードして実行する点や、保護レベル0で動作し、ハードウェアへのアクセスが可能である点についても、両者とも同じである。一方、両者の相違点としては、デバイスドライバを呼び出す際のAPIがオープン/クローズ、リード/ライト型に固定されているのに対して、サブシステムを呼び出す際のAPIは自由に定義できる。また、サブシステムの場合はリソースの管理を行う機能があるが、デバイスドライバの場合はそのような機能がない。

デバイス管理機能によって管理されるT-Kernelのデバイスドライバは、物理的な意味でのデバイスやハードウェアに対するドライバを想定した機能であるが、物理的な意味でのデバイスやハードウェアを扱うことが必須ではない。一方、デバイスを操作するためのシステムプログラムであっても、オープン/クローズ、リード/ライト型のAPIが馴染まない場合など、デバイスドライバではなくサブシステムとして実装されることがある。

デバイスドライバに関する共通事項

デバイスの基本概念

デバイスには、物理的なハードウェアとしてのデバイスを表す物理デバイスのほかに、ソフトウェアから見たデバイスの単位である論理デバイスがある。

多くのデバイスにおいて両者は一致するが、ハードディスクやストレージ系のデバイス(SDカード, USBストレージなど)の中に区画(パーティション)を作った場合には、デバイス全体が物理デバイス、1つの区画が論理デバイスとなる。

同種類の物理デバイスは「ユニット」により区別され、1つの物理デバイス内の論理デバイスは「サブユニット」により区別される。たとえば、1台目のハードディスクと2台目のハードディスクを区別する情報が「ユニット」であり、1台目のハードディスク内の1つ目の区画と2つ目の区画を区別する情報が「サブユニット」である。

デバイス管理機能で使用するデータの定義は、以下の通りである。

デバイス名 (UB*型)

デバイス名は、デバイス毎につけられた最大8文字の文字列であり、次の要素により構成される。

#define L_DEVNM         8       /* デバイス名の長さ */

種別

デバイスの種別を示す名前

使用可能な文字は a~z A~Z

ユニット

物理的なデバイスを示す英字1文字

a~zでユニットごとにaから順に割り当てる

サブユニット

論理的なデバイスを示す数字最大3文字

0~254でサブユニットごとに0から順に割り当てる

デバイス名は、種別+ユニット+サブユニットの形式で表すが、ユニット、サブユニットはデバイスによっては存在しない場合もあり、その場合はそれぞれのフィールドは存在しない。

サブユニットは、ハードディスクなどの区画(パーティション)を区別するために使用するが、それ以外のデバイスにおいても、1つの物理デバイスの中に複数の論理的なデバイスを設けたい場合に使用できる。

種別+ユニットの形式を物理デバイス名と呼ぶ。また、種別+ユニット+サブユニットを論理デバイス名と呼ぶ。サブユニットがない場合は、物理デバイス名と論理デバイス名は同じになる。単にデバイス名と言ったときは、論理デバイス名を指す。

例 1. デバイス名の例

デバイス名対象デバイス
hdaハードディスク(ディスク全体)
hda0ハードディスク(先頭の区画)
fdaフロッピーディスク
rsaシリアルポート
kbpdキーボード/ポインティングデバイス

デバイスID (ID型)

デバイス(デバイスドライバ)を T-Kernel/SMに登録することにより、デバイス(物理デバイス名)に対してデバイスID(>0)が割り当てられる。デバイスIDは物理デバイスごとに割り当てられ、論理デバイスのデバイスIDは物理デバイスに割り当てられたデバイスIDにサブユニット番号+1(1~255)を加えたものとなる。

devid: 登録時に割り当てられたデバイスID

devid           物理デバイス
devid + n+1     n 番目のサブユニット(論理デバイス)

例 2. デバイスIDの例

デバイス名デバイスID説明
hdadevidハードディスク(ディスク全体)
hda0devid + 1ハードディスクの先頭の区画
hda1devid + 2ハードディスクの2番目の区画

デバイス属性 (ATR型)

各デバイスの特徴を表すとともに、デバイスの種類分けを行うため、デバイス属性を定義する。デバイス属性は、デバイスドライバを登録する際に指定する。

デバイス属性の指定方法は、次の通りである。

IIII IIII IIII IIII PRxx xxxx KKKK KKKK

上位16ビットは、デバイス依存属性で、デバイスごとに定義される。下位16ビットは、標準属性で、下記のように定義される。

#define TD_PROTECT      0x8000  /* P: 書込み禁止 */
#define TD_REMOVABLE    0x4000  /* R: メディアの取り外し可能 */

#define TD_DEVKIND      0x00ff  /* K: デバイス/メディア種別 */
#define TD_DEVTYPE      0x00f0  /*    デバイスタイプ */

                                /* デバイスタイプ */
#define TDK_UNDEF       0x0000  /* 未定義/不明 */
#define TDK_DISK        0x0010  /* ディスクデバイス */

上記のデバイスタイプのうち、ディスクタイプ(TDK_DISK)であるかどうかは、サスペンド時の処理手順に影響する。詳細は tk_sus_dev および「ディスクデバイスの特殊性」を参照のこと。

T-Kernelの範囲では、ディスクタイプ以外のデバイスタイプは定義されておらず、ディスクタイプ以外のデバイスタイプを定義しても、T-Kernelの動作には影響しない。未定義のデバイスは、未定義 TDK_UNDEF とする。

ディスクデバイスの場合には、さらに、ディスク種別が定義される。代表的なディスク種別は以下の通りである。これ以外のディスク種別については、デバイスドライバ関連の仕様書、あるいは「参考とすべきデバイスドライバ関連の仕様付録」の「デバイス属性のディスク種別付録」を参照のこと。

/* ディスク種別 */
#define TDK_DISK_UNDEF  0x0010  /* その他のディスク */
#define TDK_DISK_HD     0x0015  /* ハードディスク */
#define TDK_DISK_CDROM  0x0016  /* CD-ROM */

ディスク種別の定義も、T-Kernelの動作には影響しない。これらの定義は、デバイスドライバやアプリケーションにおいて、必要な場合にのみ利用する。たとえば、アプリケーションがデバイスやメディアの種類によって処理内容を変える必要がある場合に、ディスク種別の情報を利用する。特に明確な区別をする必要がないデバイスやメディアに対しては、必ずしもディスク種別を割り当てる必要はない。

デバイスディスクリプタ (ID型)

デバイスディスクリプタは、デバイスをアクセスするための識別子である。

デバイスディスクリプタは、デバイスをオープンしたときに、T-Kernel/SMによって正の値(>0)が割り当てられる。

デバイスディスクリプタは、そのデバイスをオープンしたタスクと同じリソースグループに所属する。デバイスディスクリプタを使用した操作は、そのデバイスディスクリプタと同じリソースグループに所属するタスクからしかできない。異なるリソースグループに所属するタスクからの要求はエラーとなる(E_OACV)。

リクエストID (ID型)

デバイスに対する入出力を要求したときには、その要求の識別子として、リクエストID(>0)が割り当てられる。このリクエストIDにより入出力の完了を待つことができる。

データ番号 (W型, D型)

デバイスから入出力するデータはデータ番号により指定する。データは固有データと属性データに大別される。

固有データ:データ番号≧0

デバイス固有のデータで、データ番号はデバイスごとに定義される。

例 3. 固有データの例

デバイスデータ番号
ディスクデータ番号=物理ブロック番号
シリアル回線データ番号は0のみ使用

属性データ:データ番号<0

ドライバやデバイスの状態の取得や設定、特殊機能などを指定する。

データ番号のいくつかは共通で定義されているが、デバイス独自にも定義できる。詳細は「属性データ」を参照。

属性データ

属性データは大きく次の3つに分類される。

共通属性

すべてのデバイス(デバイスドライバ)に共通に定義する属性。

デバイス種別属性

同じ種類に分類されるデバイス(デバイスドライバ)に共通に定義する属性。

デバイス個別属性

各デバイス(デバイスドライバ)ごとに独自に定義される属性。

デバイス種別属性およびデバイス個別属性については、デバイスドライバ関連の仕様書を参照のこと。ここでは、共通属性のみ定義する。

共通属性の属性データ番号は -1~-99 の範囲となる。共通属性のデータ番号はすべてのデバイスで共通となるが、すべてのデバイスが必ずしもすべての共通属性に対応しているとは限らない。対応していないデータ番号を指定されたときは、エラー E_PAR とする。

共通属性の定義は、以下の通りである。

#define TDN_EVENT       (-1)    /* RW:事象通知用メッセージバッファID */
#define TDN_DISKINFO    (-2)    /* R-:ディスク情報 */
#define TDN_DISPSPEC    (-3)    /* R-:表示デバイス仕様 */
#define TDN_PCMCIAINFO  (-4)    /* R-:PCカード情報 */
#define TDN_DISKINFO_D  (-5)    /* R-:ディスク情報(64ビットデバイス) */

RW: 読込み(tk_rea_dev)/書込み(tk_wri_dev)可能
R-: 読込み(tk_rea_dev)のみ可能

TDN_EVENT

事象通知用メッセージバッファID

データ形式ID

デバイス事象通知用のメッセージバッファのIDである。

デバイスドライバの起動時には、tk_def_dev によってデバイスの登録を行うが、このAPIのリターンパラメータとしてシステムデフォルトの事象通知用メッセージバッファID(evtmbfid)が返されるので、その値をデバイスドライバ内で保持し、本属性データの初期値とする。

0が設定されている場合は、デバイス事象通知を行わない。デバイス事象通知については、「デバイス事象通知」を参照。

TDN_DISKINFO

32ビットデバイス・ディスク情報

データ形式DiskInfo

typedef enum {
        DiskFmt_STD     = 0,            /* 標準(HDなど) */
        DiskFmt_2HD     = 2,            /* 2HD 1.44MB */
        DiskFmt_CDROM   = 4             /* CD-ROM 640MB */
} DiskFormat;
typedef struct {
        DiskFormat format;              /* フォーマット形式 */
        UW      protect:1;              /* プロテクト状態 */
        UW      removable:1;            /* 取り外し可否 */
        UW      rsv:30;                 /* 予約 (常に0) */
        W       blocksize;              /* ブロックバイト数 */
        W       blockcount;             /* 総ブロック数 */
} DiskInfo;

上記の記載以外のDiskFormatの定義については、デバイスドライバ関連の仕様書、あるいは「参考とすべきデバイスドライバ関連の仕様付録」の「デバイスの属性データ付録」を参照のこと。

TDN_DISPSPEC

表示デバイス仕様

データ形式DEV_SPEC

DEV_SPECの定義については、デバイスドライバ関連の仕様書、あるいは「参考とすべきデバイスドライバ関連の仕様付録」の「デバイスの属性データ付録」を参照のこと。

TDN_DISKINFO_D

64ビットデバイス・ディスク情報

データ形式DiskInfo_D

typedef struct diskinfo_d {
        DiskFormat format;      /* フォーマット形式 */
        BOOL    protect:1;      /* プロテクト状態 */
        BOOL    removable:1;    /* 取り外し可否 */
        UW      rsv:30;         /* 予約 (0) */
        W       blocksize;      /* ブロックバイト数 */
        D       blockcont_d;    /* 64ビットの総ブロック数 */
} DiskInfo_D;

DiskInfo_DとDiskInfoとの差異は、blockcont あるいは blockcont_d の部分の名称およびデータタイプのみである。

T-Kernel/SMは、DiskInfoとDiskInfo_Dの間の変換は行わない。TDN_DISKINFOTDN_DISKINFO_D も、デバイスドライバへの要求をそのまま渡すのみである。

ディスクドライバは、TDN_DISKINFO または TDN_DISKINFO_D のいずれか一方、または両方に対応する必要がある。T-Kernel 1.0との互換性のため、TDN_DISKINFO は可能な限り対応することを推奨する。

ディスク全体の総ブロック数がWに収まらない場合でも、個々の区画のブロック数はWに収まることがある。そのような場合、Wに収まる区画は TDN_DISKINFO に対応し、Wに収まらないもののみ TDN_DISKINFO はエラー(E_PAR)とするような実装が望ましい。また、ブロック数がWに収まる場合であっても、TDN_DISKINFO_D に対応することは望ましいことである。

TDN_DISKINFO_D への対応とデバイスドライバ属性の TDA_DEV_D には直接の依存関係がない。TDN_DISKINFO_D に対応しているからといって TDA_DEV_D 属性のデバイスドライバであるとは限らないし、TDA_DEV_D 属性のデバイスドライバであっても TDN_DISKINFO_D に対応しているとは限らない。

なお、上記の共通属性の定義は、T-Kernelではなくデバイスドライバの仕様の一部を定めるものであり、T-Kernelの動作には直接影響しない。また、各デバイスドライバは、共通属性に定義されたすべての機能を実装する必要はない。しかし、共通属性の定義はすべてのデバイスドライバに対して有効であり、各デバイスドライバの仕様は、これらの定義と矛盾のないように定める必要がある。

注意T-Kernel 1.0との差異
 

64ビットデバイスへの対応のため、TDN_DISKINFO_D の属性データを追加した。

デバイスの入出力操作

登録済みのデバイスドライバをアプリケーションやミドルウェアから利用するためには、アプリケーションインタフェースを使用する。アプリケーションインタフェースには下記の関数があり、拡張SVCにより呼び出す。これらの関数は、タスク独立部およびディスパッチ禁止中、割込み禁止中に呼び出すことはできない(E_CTX)。

ID  tk_opn_dev( CONST UB *devnm, UINT omode )
ER  tk_cls_dev( ID dd, UINT option )
ID  tk_rea_dev( ID dd, W start, void *buf, W size, TMO tmout )
ID  tk_rea_dev_du( ID dd, D start_d, void *buf, W size, TMO_U tmout_u )
ER  tk_srea_dev( ID dd, W start, void *buf, W size, W *asize )
ER  tk_srea_dev_d( ID dd, D start_d, void *buf, W size, W *asize )
ID  tk_wri_dev( ID dd, W start, CONST void *buf, W size, TMO tmout )
ID  tk_wri_dev_du( ID dd, D start_d, CONST void *buf, W size, TMO_U tmout_u )
ER  tk_swri_dev( ID dd, W start, CONST void *buf, W size, W *asize )
ER  tk_swri_dev_d( ID dd, D start_d, CONST void *buf, W size, W *asize )
ID  tk_wai_dev( ID dd, ID reqid, W *asize, ER *ioer, TMO tmout )
ID  tk_wai_dev_u( ID dd, ID reqid, W *asize, ER *ioer, TMO_U tmout_u )
INT tk_sus_dev( UINT mode )
ID  tk_get_dev( ID devid, UB *devnm )
ID  tk_ref_dev( CONST UB *devnm, T_RDEV *rdev )
ID  tk_oref_dev( ID dd, T_RDEV *rdev )
INT tk_lst_dev( T_LDEV *ldev, INT start, INT ndev )
INT tk_evt_dev( ID devid, INT evttyp, void *evtinf )

tk_opn_dev - デバイスのオープン

C言語インタフェース

#include <tk/tkernel.h>

ID dd = tk_opn_dev (CONST UB *devnm , UINT omode );

パラメータ

CONST UB* devnm Device Nameデバイス名
UINT omode Open Modeオープンモード

リターンパラメータ

ID dd Device Descriptorデバイスディスクリプタ
またはError Codeエラーコード

エラーコード

E_BUSY デバイスは使用中(排他オープン中)
E_NOEXS デバイスは存在しない
E_LIMIT オープン可能な最大数を超えた
その他デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

devnm で指定したデバイスを omode で指定したモードでオープンし、デバイスへのアクセスを準備する。戻値に、デバイスディスクリプタを返す。

omode := (TD_READ || TD_WRITE || TD_UPDATE) | [TD_EXCL || TD_WEXCL || TD_REXCL]
         | [TD_NOLOCK]
#define TD_READ         0x0001          /* 読込み専用 */
#define TD_WRITE        0x0002          /* 書込み専用 */
#define TD_UPDATE       0x0003          /* 読込みおよび書込み */
#define TD_EXCL         0x0100          /* 排他 */
#define TD_WEXCL        0x0200          /* 排他書込み */
#define TD_REXCL        0x0400          /* 排他読込み */
#define TD_NOLOCK       0x1000          /* ロック(常駐化)不要 */

TD_READ

読込み専用

TD_WRITE

書込み専用

TD_UPDATE

読込みおよび書込み

アクセスモードを指定する。

TD_READ の場合は、tk_wri_dev() は使用できない。

TD_WRITE の場合は、tk_rea_dev() は使用できない。

TD_EXCL

排他

TD_WEXCL

排他書込み

TD_REXCL

排他読込み

排他モードを指定する。

TD_EXCL は、一切の同時オープンを禁止する。

TD_WEXCL は、書込みモード(TD_WRITE または TD_UPDATE)による同時オープンを禁止する。

TD_REXCL は、読込みモード(TD_READ または TD_UPDATE)による同時オープンを禁止する。

表 1. 同じデバイスを同時にオープンしようとしたときの可否

現在オープンモード同時オープンモード
排他指定なしTD_WEXCLTD_REXCLTD_EXCL
RUWRUWRUWRUW
排他指定なしR××××××
×××××××××
××××××
TD_WEXCLR××××××××××
×××××××××××
××××××××××
TD_REXCLR××××××××××
×××××××××××
××××××××××
TD_EXCLR××××××××××××
××××××××××××
××××××××××××
R = TD_READ
W = TD_WRITE
U = TD_UPDATE
○ = オープン可
× = オープン不可(E_BUSY)
TD_NOLOCK

ロック(常駐化)不要

入出力時(tk_rea_dev/tk_wri_dev)に指定したメモリ(buf)の領域は、呼出側でロック(常駐化)済みで、デバイスドライバ側ではロック不要であることを指示する。この場合、デバイスドライバではロックを行わない(行ってはいけない)。この指定は、仮想記憶システムにおいてページイン/ページアウトのためのディスクアクセスを行う場合などに使用する。一般的には指定する必要はない。

デバイスディスクリプタは、オープンしたタスクのリソースグループに所属する。

なお、物理デバイスをオープンした場合、その物理デバイスに属する論理デバイスをすべて同じモードでオープンしたのと同様に扱い、排他オープンの処理が行われる。

tk_cls_dev - デバイスのクローズ

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_cls_dev (ID dd , UINT option );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
UINT option Close Optionクローズオプション

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

E_ID dd が不正またはオープンされていない
その他デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

dd のデバイスディスクリプタをクローズする。処理中の要求があった場合は、その処理を中止させてクローズする。

option := [TD_EJECT]
#define TD_EJECT        0x0001          /* メディア排出 */

TD_EJECT

メディア排出

同一デバイスが他からオープンされていなければ、メディアを排出する。ただし、メディアの排出ができないデバイスでは無視される。

サブシステムのクリーンアップ処理(tk_cln_ssy)により、対象リソースグループに属するデバイスディスクリプタはすべてクローズされる。

tk_rea_dev - デバイスの読込み開始

C言語インタフェース

#include <tk/tkernel.h>

ID reqid = tk_rea_dev (ID dd , W start , void *buf , W size , TMO tmout );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
W start Start Location読込み開始位置(≧0:固有データ, <0:属性データ)
void* buf Buffer読み込んだデータを格納するバッファ
W size Read Size読み込むサイズ
TMO tmout Timeout要求受付待ちタイムアウト時間(ミリ秒)

リターンパラメータ

ID reqid Request IDリクエストID
またはError Codeエラーコード

エラーコード

E_ID dd が不正またはオープンされていない
E_OACV オープンモードが不正(読込みが許可されていない)
E_LIMIT 最大リクエスト数を超えた
E_TMOUT 他の要求を処理中で受け付けられない
E_ABORT 処理中止
その他 デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

デバイスから固有データまたは属性データの読込みを開始する。読込みを開始するのみで、読込み完了を待たずに呼出元へ戻る。読込みが完了するまで、buf を保持しなければならない。読込み完了は tk_wai_dev() により待つ。読込み開始のための処理にかかる時間はデバイスドライバにより異なる。必ずしも即座に戻るとは限らない。

固有データの場合、start および size の単位はデバイスごとに決められる。属性データの場合、start は属性データ番号、size はバイト数となり、start のデータ番号の属性データを読み込む。通常、size は読み込む属性データのサイズ以上でなければならない。複数の属性データを一度に読み込むことはできない。size=0を指定した場合、実際の読込みは行わず、現時点で読込み可能なサイズを調べる。

読込みまたは書込みの動作中である場合、新たな要求を受け付けられるか否かはデバイスドライバによる。新たな要求を受け付けられない状態の場合、要求受付待ちとなる。要求受付待ちのタイムアウト時間を tmout に指定する。tmout には TMO_POL または TMO_FEVR を指定することもできる。なお、タイムアウトするのは要求受付までである。要求が受け付けられた後にはタイムアウトしない。

TDA_DEV_DTDA_TMO_U 属性のデバイスドライバに対して、本拡張SVCを使用しても構わない。その場合、T-Kernel/SMの中でパラメータを適切に変換する。たとえば、デバイスドライバの属性が TDA_TMO_U の場合、本拡張SVCの tmout で指定されたミリ秒単位のタイムアウト時間が、マイクロ秒単位の時間に換算された上で、TDA_TMO_U 属性のデバイスドライバに渡される。

T-Kernel 1.0との差異

start, size のデータタイプをINTからWに変更した。これは、T-Kernel 2.0で64ビットを導入した機能(時間管理、デバイス管理)と関連の深いパラメータについて、ビット数を固定した方が分かりやすく誤解がないという理由によるものである。MSECやTMOをINTからWに、RELTIMをUINTからUWに変更したのも、μT-Kernelとの関係に加えて、同様の趣旨がある。

tk_rea_dev_du - デバイスの読込み開始(64ビットマイクロ秒単位)

C言語インタフェース

#include <tk/tkernel.h>

ID reqid = tk_rea_dev_du (ID dd , D start_d , void *buf , W size , TMO_U tmout_u );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
D start_d Start Location読込み開始位置(64ビット, ≧0:固有データ, <0:属性データ)
void* buf Buffer読み込んだデータを格納するバッファ
W size Read Size読み込むサイズ
TMO_U tmout_u Timeout要求受付待ちタイムアウト時間(マイクロ秒)

リターンパラメータ

ID reqid Request IDリクエストID
またはError Codeエラーコード

エラーコード

E_ID dd が不正またはオープンされていない
E_OACV オープンモードが不正(読込みが許可されていない)
E_LIMIT 最大リクエスト数を超えた
E_TMOUT 他の要求を処理中で受け付けられない
E_ABORT 処理中止
その他 デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

tk_rea_dev のパラメータである start および tmout を、64ビットの start_d および64ビットマイクロ秒単位の tmout_u とした拡張SVCである。

パラメータが start_d および tmout_u となった点を除き、本拡張SVCの仕様は tk_rea_dev と同じである。詳細は tk_rea_dev の説明を参照のこと。

補足事項

対応するデバイスドライバが TDA_DEV_D 属性のデバイスドライバでない場合に、開始位置 start_d としてWに入りきらない値を指定すると、E_PAR のエラーになる。

また、対応するデバイスドライバが TDA_TMO_U 属性のデバイスドライバでない(マイクロ秒単位に対応していない)場合には、デバイスドライバがマイクロ秒単位のタイムアウトを扱うことができない。この場合は、本拡張SVCの tmout_u で指定されたマイクロ秒単位のタイムアウト時間が、ミリ秒単位の時間に切り上げられた上で、デバイスドライバに渡される。

このように、T-Kernel/SMの中でパラメータの適切な変換を行うので、アプリケーション側では、デバイスドライバの属性が TDA_DEV_D かどうか、すなわちデバイスドライバが64ビット対応かどうかに関して意識する必要はない。

T-Kernel 1.0との差異

T-Kernel 2.0で追加された拡張SVCである。

なお、tk_rea_dev_dutk_wri_dev_du は、開始位置が64ビット、タイムアウトが64ビットマイクロ秒のため、_uと_dの両方の意味を含む。

tk_srea_dev - デバイスの同期読込み

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_srea_dev (ID dd , W start , void *buf , W size , W *asize );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
W start Start Location読込み開始位置(≧0:固有データ, <0:属性データ)
void* buf Buffer読み込んだデータを格納するバッファ
W size Read Size読み込むサイズ
W* asize Actual Size読込みサイズを返す領域へのポインタ

リターンパラメータ

ER ercd Error Codeエラーコード
W asize Actual Size実際の読込みサイズ

エラーコード

E_ID dd が不正またはオープンされていない
E_OACV オープンモードが不正(読込みが許可されていない)
E_LIMIT 最大リクエスト数を超えた
E_ABORT 処理中止
その他 デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

同期読込み。以下と等価である。

ER tk_srea_dev( ID dd, W start, void *buf, W size, W *asize )
{
        ER      er, ioer;

        er = tk_rea_dev(dd, start, buf, size, TMO_FEVR);
        if ( er > 0 ) {
                er = tk_wai_dev(dd, er, asize, &ioer, TMO_FEVR);
                if ( er > 0 ) er = ioer;
        }

        return er;
}

TDA_DEV_D 属性のデバイスドライバに対して、本拡張SVCを使用しても構わない。その場合、T-Kernel/SMの中でパラメータを適切に変換する。

T-Kernel 1.0との差異

start, size のデータタイプをINTからWに、asize のデータタイプをINT *からW *に変更した。

tk_srea_dev_d - デバイスの同期読込み(64ビット)

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_srea_dev_d (ID dd , D start_d , void *buf , W size , W *asize );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
D start_d Start Location読込み開始位置(64ビット, ≧0:固有データ, <0:属性データ)
void* buf Buffer読み込んだデータを格納するバッファ
W size Read Size読み込むサイズ
W* asize Actual Size読込みサイズを返す領域へのポインタ

リターンパラメータ

ER ercd Error Codeエラーコード
W asize Actual Size実際の読込みサイズ

エラーコード

E_ID dd が不正またはオープンされていない
E_OACV オープンモードが不正(読込みが許可されていない)
E_LIMIT 最大リクエスト数を超えた
E_ABORT 処理中止
その他 デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

tk_srea_dev のパラメータである start を、64ビットの start_d とした拡張SVCである。

パラメータが start_d となった点を除き、本拡張SVCの仕様は tk_srea_dev と同じである。詳細は tk_srea_dev の説明を参照のこと。

補足事項

対応するデバイスドライバが TDA_DEV_D 属性のデバイスドライバでない場合に、開始位置 start_d としてWに入りきらない値を指定すると、E_PAR のエラーになる。

このように、T-Kernel/SMの中でパラメータの適切な変換を行うので、アプリケーション側では、デバイスドライバの属性が TDA_DEV_D かどうか、すなわちデバイスドライバが64ビット対応かどうかに関して意識する必要はない。

T-Kernel 1.0との差異

T-Kernel 2.0で追加された拡張SVCである。

tk_wri_dev - デバイスの書込み開始

C言語インタフェース

#include <tk/tkernel.h>

ID reqid = tk_wri_dev (ID dd , W start , CONST void *buf , W size , TMO tmout );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
W start Start Location書込み開始位置(≧0:固有データ, <0:属性データ)
CONST void* buf Buffer書き込むデータを格納したバッファ
W size Write Size書き込むサイズ
TMO tmout Timeout要求受付待ちタイムアウト時間(ミリ秒)

リターンパラメータ

ID reqid Request IDリクエストID
またはError Codeエラーコード

エラーコード

E_ID dd が不正またはオープンされていない
E_OACV オープンモードが不正(書込みが許可されていない)
E_RONLY 書き込めないデバイス
E_LIMIT 最大リクエスト数を超えた
E_TMOUT 他の要求を処理中で受け付けられない
E_ABORT 処理中止
その他デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

デバイスへ固有データまたは属性データの書込みを開始する。書込みを開始するのみで、書込み完了を待たずに呼出元へ戻る。書込みが完了するまで、buf を保持しなければならない。書込み完了は tk_wai_dev() により待つ。書込み開始のための処理にかかる時間はデバイスドライバにより異なる。必ずしも即座に戻るとは限らない。

固有データの場合、start および size の単位はデバイスごとに決められる。属性データの場合、start は属性データ番号、size はバイト数となり、start のデータ番号の属性データに書き込む。通常、size は書き込む属性データのサイズと同じでなければならない。複数の属性データを一度に書き込むことはできない。size=0を指定した場合、実際の書込みは行わず、現時点で書込み可能なサイズを調べる。

読込みまたは書込みの動作中である場合、新たな要求を受け付けられるか否かはデバイスドライバによる。新たな要求を受け付けられない状態の場合、要求受付待ちとなる。要求受付待ちのタイムアウト時間を tmout に指定する。tmout には TMO_POL または TMO_FEVR を指定することもできる。なお、タイムアウトするのは要求受付までである。要求が受け付けられた後にはタイムアウトしない。

TDA_DEV_DTDA_TMO_U 属性のデバイスドライバに対して、本拡張SVCを使用しても構わない。その場合、T-Kernel/SMの中でパラメータを適切に変換する。たとえば、デバイスドライバの属性が TDA_TMO_U の場合、本拡張SVCの tmout で指定されたミリ秒単位のタイムアウト時間が、マイクロ秒単位の時間に換算された上で、TDA_TMO_U 属性のデバイスドライバに渡される。

T-Kernel 1.0との差異

start, size のデータタイプをINTからWに変更した。

tk_wri_dev_du - デバイスの書込み開始(64ビットマイクロ秒単位)

C言語インタフェース

#include <tk/tkernel.h>

ID reqid = tk_wri_dev_du (ID dd , D start_d , CONST void *buf , W size , TMO_U tmout_u );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
D start_d Start Location書込み開始位置(64ビット, ≧0:固有データ, <0:属性データ)
CONST void* buf Buffer書き込むデータを格納したバッファ
W size Write Size書き込むサイズ
TMO_U tmout_u Timeout要求受付待ちタイムアウト時間(マイクロ秒)

リターンパラメータ

ID reqid Request IDリクエストID
またはError Codeエラーコード

エラーコード

E_ID dd が不正またはオープンされていない
E_OACV オープンモードが不正(書込みが許可されていない)
E_RONLY 書き込めないデバイス
E_LIMIT 最大リクエスト数を超えた
E_TMOUT 他の要求を処理中で受け付けられない
E_ABORT 処理中止
その他デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

tk_wri_dev のパラメータである start および tmout を、64ビットの start_d および64ビットマイクロ秒単位の tmout_u とした拡張SVCである。

パラメータが start_d および tmout_u となった点を除き、本拡張SVCの仕様は tk_wri_dev と同じである。詳細は tk_wri_dev の説明を参照のこと。

補足事項

対応するデバイスドライバが TDA_DEV_D 属性のデバイスドライバでない場合に、開始位置 start_d としてWに入りきらない値を指定すると、E_PAR のエラーになる。

また、対応するデバイスドライバが TDA_TMO_U 属性のデバイスドライバでない(マイクロ秒単位に対応していない)場合には、デバイスドライバがマイクロ秒単位のタイムアウトを扱うことができない。この場合は、本拡張SVCの tmout_u で指定されたマイクロ秒単位のタイムアウト時間が、ミリ秒単位の時間に切り上げられた上で、デバイスドライバに渡される。

このように、T-Kernel/SMの中でパラメータの適切な変換を行うので、アプリケーション側では、デバイスドライバの属性が TDA_DEV_D かどうか、すなわちデバイスドライバが64ビット対応かどうかに関して意識する必要はない。

T-Kernel 1.0との差異

T-Kernel 2.0で追加された拡張SVCである。

なお、tk_rea_dev_dutk_wri_dev_du は、開始位置が64ビット、タイムアウトが64ビットマイクロ秒のため、_uと_dの両方の意味を含む。

tk_swri_dev - デバイスの同期書込み

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_swri_dev (ID dd , W start , CONST void *buf , W size , W *asize );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
W start Start Location書込み開始位置(≧0:固有データ,<0:属性データ)
CONST void* buf Buffer書き込むデータを格納したバッファ
W size Write Size書き込むサイズ
W* asize Actual Size書込みサイズを返す領域へのポインタ

リターンパラメータ

ER ercd Error Codeエラーコード
W asize Actual Size実際の書込みサイズ

エラーコード

E_ID dd が不正またはオープンされていない
E_OACV オープンモードが不正(書込みが許可されていない)
E_RONLY 書き込めないデバイス
E_LIMIT 最大リクエスト数を超えた
E_ABORT 処理中止
その他デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

同期書込み。以下と等価である。

ER tk_swri_dev( ID dd, W start, void *buf, W size, W *asize )
{
        ER      er, ioer;

        er = tk_wri_dev(dd, start, buf, size, TMO_FEVR);
        if ( er > 0 ) {
                er = tk_wai_dev(dd, er, asize, &ioer, TMO_FEVR);
                if ( er > 0 ) er = ioer;
        }

        return er;
}

TDA_DEV_D 属性のデバイスドライバに対して、本拡張SVCを使用しても構わない。その場合、T-Kernel/SMの中でパラメータを適切に変換する。

T-Kernel 1.0との差異

start, size のデータタイプをINTからWに、asize のデータタイプをINT *からW *に変更した。

tk_swri_dev_d - デバイスの同期書込み(64ビット)

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_swri_dev_d (ID dd , D start_d , CONST void *buf , W size , W *asize );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
D start_d Start Location書込み開始位置(64ビット, ≧0:固有データ, <0:属性データ)
CONST void* buf Buffer書き込むデータを格納したバッファ
W size Write Size書き込むサイズ
W* asize Actual Size書込みサイズを返す領域へのポインタ

リターンパラメータ

ER ercd Error Codeエラーコード
W asize Actual Size実際の書込みサイズ

エラーコード

E_ID dd が不正またはオープンされていない
E_OACV オープンモードが不正(書込みが許可されていない)
E_RONLY 書き込めないデバイス
E_LIMIT 最大リクエスト数を超えた
E_ABORT 処理中止
その他デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

tk_swri_dev のパラメータである start を、64ビットの start_d とした拡張SVCである。

パラメータが start_d となった点を除き、本拡張SVCの仕様は tk_swri_dev と同じである。詳細は tk_swri_dev の説明を参照のこと。

補足事項

対応するデバイスドライバが TDA_DEV_D 属性のデバイスドライバでない場合に、開始位置 start_d としてWに入りきらない値を指定すると、E_PAR のエラーになる。

このように、T-Kernel/SMの中でパラメータの適切な変換を行うので、アプリケーション側では、デバイスドライバの属性が TDA_DEV_D かどうか、すなわちデバイスドライバが64ビット対応かどうかに関して意識する必要はない。

T-Kernel 1.0との差異

T-Kernel 2.0で追加された拡張SVCである。

tk_wai_dev - デバイスの要求完了待ち

C言語インタフェース

#include <tk/tkernel.h>

ID creqid = tk_wai_dev (ID dd , ID reqid , W *asize , ER *ioer , TMO tmout );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
ID reqid Request IDリクエストID
W* asize Read/Write Actual Size読込み/書込みサイズを返す領域へのポインタ
ER* ioer I/O Error入出力エラーを返す領域へのポインタ
TMO tmout Timeoutタイムアウト時間(ミリ秒)

リターンパラメータ

ID creqid Completed Request ID完了したリクエストID
またはError Codeエラーコード
W asize Read/Write Actual Size実際の読込み/書込みサイズ
ER ioer I/O Error入出力エラー

エラーコード

E_ID dd が不正またはオープンされていない、reqid が不正または dd に対する要求ではない
E_OBJ reqid の要求は他のタスクで完了待ちしている
E_NOEXS 処理中の要求はない(reqid=0の場合のみ)
E_TMOUT タイムアウト(処理継続中)
E_ABORT 処理中止
その他デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

dd に対する reqid の要求の完了を待つ。reqid=0 の場合は、dd に対する要求の内のいずれかが完了するのを待つ。なお、現時点で処理中の要求のみが完了待ちの対象となる。tk_wai_dev() の呼出後に要求された処理は完了待ちの対象とならない。

複数の要求を同時に処理している場合、その要求の完了の順序は必ずしも要求した順序ではなく、デバイスドライバに依存する。ただし、要求した順序で処理した場合と結果が矛盾しないような順序で処理されることは保証される。例えば、ディスクからの読込みの場合、次のような処理順序の変更が考えられる。

要求順ブロック番号

1 4 3 2 5

処理順ブロック番号

1 2 3 4 5

このように順序を入れ替えて処理することにより、シークや回転待ちを減らすことができ、より効率的にディスクアクセスができる。

tmout に完了待ちのタイムアウト時間を指定する。TMO_POL または TMO_FEVR を指定することもできる。タイムアウト(E_TMOUT)した場合は要求された処理を継続中なので、再度 tk_wai_dev() により完了を待つ必要がある。reqid > 0かつ tmoutTMO_FEVR の場合はタイムアウトすることはなく、必ず処理が完了する。

要求された処理に対して、デバイスドライバから処理結果のエラー(入出力エラーなど)が返った場合、そのエラーコードは、戻値ではなく ioer に格納される。具体的には、tk_wai_dev の処理のために呼び出された完了待ち関数 waitfn の中で、要求パケットT_DEVREQの error に格納されたエラーコードが、処理結果のエラーとして ioer に返される。

一方、戻値には、要求の完了待ちが正しくできなかった場合にエラーを返す。戻値にエラーが返された場合、ioer の内容は無意味である。また、戻値にエラーが返された場合は処理を継続中なので、再度 tk_wai_dev() により完了を待つ必要がある。詳細は「waitfn - 完了待ち関数」を参照のこと。

tk_wai_dev() で完了待ち中にタスク例外が発生すると、reqid の要求を中止して処理を完了させる。中止した処理の結果がどのようになるかは、デバイスドライバに依存する。ただし、reqid=0の場合は、要求を中止することなくタイムアウトと同様に扱われる。この場合は、E_TMOUT ではなく E_ABORT を返す。

同じリクエストIDに対して、複数のタスクから同時に完了待ちすることはできない。reqid=0で待っているタスクがあれば、同じ dd に対して他のタスクは完了待ちできない。同様に、reqid > 0で待っているタスクがあれば、他のタスクで reqid=0の完了待ちはできない。

TDA_TMO_U 属性のデバイスドライバに対して、本拡張SVCを使用しても構わない。その場合、T-Kernel/SMの中でパラメータを適切に変換する。たとえば、デバイスドライバの属性が TDA_TMO_U の場合、本拡張SVCの tmout で指定されたミリ秒単位のタイムアウト時間が、マイクロ秒単位の時間に換算された上で、TDA_TMO_U 属性のデバイスドライバに渡される。

T-Kernel 1.0との差異

asize のデータタイプをINT *からW *に変更した。

tk_wai_dev_u - デバイスの要求完了待ち(マイクロ秒単位)

C言語インタフェース

#include <tk/tkernel.h>

ID creqid = tk_wai_dev_u (ID dd , ID reqid , W *asize , ER *ioer , TMO_U tmout_u );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
ID reqid Request IDリクエストID
W* asize Read/Write Actual Size読込み/書込みサイズを返す領域へのポインタ
ER* ioer I/O Error入出力エラーを返す領域へのポインタ
TMO_U tmout_u Timeoutタイムアウト時間(マイクロ秒)

リターンパラメータ

ID creqid Completed Request ID完了したリクエストID
またはError Codeエラーコード
W asize Read/Write Actual Size実際の読込み/書込みサイズ
ER ioer I/O Error入出力エラー

エラーコード

E_ID dd が不正またはオープンされていない、reqid が不正または dd に対する要求ではない
E_OBJ reqid の要求は他のタスクで完了待ちしている
E_NOEXS 処理中の要求はない(reqid=0の場合のみ)
E_TMOUT タイムアウト(処理継続中)
E_ABORT 処理中止
その他デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

tk_wai_dev のパラメータである tmout を、64ビットマイクロ秒単位の tmout_u とした拡張SVCである。

パラメータが tmout_u となった点を除き、本拡張SVCの仕様は tk_wai_dev と同じである。詳細は tk_wai_dev の説明を参照のこと。

補足事項

対応するデバイスドライバが TDA_TMO_U 属性のデバイスドライバでない(マイクロ秒単位に対応していない)場合には、デバイスドライバがマイクロ秒単位のタイムアウトを扱うことができない。この場合は、本拡張SVCの tmout_u で指定されたマイクロ秒単位のタイムアウト時間が、ミリ秒単位の時間に切り上げられた上で、デバイスドライバに渡される。

このように、T-Kernel/SMの中でパラメータの適切な変換を行うので、アプリケーション側では、デバイスドライバの属性が TDA_TMO_U かどうか、すなわちデバイスドライバがマイクロ秒単位に対応かどうかに関して意識する必要はない。

T-Kernel 1.0との差異

T-Kernel 2.0で追加された拡張SVCである。

tk_wai_dev_u は、デバイス管理機能の拡張SVCであるが、_dではなく_uが付くことに注意。

tk_sus_dev - デバイスのサスペンド

C言語インタフェース

#include <tk/tkernel.h>

INT dissus = tk_sus_dev (UINT mode );

パラメータ

UINT mode Modeモード

リターンパラメータ

INT dissus Suspend Disable Request Countサスペンド禁止要求カウント数
またはError Codeエラーコード

エラーコード

E_BUSY サスペンド禁止中
E_QOVR サスペンド禁止要求カウントオーバー

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

mode にしたがって処理を行い、その処理を行ったあとのサスペンド禁止要求カウント数を戻値に返す。

mode := ( (TD_SUSPEND | [TD_FORCE]) || TD_DISSUS || TD_ENASUS || TD_CHECK)
#define TD_SUSPEND      0x0001      /* サスペンド */
#define TD_DISSUS       0x0002      /* サスペンドを禁止 */
#define TD_ENASUS       0x0003      /* サスペンドを許可 */
#define TD_CHECK        0x0004      /* サスペンド禁止要求カウント取得 */
#define TD_FORCE        0x8000      /* 強制サスペンド指定 */

TD_SUSPEND

サスペンド

サスペンド許可状態であればサスペンドする。

サスペンド禁止状態であれば E_BUSY を返す。

TD_SUSPEND|TD_FORCE

強制サスペンド

サスペンド禁止状態であってもサスペンドする。

TD_DISSUS

サスペンド禁止

サスペンドを禁止する。

TD_ENASUS

サスペンド許可

サスペンドを許可する。

自リソースグループでサスペンド禁止した回数以上に許可した場合は何もしない。

TD_CHECK

サスペンド禁止カウント取得

サスペンド禁止要求を行っている回数の取得のみ行う。

サスペンドは、次の手順によって行われる。

  1. 各サブシステムのサスペンド開始前の処理

    tk_evt_ssy(0, TSEVT_SUSPEND_BEGIN, 0, 0)

  2. 各ディスクデバイス以外のサスペンド処理

  3. 各ディスクデバイスのサスペンド処理

  4. 各サブシステムのサスペンド完了後の処理

    tk_evt_ssy(0, TSEVT_SUSPEND_DONE, 0, 0)

  5. サスペンド状態へ移行

    tk_set_pow(TPW_DOSUSPEND)

リジューム(サスペンドからの復帰)は、次の手順によって行われる。

  1. サスペンド状態から復帰

    tk_set_pow(TPW_DOSUSPEND) から戻る

  2. 各サブシステムのリジューム開始前の処理

    tk_evt_ssy(0, TSEVT_RESUME_BEGIN, 0, 0)

  3. 各ディスクデバイスのリジューム処理

  4. 各ディスクデバイス以外のリジューム処理

  5. 各サブシステムのリジューム完了後の処理

    tk_evt_ssy(0, TSEVT_RESUME_DONE, 0, 0)

上記の処理において、各デバイスがディスクデバイスかそれ以外かの判断は、デバイス属性がディスクタイプ(TDK_DISK)かどうかによって行われる。

サスペンド禁止は、その要求回数がカウントされる。同じ回数だけサスペンド許可を要求しないとサスペンドは許可されない。システム起動時はサスペンド許可(サスペンド禁止要求カウント=0)である。サスペンド禁止要求カウントはシステム全体で1つだが、その要求がどのリソースグループから行われたかを管理する。他のリソースグループで行ったサスペンド禁止要求を解除することはできない。なお、リソースグループのクリーンアップ処理が行われることによって、そのリソースグループで行ったサスペンド要求はすべて解除され、サスペンド禁止要求カウントは減算される。サスペンド禁止要求カウントの上限は実装依存だが、最低255回まではカウントできるものとする。上限を超えた場合は E_QOVR を返す。

tk_get_dev - デバイスのデバイス名取得

C言語インタフェース

#include <tk/tkernel.h>

ID pdevid = tk_get_dev (ID devid , UB *devnm );

パラメータ

ID devid Device IDデバイスID
UB* devnm Device Nameデバイス名の格納領域へのポインタ

リターンパラメータ

ID pdevid Device ID of Physical Device物理デバイスのデバイスID
またはError Codeエラーコード
UB devnm Device Nameデバイス名

エラーコード

E_NOEXS devid のデバイスは存在しない

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

devid で示すデバイスのデバイス名を取得し devnm に格納する。

devid は物理デバイスのデバイスIDまたは論理デバイスのデバイスIDである。

devid が物理デバイスであれば、devnm には物理デバイス名が格納される。

devid が論理デバイスであれば、devnm には論理デバイス名が格納される。

devnmL_DEVNM+1 バイト以上の領域が必要である。

戻値には、devid のデバイスが属する物理デバイスのデバイスIDを返す。

tk_ref_dev - デバイスのデバイス情報取得

C言語インタフェース

#include <tk/tkernel.h>

ID devid = tk_ref_dev (CONST UB *devnm , T_RDEV *rdev );

パラメータ

CONST UB* devnm Device Nameデバイス名
T_RDEV* rdev Packet to Refer Device Informationデバイス情報を返す領域へのポインタ

リターンパラメータ

ID devid Device IDデバイスID
またはError Codeエラーコード

rdev の内容

ATR devatr Device Attributeデバイス属性
INT blksz Block Size of Device-specific Data固有データのブロックサイズ(-1:不明)
INT nsub Subunit Countサブユニット数
INT subno Subunit Number0:物理デバイス 1~nsub:サブユニット番号+1
──(以下に実装独自に他の情報を追加してもよい)──

エラーコード

E_NOEXS devnm のデバイスは存在しない

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

devnm で示すデバイスのデバイス情報を取得し、rdev に格納する。rdevNULL とした場合には、デバイス情報は格納されない。

nsub は、devnm で示すデバイスが属する物理デバイスのサブユニット数である。

戻値に devnm のデバイスのデバイスIDを返す。

tk_oref_dev - デバイスのデバイス情報取得

C言語インタフェース

#include <tk/tkernel.h>

ID devid = tk_oref_dev (ID dd , T_RDEV *rdev );

パラメータ

ID dd Device Descriptorデバイスディスクリプタ
T_RDEV* rdev Packet to Refer Device Informationデバイス情報を返す領域へのポインタ

リターンパラメータ

ID devid Device IDデバイスID
またはError Codeエラーコード

rdev の内容

ATR devatr Device Attributeデバイス属性
INT blksz Block Size of Device-specific Data固有データのブロックサイズ(-1:不明)
INT nsub Subunit Countサブユニット数
INT subno Subunit Number0:物理デバイス 1~nsub:サブユニット番号+1
──(以下に実装独自に他の情報を追加してもよい)──

エラーコード

E_ID dd が不正またはオープンされていない

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

dd で示すデバイスのデバイス情報を取得し、rdev に格納する。rdevNULL とした場合には、デバイス情報は格納されない。

nsub は、dd で示すデバイスが属する物理デバイスのサブユニット数である。

戻値に dd のデバイスのデバイスIDを返す。

tk_lst_dev - 登録済みデバイス一覧の取得

C言語インタフェース

#include <tk/tkernel.h>

INT remcnt = tk_lst_dev (T_LDEV *ldev , INT start , INT ndev );

パラメータ

T_LDEV* ldev List of Devices登録デバイス情報の格納領域(配列)
INT start Starting Number開始番号
INT ndev Number of Devices取得数

リターンパラメータ

INT remcnt Remaining Device Count残りの登録数
またはError Codeエラーコード

ldev の内容

ATR devatr Device Attributeデバイス属性
INT blksz Block Size of Device-specific Data固有データのブロックサイズ(-1:不明)
INT nsub Subunit Countサブユニット数
UB devnm[L_DEVNM] Physical Device Name物理デバイス名
──(以下に実装独自に他の情報を追加してもよい)──

エラーコード

E_NOEXS start が登録数を超えている

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

登録済みのデバイスの情報を取得する。登録デバイスは物理デバイス単位で管理される。したがって、登録デバイス情報も物理デバイス単位で取得される。

登録デバイスの数がNの時、登録デバイスに0~N-1の連番を振る。この連番にしたがって、start 番目から ndev 個の登録情報を取得し、ldev に格納する。ldevndev 個の情報を格納するのに十分な大きさの領域でなければならない。戻値には、start 以降の残りの登録数(N-start)を返す。

start 以降の残りが ndev 個に満たない場合は、残りのすべてを格納する。戻値≦ndev であれば、すべての登録情報が取得できたことを示す。なお、この連番はデバイスの登録・抹消があると変化する。したがって、複数回に分けて取得すると、正確な情報が得られない場合がある。

tk_evt_dev - デバイスにドライバ要求イベントを送信

C言語インタフェース

#include <tk/tkernel.h>

INT retcode = tk_evt_dev (ID devid , INT evttyp , void *evtinf );

パラメータ

ID devid Device IDイベント送信先デバイスID
INT evttyp Event Typeドライバ要求イベントタイプ
void* evtinf Event Informationイベントタイプ別の情報

リターンパラメータ

INT retcode Return Code from eventfn eventfn からの戻値
またはError Codeエラーコード

エラーコード

E_NOEXS devid のデバイスは存在しない
E_PAR デバイス管理内部イベント(evttyp < 0)は指定できない
その他 デバイスドライバから返されたエラーコード

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

devid のデバイス(デバイスドライバ)に、ドライバ要求イベントを送信する。

ドライバ要求イベントの機能(処理内容)および evtinf の内容はイベントタイプごとに定義される。ドライバ要求イベントについては、「eventfn - イベント関数」を参照のこと。

デバイスドライバの登録

デバイスドライバの登録方法

デバイスドライバは、物理デバイスごとに登録する。

tk_def_dev - デバイスの登録

C言語インタフェース

#include <tk/tkernel.h>

ID devid = tk_def_dev (CONST UB *devnm , CONST T_DDEV *ddev , T_IDEV *idev );

パラメータ

CONST UB* devnm Physical Device Name物理デバイス名
CONST T_DDEV* ddev Define Deviceデバイス登録情報
T_IDEV* idev Initial Device Informationデバイス初期情報

リターンパラメータ

ID devid Device IDデバイスID
またはError Codeエラーコード

idev の内容

ID evtmbfid Event Notification Message Buffer ID事象通知用メッセージバッファID
──(以下に実装独自に他の情報を追加してもよい)──

エラーコード

E_LIMIT 登録可能な最大数を超えた
E_NOEXS devnm のデバイスは存在しない(ddevNULL の場合)

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

devnm のデバイス名でデバイス(デバイスドライバ)を登録し、登録したデバイスのデバイスIDを戻値に返す。devnm のデバイスがすでに登録されているときは、新しい登録情報で更新する。更新の場合は、デバイスIDは変更されない。

ddev でデバイス登録情報を指定する。ddevNULL の場合は、devnm のデバイス登録を抹消する。

ddev は次の形式の構造体である。

typedef struct t_ddev {
        void    *exinf;   /* 拡張情報 */
        ATR     drvatr;   /* ドライバ属性 */
        ATR     devatr;   /* デバイス属性 */
        INT     nsub;     /* サブユニット数 */
        INT     blksz;    /* 固有データのブロックサイズ (-1:不明) */
        FP      openfn;   /* オープン関数 */
        FP      closefn;  /* クローズ関数 */
        FP      execfn;   /* 処理開始関数 */
        FP      waitfn;   /* 完了待ち関数 */
        FP      abortfn;  /* 中止処理関数 */
        FP      eventfn;  /* イベント関数 */
        /* 以下に実装独自の情報が追加される場合がある */
} T_DDEV;

exinf は、任意の情報の格納に使用できる。この値は、各処理関数に渡される。内容に関してデバイス管理では関知しない。

drvatr は、デバイスドライバの属性に関する情報を設定する。下位側がシステム属性を表し、上位側が実装独自属性を表す。実装独自属性は、T_DDEVに実装独自データを追加する場合に有効フラグを定義するためなどに使用する。

drvatr := [TDA_OPENREQ] | [TDA_TMO_U] | [TDA_DEV_D]
#define TDA_OPENREQ     0x0001  /* 毎回オープン/クローズ */
#define TDA_TMO_U       0x0002  /* マイクロ秒単位タイムアウト時間使用 */
#define TDA_DEV_D       0x0004  /* 64ビットデバイス */

drvatr では、以下のドライバ属性を組み合わせて指定することができる。

TDA_OPENREQ

デバイスが多重オープンされた場合、通常は最初のオープン時に openfn が呼び出され、最後のクローズ時に closefn が呼び出される。TDA_OPENREQ を指定した場合、多重オープンの場合でもすべてのオープン/クローズ時に openfn/closefn が呼び出される。

TDA_TMO_U

マイクロ秒単位タイムアウト時間を使用することを示す。

この場合、ドライバ処理関数のタイムアウト指定 tmout がTMO_U型(マイクロ秒単位)となる。

TDA_DEV_D

64ビットデバイスを使用することを示す。この場合、ドライバ処理関数の要求パケット devreq の型がT_DEVREQ_Dとなる。

TDA_TMO_U および TDA_DEV_D を指定した場合、ドライバ処理関数の一部の引数の型が変化する。このような引数の型を変化させるドライバ属性を複数組み合わせて指定した場合は、指定されたすべての型変化を行った引数を持つドライバ処理関数となる。

devatr は、デバイス属性を設定する。デバイス属性の詳細については前述。

nsub は、サブユニット数を設定する。サブユニットがない場合は0とする。

blksz は、固有データのブロックサイズをバイト数で設定する。ディスクデバイスの場合は、物理ブロックサイズとなる。シリアル回線などは1バイトとなる。固有データのないデバイスでは0とする。未フォーマットのディスクなど、ブロックサイズが不明の場合は-1とする。blksz≦0の場合は、固有データにアクセスできない。tk_rea_dev, tk_wri_dev で固有データをアクセスする場合に、size * blksz がアクセスする領域サイズ、つまり buf のサイズとならなければならない。

openfn, closefn, execfn, waitfn, abortfn, eventfn は、ドライバ処理関数のエントリーアドレスを設定する。ドライバ処理関数の詳細については、「デバイスドライバインタフェース」を参照。

idev にデバイス初期情報が返される。ここには、デバイスドライバ起動時のデフォルトとして設定するための情報などが返されるので、必要に応じて利用する。idevNULL とした場合には、デバイス初期情報は格納されない。

evtmbfid は、システムデフォルトの事象通知用メッセージバッファIDである。システムデフォルトの事象通知用メッセージバッファがない場合は0が設定される。

デバイス登録および抹消が行われたとき、各サブシステムに対して次のように通知が行われる。devid は登録・抹消された、物理デバイスのデバイスIDである。

デバイス登録・更新時

tk_evt_ssy(0, TSEVT_DEVICE_REGIST, 0, devid)

デバイス抹消時

tk_evt_ssy(0, TSEVT_DEVICE_DELETE, 0, devid)

T-Kernel 1.0との差異

64ビットデバイスへの対応のため、drvatr の属性として TDA_TMO_U および TDA_DEV_D を追加した。

tk_ref_idv - デバイス初期情報の取得

C言語インタフェース

#include <tk/tkernel.h>

ER ercd = tk_ref_idv (T_IDEV *idev );

パラメータ

T_IDEV* idev Packet to Refer Initial Device Informationデバイス初期情報を返す領域へのポインタ

リターンパラメータ

ER ercd Error Codeエラーコード

idev の内容

ID evtmbfid Event Notification Message Buffer ID事象通知用メッセージバッファID
──(以下に実装独自に他の情報を追加してもよい)──

エラーコード

E_MACV メモリアクセス権違反

利用可能なコンテキスト

タスク部準タスク部タスク独立部
×

解説

デバイス初期情報を取得する。tk_def_dev() で得られるものと同じ内容である。

補足事項

E_MACV のエラーは、多くのシステムコールで共通に発生する可能性があり、通常はシステムコール別のエラーコードには記載していない。しかし、本拡張SVCの場合は代表的なエラーが E_MACV のみであるため、エラーコード欄にこのエラーを記載している。

デバイスドライバインタフェース

デバイスドライバインタフェースは、デバイス登録時に指定した処理関数(ドライバ処理関数)群によって構成される。

オープン関数

ER openfn(ID devid, UINT omode, void *exinf);

クローズ関数

ER closefn(ID devid, UINT option, void *exinf);

処理開始関数

ER execfn(T_DEVREQ *devreq, TMO tmout, void *exinf);

完了待ち関数

INT waitfn(T_DEVREQ *devreq, INT nreq, TMO tmout, void *exinf);

中止処理関数

ER abortfn(ID tskid, T_DEVREQ *devreq, INT nreq, void *exinf);

イベント関数

INT eventfn(INT evttyp, void *evtinf, void *exinf);

ドライバ属性に TDA_TMO_U を指定した場合、次のドライバ処理関数のタイムアウト指定 tmout がTMO_U型(マイクロ秒単位)となる。

処理開始関数

ER execfn(T_DEVREQ *devreq, TMO_U tmout_u, void *exinf);

完了待ち関数

INT waitfn(T_DEVREQ *devreq, INT nreq, TMO_U tmout_u, void *exinf);

ドライバ属性に TDA_DEV_D を指定した場合、次のドライバ処理関数の要求パケット devreq の型がT_DEVREQ_Dとなる。

処理開始関数

ER execfn(T_DEVREQ_D *devreq_d, TMO tmout, void *exinf);

完了待ち関数

INT waitfn(T_DEVREQ_D *devreq_d, INT nreq, TMO tmout, void *exinf);

中止処理関数

ER abortfn(ID tskid, T_DEVREQ_D *devreq_d, INT nreq, void *exinf);

ドライバ属性に TDA_TMO_UTDA_DEV_D を指定した場合、指定されたすべての型変化を行った引数を持つドライバ処理関数となる。

処理開始関数

ER execfn(T_DEVREQ_D *devreq_d, TMO_U tmout_u, void *exinf);

完了待ち関数

INT waitfn(T_DEVREQ_D *devreq_d, INT nreq, TMO_U tmout_u, void *exinf);

ドライバ処理関数は、デバイス管理によって呼び出され、準タスク部として実行される。これらのドライバ処理関数は、再入可能(reentrant)でなければならない。また、ドライバ処理関数が排他的に呼び出されることは保証されない。例えば、複数のタスクから同じデバイスに対して同時に要求があった場合、それぞれのタスクが同時にドライバ処理関数を呼び出すことがある。デバイスドライバ側は、必要に応じて排他制御などを行う必要がある。

デバイスドライバへの入出力要求は、リクエストIDに対応した下記の要求パケットにより行う。

/*
 * デバイス要求パケット: 32ビット用
 * In:  ドライバ処理関数への入力パラメータ(T-Kernel/SMのデバイス管理で設定)
 * Out: ドライバ処理関数からの出力パラメータ(ドライバ処理関数で設定)
 */
typedef struct t_devreq {
        struct t_devreq *next;    /* In:要求パケットのリンク (NULL:終端) */
        void     *exinf;          /* X:拡張情報 */
        ID       devid;           /* In:対象デバイスID */
        INT      cmd:4;           /* In:要求コマンド */
        BOOL     abort:1;         /* In:中止要求を行った時 TRUE */
        BOOL     nolock:1;        /* In:ロック(常駐化)不要のとき TRUE */
        INT      rsv:26;          /* In:予約(常に0) */
        T_TSKSPC tskspc;          /* In:要求タスクのタスク固有空間 */
        W        start;           /* In:開始データ番号 */
        W        size;            /* In:要求サイズ */
        void     *buf;            /* In:入出力バッファアドレス */
        W        asize;           /* Out:結果サイズ */
        ER       error;           /* Out:結果エラー */
        /* 以下に実装独自の情報が追加される場合がある */
} T_DEVREQ;
/*
 * デバイス要求パケット: 64ビット用
 * In:  ドライバ処理関数への入力パラメータ(T-Kernel/SMのデバイス管理で設定)
 * Out: ドライバ処理関数からの出力パラメータ(ドライバ処理関数で設定)
 */
typedef struct t_devreq_d {
        struct t_devreq_d *next;  /* In:要求パケットのリンク (NULL:終端) */
        void     *exinf;          /* X:拡張情報 */
        ID       devid;           /* In:対象デバイスID */
        INT      cmd:4;           /* In:要求コマンド */
        BOOL     abort:1;         /* In:中止要求を行った時 TRUE */
        BOOL     nolock:1;        /* In:ロック(常駐化)不要のとき TRUE */
        INT      rsv:26;          /* In:予約(常に0) */
        T_TSKSPC tskspc;          /* In:要求タスクのタスク固有空間 */
        D        start_d;         /* In:開始データ番号, 64ビット */
        W        size;            /* In:要求サイズ */
        void     *buf;            /* In:入出力バッファアドレス */
        W        asize;           /* Out:結果サイズ */
        ER       error;           /* Out:結果エラー */
        /* 以下に実装独自の情報が追加される場合がある */
} T_DEVREQ_D;

In: はドライバ処理関数への入力パラメータであり、T-Kernel/SMのデバイス管理で設定され、デバイスドライバ側で変更してはならない。入力パラメータ(In:)以外は、デバイス管理により最初に0クリアされる。その後はデバイス管理は変更しない。Out: はドライバ処理関数から戻る際の出力パラメータであり、ドライバ処理関数の中で設定する。

next は、要求パケットをリンクするために使用する。デバイス管理内の要求パケットの管理に使用される他、完了待ち関数(waitfn),中止処理関数(abortfn)でも使用する。

exinf は、デバイスドライバ側で任意に使用できる。デバイス管理では内容には関知しない。

devid は、要求対象のデバイスIDが設定される。

cmd は、要求コマンドが設定される。

cmd := (TDC_READ || TDC_WRITE)
#define TDC_READ        1       /* 読込み要求 */
#define TDC_WRITE       2       /* 書込み要求 */

abort は中止処理を行う場合、中止処理関数(abortfn)を呼び出す直前に TRUE を設定する。abort は中止処理を要求したことを示すフラグであり、処理が中止されたことを示すものではない。また、中止処理関数(abortfn)を呼び出さない場合でも abortTRUE に設定される場合がある。abortTRUE に設定された要求がデバイスドライバに渡された場合は、中止処理を行う。

nolock は、buf の領域が呼出側ですでにロック(常駐化)されており、デバイスドライバ側ではロック不要であることを示す。この場合、デバイスドライバはロックを行ってはいけない。(デバイスドライバでロックを行うと正しく動作しなくなる可能性がある状況で nolock が指定される。したがって、nolockTRUE の場合はロックを行ってはいけない。)

tskspc は、デバイス入出力操作のAPIを発行したタスク(API発行タスク)のタスク固有空間が設定される。処理関数は、API発行タスクを要求タスクとする準タスク部のコンテキストで実行されるため、tskspc は処理関数のタスク固有空間と同じである。しかし、実際の入出力処理(buf の領域の読込み/書込み)をデバイスドライバ内の別タスクで行う場合は、実際の入出力処理を行うタスクのタスク固有空間を、API発行タスクのタスク固有空間に切り替える必要がある。

start, start_d, size は、tk_rea_dev(), tk_rea_dev_du(), tk_wri_dev(), tk_wri_dev_du() で指定された start, start_d, size がそのまま設定される。

buf は、tk_rea_dev(), tk_rea_dev_du(), tk_wri_dev(), tk_wri_dev_du() で指定された buf がそのまま設定される。buf の指す領域は、非常駐である場合やタスク固有空間である場合がある。そのため、次の点に注意する必要がある。

  • 非常駐のメモリは、タスク独立部やディスパッチ禁止・割込み禁止の状態でアクセスすることはできない。

  • タスク固有空間のメモリは、異なるタスク固有空間からはアクセスできない。

そのため、必要に応じてタスク固有空間の切り替えや常駐化を行わなければならない。特に割込みハンドラから直接アクセスする場合には注意が必要である。一般的には、buf の領域に割込みハンドラから直接アクセスしない方がよい。また、buf の領域をアクセスする前に、buf の領域の有効性をアドレス空間チェック機能(ChkSpace~)により検査する必要がある。(ChkSpace~ については前述)

asize は、tk_wai_dev()asize に返す値をデバイスドライバが設定する。

error は、tk_wai_dev() の戻値として返すエラーコードをデバイスドライバが設定する。正常であれば E_OK を設定する。

T_DEVREQとT_DEVREQ_Dとの差異は、start あるいは start_d の部分の名称およびデータタイプのみである。

デバイス要求パケットの種類(T_DEVREQまたはT_DEVREQ_D)は、デバイス登録時のドライバ属性 TDA_DEV_D によって選択される。したがって、1つのドライバに対する要求パケットにT_DEVREQとT_DEVREQ_Dが混在することはない。

注意T-Kernel 1.0との差異
 

T_DEVREQの start, size, asize のデータタイプをINTからWに変更した。また、64ビットデバイスへの対応のため、T_DEVREQ_Dのデバイス要求パケットを追加した。

openfn - オープン関数

C言語インタフェース

ER ercd = openfn (ID devid , UINT omode , void *exinf );

パラメータ

ID devid Device IDオープンするデバイスのデバイスID
UINT omode Open Modeオープンモード(tk_opn_dev と同じ)
void* exinf Extended Informationデバイス登録時に指定した拡張情報

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

その他 デバイスドライバの返すエラーコード

解説

tk_opn_dev() が呼び出されたときに、オープン関数 openfn が呼び出される。

openfn では、デバイスの使用開始のための処理を行う。処理内容はデバイスに依存し、何もする必要がなければ何もしなくてもよい。また、オープンされているか否かをデバイスドライバで記憶する必要もなく、オープンされていない(openfn が呼び出されていない)という理由だけで、他の処理関数が呼び出されたときエラーにする必要もない。オープンされていない状態で他の処理関数が呼び出された場合でも、デバイスドライバの動作に問題がなければ要求を処理してしまって構わない。

openfn でデバイスの初期化等を行う場合でも、待ちを伴うような処理は原則として行わない。できる限り速やかに処理を行い openfn から戻らなければならない。例えば、シリアル回線のように通信モードを設定する必要があるようなデバイスでは、tk_wri_dev() により通信モードが設定されたときにデバイスの初期化を行えばよい。openfn ではデバイスの初期化を行う必要はない。

同じデバイスが多重オープンされた場合、通常は最初のオープン時のみ呼び出されるが、デバイス登録時にドライバ属性として TDA_OPENREQ が指定された場合は、すべてのオープン時に呼び出される。

多重オープンやオープンモードに関する処理はデバイス管理で行われるため、openfn ではそれらに関する処理は特に必要ない。omode も参考情報として渡されるだけで、omode に関する処理を行う必要はない。

openfn は、tk_opn_dev の発行タスクの準タスク部として実行される。すなわち、tk_opn_dev の発行タスクを要求タスクとする準タスク部のコンテキストで実行される。

closefn - クローズ関数

C言語インタフェース

ER ercd = closefn (ID devid , UINT option , void *exinf );

パラメータ

ID devid Device IDクローズするデバイスのデバイスID
UINT option Close Optionクローズオプション(tk_cls_dev と同じ)
void* exinf Extended Informationデバイス登録時に指定した拡張情報

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

その他 デバイスドライバの返すエラーコード

解説

tk_cls_dev() が呼び出されたときに、クローズ関数 closefn が呼び出される。

closefn では、デバイスの使用終了のための処理を行う。処理内容はデバイスに依存し、何もする必要がなければ何もしなくてもよい。

メディアの取り外しが可能なデバイスの場合、optionTD_EJECT が指定されていたならメディアの排出を行う。

closefn でデバイスの終了処理やメディアの排出を行う場合でも、待ちを伴うような処理は原則として行わない。できる限り速やかに処理を行い closefn から戻らなければならない。メディアの排出に時間がかかる場合、排出の完了を待たずに closefn から戻っても構わない。

同じデバイスが多重オープンされていた場合、通常は最後のクローズ時のみ呼び出されるが、デバイス登録時にドライバ属性として TDA_OPENREQ が指定された場合は、すべてのクローズ時に呼び出される。ただし、この場合も最後のクローズにしか optionTD_EJECT が指定されることはない。

多重オープンやオープンモードに関する処理はデバイス管理で行われるため、closefn ではそれらに関する処理は特に必要ない。

closefn は、tk_cls_dev の発行タスクの準タスク部として実行される。クリーンアップ処理によるデバイスクローズの場合は、クリーンアップ関数のコンテキスト、すなわち tk_cln_ssy の発行タスクの準タスク部として実行される。

execfn - 処理開始関数

C言語インタフェース

/* 処理開始関数(32ビット要求パケット、ミリ秒タイムアウト) */

ER ercd = execfn (T_DEVREQ *devreq , TMO tmout , void *exinf );

/* 処理開始関数(64ビット要求パケット、ミリ秒タイムアウト) */

ER ercd = execfn (T_DEVREQ_D *devreq_d , TMO tmout , void *exinf );

/* 処理開始関数(32ビット要求パケット、マイクロ秒タイムアウト) */

ER ercd = execfn (T_DEVREQ *devreq , TMO_U tmout_u , void *exinf );

/* 処理開始関数(64ビット要求パケット、マイクロ秒タイムアウト) */

ER ercd = execfn (T_DEVREQ_D *devreq_d , TMO_U tmout_u , void *exinf );

パラメータ

T_DEVREQ* devreq Device Request Packet要求パケット(32ビット)
T_DEVREQ_D* devreq_d Device Request Packet要求パケット(64ビット)
TMO tmout Timeout要求受付待ちタイムアウト時間(ミリ秒)
TMO_U tmout_u Timeout要求受付待ちタイムアウト時間(マイクロ秒)
void* exinf Extended Informationデバイス登録時に指定した拡張情報

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

その他 デバイスドライバの返すエラーコード

解説

tk_rea_dev() または tk_wri_dev() が呼び出されたときに、処理開始関数 execfn が呼び出される。

devreq の要求の処理を開始する。処理を開始するのみで、完了を待たずに呼出元へ戻る。処理開始のためにかかる時間はデバイスドライバに依存する。必ずしも即座に完了するとは限らない。

新たな要求を受け付けられない状態のときは、要求受付待ちとなる。tmout に指定した時間以内に新たな要求を受け付けられなければ、タイムアウトする。tmout には、TMO_POL または TMO_FEVR を指定することもできる。タイムアウトした場合、execfn の戻値に E_TMOUT を返す。要求パケットの error は変更しない。タイムアウトするのは要求を受け付けるまでで、要求を受け付けた後はタイムアウトしない。

execfn の戻値にエラーを返した場合は、要求が受け付けられなかったものとして、要求パケットは消滅する。

処理を中止する場合、その要求の受け付け前(処理開始前)であれば execfn の戻値に E_ABORT を返す。この場合、要求パケットは消滅する。要求受け付け後(処理開始後)の場合は、E_OK を返す。この場合、要求パケットは waitfn を実行し処理完了が確認されるまで消滅しない。

中止要求があった場合、execfn からできる限り速やかに戻らなければならない。処理を中止しなくてもすぐに終るのであれば中止しなくてもよい。

execfn は、tk_rea_dev, tk_wri_dev, tk_srea_dev, tk_swri_dev の発行タスクの準タスク部として実行される。

デバイス登録時のドライバ属性として TDA_DEV_D が指定されたデバイスドライバにおいて、tk_rea_dev() または tk_wri_dev() が呼び出されたときに、処理開始関数(64ビット要求パケット、ミリ秒タイムアウト) execfn が呼び出される。この場合、パラメータの要求パケットが64ビットのT_DEVREQ_D* devreq_d となった点を除き、関数の仕様は32ビット要求パケット、ミリ秒タイムアウトの execfn と同じである。

デバイス登録時のドライバ属性として TDA_TMO_U が指定されたデバイスドライバにおいて、tk_rea_dev() または tk_wri_dev() が呼び出されたときに、処理開始関数(32ビット要求パケット、マイクロ秒タイムアウト) execfn が呼び出される。この場合、パラメータのタイムアウト指定がマイクロ秒単位のTMO_U tmout_u となった点を除き、関数の仕様は32ビット要求パケット、ミリ秒タイムアウトの execfn と同じである。

デバイス登録時のドライバ属性として TDA_DEV_D および TDA_TMO_U が指定されたデバイスドライバにおいて、tk_rea_dev() または tk_wri_dev() が呼び出されたときに、処理開始関数(64ビット要求パケット、マイクロ秒タイムアウト) execfn が呼び出される。この場合、パラメータの要求パケットが64ビットのT_DEVREQ_D* devreq_d、パラメータのタイムアウト指定がマイクロ秒単位のTMO_U tmout_u となった点を除き、関数の仕様は32ビット要求パケット、ミリ秒タイムアウトの execfn と同じである。

T-Kernel 1.0との差異

処理開始関数(64ビット要求パケット、ミリ秒タイムアウト)、処理開始関数(32ビット要求パケット、マイクロ秒タイムアウト)、処理開始関数(64ビット要求パケット、マイクロ秒タイムアウト)は、T-Kernel 2.0で追加された関数である。

waitfn - 完了待ち関数

C言語インタフェース

/* 完了待ち関数(32ビット要求パケット、ミリ秒タイムアウト) */

INT creqno = waitfn (T_DEVREQ *devreq , INT nreq , TMO tmout , void *exinf );

/* 完了待ち関数(64ビット要求パケット、ミリ秒タイムアウト) */

INT creqno = waitfn (T_DEVREQ_D *devreq_d , INT nreq , TMO tmout , void *exinf );

/* 完了待ち関数(32ビット要求パケット、マイクロ秒タイムアウト) */

INT creqno = waitfn (T_DEVREQ *devreq , INT nreq , TMO_U tmout_u , void *exinf );

/* 完了待ち関数(64ビット要求パケット、マイクロ秒タイムアウト) */

INT creqno = waitfn (T_DEVREQ_D *devreq_d , INT nreq , TMO_U tmout_u , void *exinf );

パラメータ

T_DEVREQ* devreq Device Request Packet要求パケットのリスト(32ビット)
T_DEVREQ_D* devreq_d Device Request Packet要求パケットのリスト(64ビット)
INT nreq Number of Request要求パケットの数
TMO tmout Timeoutタイムアウト時間(ミリ秒)
TMO_U tmout_u Timeoutタイムアウト時間(マイクロ秒)
void* exinf Extended Informationデバイス登録時に指定した拡張情報

リターンパラメータ

INT creqno Completed Request Packet Number完了した要求パケットの番号
またはError Codeエラーコード

エラーコード

その他 デバイスドライバの返すエラーコード

解説

tk_wai_dev() が呼び出されたときに、完了待ち関数 waitfn が呼び出される。

devreqdevreq->next で接続された要求パケットのリストで、devreq から nreq 個分の要求パケットについて、その内のいずれかが完了するのを待つ。リストの最後の next は必ずしも NULL になっているとは限らないため、必ず nreq の指定に従う。戻値に完了した要求パケットの番号(devreq から何番目か)を返す。最初が0番目で最後が nreq-1番目となる。なお、完了とは、正常終了/異常(エラー)終了/中止のいずれかである。

tmout に完了待ちのタイムアウト時間を指定する。TMO_POL または TMO_FEVR を指定することもできる。タイムアウトした場合は、要求された処理は継続中である。タイムアウトの場合、waitfn の戻値に E_TMOUT を返す。要求パケットの error は変更しない。なお、要求された処理を継続中で waitfn から戻るときは、waitfn の戻値に必ずエラーを返す。戻値にエラーを返したにもかかわらず処理が完了していてはいけないし、処理継続中であればエラー以外を返してもいけない。waitfn の戻値にエラーが返されている限り、その要求は処理中として要求パケットは消滅しない。waitfn の戻値に処理を完了した要求パケットの番号が返されたとき、その要求の処理は完了したものとして要求パケットは消滅する。

入出力エラーなどデバイスに関するエラーを、要求パケットの error に格納する。waitfn の戻値には、完了待ちが正しくできなかった場合のエラーを返す。waitfn の戻値が tk_wai_dev の戻値となり、要求パケットの errorioer に戻される。

waitfn による完了待ちの間に中止処理関数 abortfn が実行された時の中止の処理は、単一要求の完了待ちだった場合(waitfnnreq=1)と、複数要求の完了待ちだった場合(waitfnnreq > 1)で異なっている。単一要求の完了待ちだった場合は、処理中の要求を中止する。一方、複数要求の完了待ちだった場合は、特別な扱いとして、waitfn による待ちの解除のみを行い、要求に対する処理自体は中止しない。すなわち、中止処理関数 abortfn が実行されても、要求パケットの abortFALSE のままであり、要求に対する処理は継続する。待ち解除となった waitfn からは、戻値に E_ABORT を返す。

完了待ち要求の中には、中止要求が要求パケットの abort にセットされている場合がある。このような場合、単一要求の完了待ちではその要求の中止処理を行わなければならない。複数要求の完了待ちでも中止処理を行うのが望ましいが、abort フラグを無視しても構わない。

なお、中止処理では waitfn からできる限り速やかに戻ることが重要であり、処理を中止しなくてもすぐに処理が終るのであれば中止しなくてもよい。

処理が中止された場合は、要求パケットの errorE_ABORT を返すことを原則とするが、そのデバイスの特性に合わせて E_ABORT 以外のエラーを返してもよい。また、中止される直前までの処理を有効として E_OK としてもよい。なお、中止要求があっても正常に最後まで処理したのなら E_OK を返す。

waitfn は、tk_wai_dev, tk_srea_dev, tk_swri_dev の発行タスクの準タスク部として実行される。

デバイス登録時のドライバ属性として TDA_DEV_D が指定されたデバイスドライバにおいて、tk_wai_dev() が呼び出されたときに、完了待ち関数(64ビット要求パケット、ミリ秒タイムアウト) waitfn が呼び出される。この場合、パラメータの要求パケットが64ビットのT_DEVREQ_D* devreq_d となった点を除き、関数の仕様は32ビット要求パケット、ミリ秒タイムアウトの waitfn と同じである。

デバイス登録時のドライバ属性として TDA_TMO_U が指定されたデバイスドライバにおいて、tk_wai_dev() が呼び出されたときに、完了待ち関数(32ビット要求パケット、マイクロ秒タイムアウト) waitfn が呼び出される。この場合、パラメータのタイムアウト指定がマイクロ秒単位のTMO_U tmout_u となった点を除き、関数の仕様は32ビット要求パケット、ミリ秒タイムアウトの waitfn と同じである。

デバイス登録時のドライバ属性として TDA_DEV_D および TDA_TMO_U が指定されたデバイスドライバにおいて、tk_wai_dev() が呼び出されたときに、完了待ち関数(64ビット要求パケット、マイクロ秒タイムアウト) waitfn が呼び出される。この場合、パラメータの要求パケットが64ビットのT_DEVREQ_D* devreq_d、パラメータのタイムアウト指定がマイクロ秒単位のTMO_U tmout_u となった点を除き、関数の仕様は32ビット要求パケット、ミリ秒タイムアウトの waitfn と同じである。

T-Kernel 1.0との差異

完了待ち関数(64ビット要求パケット、ミリ秒タイムアウト)、完了待ち関数(32ビット要求パケット、マイクロ秒タイムアウト)、完了待ち関数(64ビット要求パケット、マイクロ秒タイムアウト)は、T-Kernel 2.0で追加された関数である。

abortfn - 中止処理関数

C言語インタフェース

/* 中止処理関数(32ビット要求パケット) */

ER ercd = abortfn (ID tskid , T_DEVREQ *devreq , INT nreq , void *exinf );

/* 中止処理関数(64ビット要求パケット) */

ER ercd = abortfn (ID tskid , T_DEVREQ_D *devreq_d , INT nreq , void *exinf );

パラメータ

ID tskid Task ID execfn, waitfn を実行しているタスクのタスクID
T_DEVREQ* devreq Device Request Packet要求パケットのリスト(32ビット)
T_DEVREQ_D* devreq_d Device Request Packet要求パケットのリスト(64ビット)
INT nreq Number of Request Packets要求パケットの数
void* exinf Extended Informationデバイス登録時に指定した拡張情報

リターンパラメータ

ER ercd Error Codeエラーコード

エラーコード

その他 デバイスドライバの返すエラーコード

解説

現在実行中の処理開始関数 execfn や完了待ち関数 waitfn から速やかに戻らせたいときに、中止処理関数 abortfn が呼び出される。通常は、処理中の要求を中止して戻らせる。ただし、中止しなくてもすぐに処理が終るのであれば、必ずしも中止しなくてもよい。重要なのは、できる限り速やかに execfn, waitfn から戻ることである。

abortfn は、次のような場合に呼び出される。

  • タスク例外の発生によるブレーク関数の実行時に、タスク例外の発生したタスクによる処理中の要求があった場合、そのタスクによる処理中の要求を中止する。

  • tk_cls_dev() およびサブシステムのクリーンアップ処理によるデバイスクローズ時に、クローズするデバイスディスクリプタによる処理中の要求があった場合、そのデバイスディスクリプタによる処理中の要求を中止する。

tskid は、devreq で指定した要求を実行中のタスクである。つまり、execfn, waitfn を実行しているタスクである。devreq, nreq は、execfn, waitfn の引数として指定したものと同じである。ただし、execfn の場合は常に nreq=1である。

abortfn は、execfn, waitfn を実行しているタスクとは別のタスクから呼び出される。両者は並行して実行されるため、必要に応じて排他制御等を行う必要がある。また、execfn, waitfn の呼出直前や execfn, waitfn から戻る途中に abortfn が呼び出される可能性もある。このような場合においても正しく動作するように配慮する必要がある。abortfn を呼び出す前に、中止処理対象の要求パケットの abort フラグに TRUE が設定されるので、execfn, waitfn はこれにより中止要求の有無を知ることもできる。また、abortfn では、任意のオブジェクトに対する tk_dis_wai() を使用することができる。

複数要求待ち(nreq > 1)の waitfn 実行中の場合は、特別な扱いとなり他の場合とは次の点で異なる。

  • 要求の処理を中止することはせず、完了待ちのみ中止(待ちを解除)する。

  • 要求パケットの abort フラグはセットされない(abortFALSE のまま)。

なお、execfn, waitfn の実行中でないときに要求を中止させる場合には、abortfn を呼び出すことなく、要求パケットの abort フラグがセットされる。abort フラグがセットされた状態で execfn が呼び出されたときは、要求を受け付けない。waitfn が呼び出されたときは、abortfn が呼び出された場合と同様の中止処理を行う。

execfn により処理を開始した要求が、waitfn による完了待ちでない状態で中止された場合は、後で waitfn が呼び出されたときに中止されて処理が完了したことを知らせる。処理が中止されても、waitfn により完了が確認されるまでは要求自体は消滅しない。

abortfn は中止処理を開始するのみで、中止が完了するまで待たずに速やかに戻る。

タスク例外の際に実行される abortfn は、タスク例外を発生させた tk_ras_tex の発行タスクの準タスク部として実行される。また、デバイスクローズ時に実行される abortfn は、tk_cls_dev の発行タスクの準タスク部として実行される。クリーンアップ処理によるデバイスクローズの場合は、クリーンアップ関数のコンテキスト、すなわち tk_cln_ssy の発行タスクの準タスク部として実行される。

デバイス登録時のドライバ属性として TDA_DEV_D が指定されたデバイスドライバにおいて、現在実行中の処理開始関数 execfn や完了待ち関数 waitfn から速やかに戻らせたいときに、中止処理関数(64ビット要求パケット) abortfn が呼び出される。この場合、パラメータの要求パケットが64ビットのT_DEVREQ_D* devreq_d となった点を除き、関数の仕様は32ビット要求パケットの abortfn と同じである。

T-Kernel 1.0との差異

中止処理関数(64ビット要求パケット)は、T-Kernel 2.0で追加された関数である。

eventfn - イベント関数

C言語インタフェース

INT retcode = eventfn (INT evttyp , void *evtinf , void *exinf );

パラメータ

INT evttyp Event Typeドライバ要求イベントタイプ
void* evtinf Event Informationイベントタイプ別の情報
void* exinf Extended Informationデバイス登録時に指定した拡張情報

リターンパラメータ

INT retcode Return Codeイベントタイプ別に定義された戻値
またはError Codeエラーコード

エラーコード

その他 デバイスドライバの返すエラーコード

解説

アプリケーションインタフェースによる通常のデバイス入出力処理とは別の要因によって、デバイスやシステムの状態変化が発生し、それに対してデバイスドライバ側で何らかの処理を要する場合に、ドライバ要求イベントが発生し、イベント関数 eventfn が呼び出される。

ドライバ要求イベントは、電源管理のためのサスペンド/リジューム時(tk_sus_dev 参照)や、USBやPCカードのような活性挿抜可能な機器の接続時に発生する。

たとえば、tk_sus_dev によってシステムがサスペンドする時には、T-Kernelの内部で(tk_sus_dev の処理の中で)、サスペンドのドライバ要求イベント(TDV_SUSPEND)を発生し、evttypTDV_SUSPEND として各デバイスのイベント関数を呼び出す。各デバイスのイベント関数の中では、この呼出に応じて、サスペンド時に必要な状態保存などの処理を行う。

ドライバ要求イベントタイプには下記のものがある。

#define TDV_SUSPEND   (-1)   /* サスペンド */
#define TDV_RESUME    (-2)   /* リジューム */
#define TDV_CARDEVT     1    /* PCカードイベント */
#define TDV_USBEVT      2    /* USBイベント */

上記の値が負のドライバ要求イベントは、サスペンド/リジューム時の処理など、T-Kernel/SMのデバイス管理内部からの呼出によるものである。

一方、上記の値が正のドライバ要求イベント(TDV_CARDEVT, TDV_USBEVT)は、tk_evt_dev() の呼出によって発生するものであり、T-Kernelの動作とは直接関係しない参考仕様である。これらのドライバ要求イベントは、USBやPCカードなどのバスドライバを実装するために、必要に応じて利用する。

イベント関数で行う処理は、イベントタイプごとに定義される。サスペンド/リジュームについては「各デバイスのサスペンド/リジューム処理」を参照。

tk_evt_dev() による呼出の場合、eventfn の戻値はそのまま tk_evt_dev() の戻値となる。

イベント関数への要求は、他の要求の処理中であっても受け付け、できる限り速やかに処理しなければならない。

eventfn は、イベント発生の原因となった tk_evt_devtk_sus_dev の発行タスクの準タスク部として実行される。

補足事項

PCカードイベントやUSBイベントで想定している動作は以下のとおりである。

ただし、以下の説明はPCカードやUSBの機器を扱うデバイスドライバの実装例の説明であり、T-Kernelの仕様の範囲には含まれない。

USB機器の接続時には、そのUSB機器に対して、実際の入出力処理を行うクラスドライバを動的に対応付ける必要がある。

たとえば、USBメモリなどのストレージを接続した場合には、マスストレージクラス用のデバイスドライバがその機器の入出力処理を行うが、USBカメラを接続した場合には、ビデオクラス用のデバイスドライバがその機器の入出力処理を行う。どのデバイスドライバを使うべきかは、USB機器が接続されるまで分からない。

この時、USB機器とクラスドライバとの対応付けの処理を行うための手段として、USB接続のドライバ要求イベントと、各デバイスドライバのイベント関数を利用する。具体的には、USBポートを監視していたUSBバスドライバ(USBマネージャ)が、新しいUSB機器の接続を検出した場合に、クラスドライバの候補となる各デバイスドライバに対して、USB接続のドライバ要求イベント(TDV_USBEVT)を送り、各デバイスのイベント関数を呼び出す。

各デバイスのイベント関数では、この TDV_USBEVT に応答する形で、新しく接続されたUSB機器への対応の可否を返す。USBバスドライバでは、その戻値を見て、実際のクラスドライバとの対応付けを決定する。

PCカードの接続時の処理も、同様の手順になる。

デバイス事象通知

デバイスドライバは、各デバイスで発生した事象を、デバイス事象通知のメッセージとして特定のメッセージバッファ(事象通知用メッセージバッファ)へ送信する。事象通知用メッセージバッファのIDは、各デバイスに対する TDN_EVENT の属性データとして参照あるいは設定される。

デバイス登録の直後には、システムデフォルトの事象通知用メッセージバッファを使用する。デバイスドライバの起動時には、tk_def_dev によってデバイスの登録を行うが、このAPIのリターンパラメータとしてシステムデフォルトの事象通知用メッセージバッファのID値が返されるので、デバイスドライバではその値を保持し、属性データ TDN_EVENT の初期値とする。

なお、システムデフォルトの事象通知用メッセージバッファは、システム起動時に生成され、そのサイズとメッセージ最大長は、システム構成情報の TDEvtMbfSz により定義される。

デバイス事象通知で使用するメッセージの形式は以下のようになる。事象通知のメッセージの内容やサイズは、事象タイプごとに異なる。

◇デバイス事象通知の基本形式
typedef struct t_devevt {
        TDEvtTyp        evttyp;         /* 事象タイプ */
        /* 以下に事象タイプ別の情報が付加される */
} T_DEVEVT;
◇デバイスID付きのデバイス事象通知の形式
typedef struct t_devevt_id {
        TDEvtTyp        evttyp;         /* 事象タイプ */
        ID              devid;          /* デバイスID */
        /* 以下に事象タイプ別の情報が付加される */
} T_DEVEVT_ID;
◇拡張情報付きのデバイス事象通知の形式
typedef struct t_devevt_ex {
        TDEvtTyp        evttyp;         /* 事象タイプ */
        ID              devid;          /* デバイスID */
        UB              exdat[16];      /* 拡張情報 */
        /* 以下に事象タイプ別の情報が付加される */
} T_DEVEVT_EX;

デバイス事象通知の事象タイプは、以下のように大分類される。

  1. 基本事象通知(事象タイプ 0x0001~0x002F)

    デバイスからの基本的な事象の通知

  2. システム事象通知(事象タイプ 0x0030~0x007F)

    電源制御などシステム全体に関係する事象の通知

  3. 拡張情報付き事象通知(事象タイプ 0x0080~0x00FF)

    拡張情報を持つデバイスからの事象の通知

  4. ユーザ定義事象通知(事象タイプ 0x0100~0xFFFF)

    ユーザが内容を任意に定義可能な事象の通知

事象タイプのうち、代表的なものは以下の通りである。各事象の詳細や、これ以外の事象タイプについては、デバイスドライバ関連の仕様書、あるいは「参考とすべきデバイスドライバ関連の仕様付録」の「デバイス事象通知用の事象タイプ付録」を参照のこと。

typedef enum tdevttyp {
        TDE_unknown     = 0,            /* 未定義 */
        TDE_MOUNT       = 0x01,         /* メディア挿入 */
        TDE_EJECT       = 0x02,         /* メディア排出 */
        TDE_POWEROFF    = 0x31,         /* 電源スイッチオフ */
        TDE_POWERLOW    = 0x32,         /* 電源残量警告 */
        TDE_POWERFAIL   = 0x33,         /* 電源異常 */
        TDE_POWERSUS    = 0x34          /* 自動サスペンド */
} TDEvtTyp;

事象通知用メッセージバッファが一杯で事象通知を送信できない場合は、その事象が通知されないことで事象通知の受信側の動作に悪影響が出ないようにしなければならない。メッセージバッファが空くまで待ってから事象通知を行ってもよいが、その場合も原則として事象通知以外のデバイスドライバの処理が滞ってはならない。なお、事象通知の受信側は、できる限りメッセージバッファが溢れることがないように処理しなければならない。

注意T-Kernel 1.0との差異
 

デバイス事象通知で使用するメッセージの形式および事象タイプの説明を整理した。

各デバイスのサスペンド/リジューム処理

イベント関数(eventfn)へのサスペンド/リジューム(TDV_SUSPEND/TDV_RESUME)イベントの発行により、各デバイスドライバはデバイスのサスペンド/リジューム処理を行う。サスペンド/リジュームイベントは、物理デバイスに対してのみ発行される。

TDV_SUSPEND

サスペンド

evttyp = TDV_SUSPEND
evtinf = NULL (なし)

次のような手順でサスペンド処理を行う。

  1. 現在処理中の要求があれば、完了するまで待つか、中断または中止する。どの方法を選択するかはデバイスドライバの実装に依存する。ただし、できるだけ速やかにサスペンドする必要があるため、完了までに時間がかかる場合は中断または中止としなければならない。

    サスペンドイベントは物理デバイスに対してのみ発行されるが、そのデバイスに含まれるすべての論理デバイスに対しても、同様に処理する。

    中断:処理を一時的に中断し、リジューム後に続きを行う。
    中止:中止処理関数(abortfn)による中止と同様に、処理を中止する。リジューム後も再開されない。

  2. リジュームイベント以外の新たな要求を受け付けないようにする。

  3. デバイスの電源を切るなどのサスペンド処理を行う。

中止はアプリケーションへの影響が大きいと考えられるため極力避けたい。シリアル回線からの長期の入力待ちなどで、かつ中断とするのが難しい場合以外は中止としない。通常は、終了まで待つか、可能であれば中断とする。

サスペンド期間中にデバイスドライバへ来た要求は、リジュームまで待たせてリジューム後に受け付け処理する。ただし、デバイスへのアクセスを伴わない処理など、サスペンド中でも可能な処理は受け付けてもよい。

TDV_RESUME

リジューム

evttyp = TDV_RESUME
evtinf = NULL (なし)

次のような手順でリジューム処理を行う。

  1. デバイスの電源を入れデバイスの状態を復帰させるなどのリジューム処理を行う。

  2. 中断していた処理があれば再開する。

  3. 要求受け付けを再開する。

ディスクデバイスの特殊性

仮想記憶システムにおいて、ディスクデバイスは特別なものとなる。仮想記憶を行うにあたり、メモリとディスク間でのデータ転送を行うため、OS(具体的には、T-Kernel Extensionなどの中で仮想記憶の処理を行う部分)がディスクドライバを呼び出す必要がある。

OSがディスクとのデータ転送を行う必要があるのは、非常駐メモリにアクセスされたことにより、そのメモリの内容をディスクから読み出す(ページイン)ような場合である。このような場合に、OSはディスクドライバを呼び出す。

もし、ディスクドライバ内で非常駐メモリにアクセスした場合、OSはやはりディスクドライバを呼び出さなければならなくなる。このようなケースでは、非常駐メモリにアクセスしたことでページイン待ちとされているディスクドライバに対して、OSが再びディスクアクセスの要求を出す可能性がある。このような場合でも、ディスクドライバは後から来たOSからの要求を実行できなければならない。

同じ様なことが、サスペンド処理時にも起きる可能性がある。サスペンド処理中に非常駐メモリがアクセスされ、ディスクドライバが呼び出されたとき、そのディスクドライバがすでにサスペンドされているとページインができないことになる。このようなケースを避けるため、サスペンド時にはディスクデバイス以外を先にサスペンドした後、ディスクデバイスをサスペンドする。しかし、複数のディスクデバイスがあれば、そのディスクデバイスのサスペンド順序は不定である。したがって、ディスクドライバでは、サスペンド処理中に非常駐メモリにアクセスしてはならない。

このような制限から、ディスクドライバでは非常駐メモリを使用しない(アクセスしない)ようにしなければならない。ただし、tk_rea_dev(), tk_wri_dev() で指定される入出力バッファ(buf)に関しては、呼出側で指定したメモリ領域であるため非常駐メモリである可能性がある。そのため、入出力バッファに関しては、入出力を行う間は常駐化(LockSpace 参照)しておくなどの対応が必要である。