デバイスドライバは、 中心核 ( ITRON ) 上で独立したタスクとして動作し、 デバイスに対して以下の基本操作を要求に応じて行う。
OPEN | デバイスの使用開始 |
CLOSE | デバイスの使用終了 |
CLOSEALL | デバイスの使用終了、メディアのイジェクト |
READ | データの読み込み |
WRITE | データの書き込み |
ABORT | 現在の処理のアボート |
SUSPEND | サスペンド状態へ移行 |
RESUME | リジューム(サスペンド状態から復帰) |
CARDEVENT | PCMCIA カードの事象 |
USBEVENT | USB デバイスの事象 |
ABORT
、SUSPEND
、CARDEVENT
、USBEVENT
要求は、
他の処理の途中であっても任意の時点で受け付けなくてはいけない。
また、デバイス毎に決められた事象の発生を検出し、事象通知を行う。
ドライバが取り扱うデータはデータ番号により指定され、 以下の 2 種類に大別される。
デバイスドライバは、BTRON のプロセス / タスクではなく、 ITRON のタスクとして動作する。 したがって、ランデブなどの同期・通信機能も、 ITRON のシステムコールを使用する。
デバイスドライバーの基本構造および基本的な処理方法を示す。 ここに記述されている方法に囚われる必要はない。 デバイスドライバーの内部構造および処理方法は、 対象のハードウエアにより様々である。 デバイス管理など外部とのインターフェースが 仕様に則っていれば内部は自由である。
cal_por
での calptn
を変えているため、
同一のランデブポートから特定の要求のみを選択的に受け付けることができる。
システム初期化 ( デバイスドライバー起動処理 ) 時にタスクとして起動される。 タスク起動パラメータとしてデバイスに固有のパラメータが渡される。
ドライバ初期化時に、必要に応じて生成 / 起動される。
指定された事象通知用メッセージバッファに対して、 事象の発生を通知する。事象はデバイス毎に規定され、 メッセージバッファが指定されている場合は、 すべての事象をそのバッファに通知する。
必要であれば、事象の検出用の別タスクを生成 / 起動する。
定周期に事象の発生をチェックする必要がある場合は、
周期起動ハンドラを使用しても良いが、
事象発生のチェック処理に時間がかかる場合は、
周期起動ハンドラからタスクを起動するようにする。
また、周期に厳密さがあまり必要でない場合は、
周期起動ハンドラを使用せずに、dly_tsk
などを使用してもよい。
デバイスドライバーには、 カーネル組み込み形式とカーネルにリンクしない追加組み込み形式がある。 カーネル組み込み形式は、 デバイスドライバーとカーネル ( OS 核 ) をリンクする形式であり、 カーネルをコンパイルできる環境が必要となる。 したがって、一般には追加組み込み形式を使用する。
カーネル組み込み形式の場合 main()
関数はなく、
初期起動タスクがエントリーとなる。
void XxxxxDriver( DevDrvParam *drvpar )
typedef struct { ID mbfid; /* デフォールトの事象通知用MBF ID */ VP info; /* デバイス固有情報へのポインタ */ } DevDrvParam; drvpar デバイスドライバー起動パラメータ
次の形式の main() 関数が、ドライバーのエントリーとなる。
ERR main( Bool StartUp, TC *arg )
StartUp True : 初期化 False : 終了 終了は、要求されることがない。 もし終了要求が来ても、ER_NOSPT を返すだけでよい。 arg パラメータ
IMS から次のように起動する。
[IMS]% kerext driver parameter
この parameter
の文字列の先頭が arg
に渡される。
parameter
は空白も含まれる 1 つの文字列である。
main()
関数は、デバイスドライバー起動パラメータ
( DevDrvParam
) を準備し、
デバイスドライバー本体のタスク ( 初期起動タスク ) を起動して
return
する。
return
しないと IMS に制御が戻らない。
main()
関数から return
しない限り次のデバイスドライバーの起動は行われない。
デバイスドライバーの起動順序に依存性がある場合は、
return
する前に必要な初期化処理をすべて終わらせておくことで起動順序が守られる。
デバイスは、論理デバイス名により識別される。
論理デバイス名は、一般的に種別、ユニット、 サブユニットを示すフィールドから構成されるが、 ユニット、サブユニットが存在しない場合は、 それぞれのフィールドは存在しない。
種別 | デバイスの種別を示す名前 |
ユニット | 物理的なデバイスを示す "a" 〜 の 1 文字 |
サブユニット | 論理的なデバイスを示す "0" 〜 の数字 |
デバイス名には、以下の様なものがある ( 文字コードは TRON コード )
hd* | ハードディスク(ユニット) |
hd*# | ハードディスク(パーティション) |
fd* | フロッピーディスク |
rs* | RS-232C |
kbpd | キーボード / ポインティングデバイス |
デバイスドライバは初期起動時に自分でサポートするデバイスを上位のデバイス管理に対してユニット毎に登録する。 登録時にデバイスを指定するデバイス ID が戻される。
デバイスの登録は、以下の関数で行う。関数値はデバイス ID。
ID DefDevice(DevDef *devdef, DiskInfo *info) /* デバイス属性 */ typedef struct { UW devinfo:8; /* デバイス詳細情報 */ UW devkind:8; /* デバイス/メディア種別 */ UW reserved:10; /* 予約(0) */ UW openreq:1; /* 毎回オープン/クローズが必要 */ UW lockreq:1; /* アドレス空間のロックが必要 */ UW diskinfo:1; /* DN_DISKINFO のサポート有無 */ UW chardev:1; /* 文字型デバイス */ UW nowait:1; /* NOWAITモードの適用の有無 */ UW eject:1; /* イジェクトの可否 */ } DevAttr;
devinfo :
devkind :
#define DK_UNDEF 0x00 /* 未定義/不明 */ #define DK_DISK 0x10 /* ディスクタイプ */ #define DK_DISK_UNDEF 0x10 /* その他のディスク */ #define DK_DISK_RAM 0x11 /* RAM ディスク */ #define DK_DISK_ROM 0x12 /* ROM ディスク */ #define DK_DISK_FLA 0x13 /* FLASH ROM / SS ディスク*/ #define DK_DISK_FD 0x14 /* フロッピーディスク */ #define DK_DISK_HD 0x15 /* ハードディスク */ #define DK_DISK_CDROM 0x16 /* CD-ROM */
openreq :
lockreq :
diskinfo :
DN_DISKINO
をサポートしている場合は 1、そうでないときは 0
ディスクドライバ以外は未サポートとする。
1 とした場合は、
info
にディスク情報を設定する。0 の場合には info
は NULL
とする
( DiskInfo
の詳細は後述 ) 。
chardev :
nowait :
eject :
/* デバイス登録 */ #define L_DEVNM 8 /* デバイス名の長さ */ typedef struct { DevAttr attr; /* デバイス属性 */ W subunits: /* サブユニット数 */ TC name[L_DEVNM]; /* 登録するデバイス名 */ ID portid; /* 受け付け用ランデブポートID */ } DevDef;
attr :
subunits :
name[] :
hda
、fda
など。
portid :
サブユニット数、登録されるデバイス名、 デバイス ID の関連は以下の通り。
サブユニット数 | 登録されるデバイス名 | デバイスID |
---|---|---|
0 | xxx | ID |
1 | xxx | ID |
xxx0 | ID+1 | |
N | xxx | ID |
xxx0 | ID+1 | |
: : | ||
xxx(N-1) | ID+N |
xxx
は name[]
で指定したデバイス(ユニット)名。
xxx
はユニット全体
( 物理デバイス ) を意味する。
デバイス処理要求はランデブによりドライバに渡され、 ドライバは処理を行った後ランデブ応答を戻す。
/* コマンド種別 */ typedef enum { DC_OPEN = 1, DC_CLOSE = 2, DC_CLOSEALL = 3, DC_READ = 4, DC_WRITE = 5, DC_ABORT = 6, DC_SUSPEND = 7, DC_RESUME = 8, DC_CARDEVENT = 9, DC_USBEVENT = 10 } DevCmdKind; #define D_CALPTN(devcmd) ( 1 << (devcmd) ) /* 通常要求の calptn */ #define D_NORM_PTN ( D_CALPTN(DC_OPEN) \ |D_CALPTN(DC_CLOSE) \ |D_CALPTN(DC_CLOSEALL) \ |D_CALPTN(DC_READ) \ |D_CALPTN(DC_WRITE) ) /* 例外要求の calptn */ #define D_ABORT_PTN ( D_CALPTN(DC_ABORT) \ |D_CALPTN(DC_SUSPEND) \ |D_CALPTN(DC_RESUME) \ |D_CALPTN(DC_CARDEVENT) \ |D_CALPTN(DC_USBEVENT) )
cal_por
の calptn
を指定する。
/* デバイス要求コマンド */ typdef struct { UW nowait:1; /* NOWAIT モード */ UW rsv0:14; /* 予約(0) */ UW adcnv:1; /* アドレス変換モード */ DevCmdKind cmd:16; /* コマンド */ } DevCmd; /* デバイス処理要求メッセージ */ typedef struct { ID devid; /* 対象のデバイスID */ DevCmd cmd; /* 要求コマンド */ W datano; /* データ番号 */ W datacnt; /* データ数 */ ID taskid; /* 要求したタスクID */ VP memptr; /* メモリーポインタ */ } DevReq; /* デバイス処理応答メッセージ */ typedef struct { ID devid; /* 対象のデバイスID */ DevCmd cmd; /* 要求コマンド */ W datano; /* データ番号 */ W datacnt; /* データ数 */ ErrCode error; /* エラーコード */ } DevRsp;
cmd.nowait :
NOWAIT
モード指定NOWAIT
モードをサポートしていない場合は無視する。
cmd.adcnv :
cmd.cmd :
DC_OPEN :
openreq = 0
の時は、
最初の 1 回のみ発行される。
openreq = 1
の時は、毎回発行される。taskid
にはオープンしたタスク ID、
datano
にはオープンしたタスクが属するプロセス ID が入る
( タスク ID、プロセス ID が不明 / 未定義の時は、それぞれ 0 が入る ) 。datacnt
、memptr
は未使用。
DC_CLOSE :
openreq = 0
の時は、
最後の 1 回のみ発行される。
openreq = 1
の時は、毎回発行される。taskid
にはクローズしたタスク ID、
datano
にはクローズしたタスクが属するプロセス IDが入る
( タスク ID、プロセス ID が不明 / 未定義の時は、それぞれ 0 が入る)。datacnt
、memptr
は未使用。
DC_CLOSEALL :
DC_CLOSE
の処理の後、メディアをイジェクトする。
イジェクト不能デバイスの時は、DC_CLOSE
と同じ。
DC_OPEN
、DC_CLOSE
、DC_CLOSEALL
はデバイスの使用開始・終了を明示的に示すためのものであり、
対象デバイスの特性上特に処理すべきことがなければ何もしなくてもよい。
また、オープンされていない状態での
DC_READ
、DC_WRITE
等の要求は、
デバイスの動作上特に問題が無ければエラーとする必要はない
( オープンされているか否かをエラーのためだけにチェックする必要はない ) 。
DC_READ :
datano
のデータを datacnt
だけ、
taskid
のタスクの memptr
の領域に読み込む。
DC_WRITE :
taskid
のタスクの memptr
の領域のデータを、
datacnt
だけ、datano
に書き込む。
DC_ABORT :
taskid
のタスクから要求された処理を処理中の場合は、
その処理を即時に中止し、
その要求はエラー応答を戻す。
そうでない場合は何もしない。datano
、datacnt
、memptr
は未使用。
DC_SUSPEND :
taskid
、datano
、
datacnt
、memptr
は未使用。
処理の詳細は後述。
DC_RESUME :
taskid
、datano
、datacnt
、memptr
は未使用。
処理の詳細は後述。
DC_SUSPEND
および DC_RESUME
は、
デバイスユニットに対し要求される。
サブユニットに対しては要求されない。
DC_CARDEVENT :
DC_USBEVENT :
datano :
datacnt :
datano
< 0 デバイス属性データ
datacnt
の単位はバイト数で、
原則的にデータ全体を一括しての読み込み / 書き込みのみ可能である。
datacnt = 0
datacnt
にデータ長を戻す。
datacnt < データ長
datacnt >= データ長
datacnt
にデータ長を戻す。
datano >= 0
デバイス固有データ
datacnt
の単位はデバイスに依存する。
datacnt = 0
datacnt
に有効 ( 読み書き可能 ) なデータ長を戻す。
datacnt < 0
datacnt > 0
datacnt
に実際に読み込み / 書き込みを行ったデータ長を戻す。
taskid :
memptr :
cmd.adcnv = 0 の時
memptr
で示されるメモリーは常に直接アクセス可能であり、
論理空間の切り換えおよび不正アドレスのチェックは不要である。
cmd.adcnv = 1 の時
datacnt = 0
の場合は、memptr
の正当性はチェックしない。
error :
error | = 0 ( ER_OK ) |
正常 | |
< 0 | |
エラー ( 詳細は別途デバイスごとに定義される ) |
ER_MINTR
を返すが、
そのデバイスの特性に合わせて他のエラーコードを返してもよい。
RS-232C などでは、
データの取りこぼしが起きないような配慮が必要である。
DC_SUSPEND
)次の処理を行う。
DC_SUSPEND
コマンド自身は、
デバイスユニットに対して要求されるが、
現在処理中の要求がサブユニットに対するものでも同様に処理する。
DC_ABORT
要求と同様に、処理中の要求を中止してしまう。
この時、エラーコードは原則として ER_MINTR
とし、
アプリケーションから見たときメッセージハンドラの起動による中止と等価に見えるようにする。
なお、エラーコードについては、
そのデバイスの特性に合わせて他のエラーコードを返してもよい。
DC_RESUME
以外の新たな要求の受け付けを停止する。DC_RESUME
以外の要求は受け付けを停止するが、
ハードウエアへのアクセスを伴わない処理など、
サスペンド期間中でも処理可能な要求は受け付けてもよい。
ドライバーのインプリメント依存とする。
DC_RESUME
)次の処理を行う。
DC_SUSPEND
要求は、DC_ABORT
要求と同様に他の通常要求の処理中であっても、
任意の時点で受け付けられなければならない。
DC_RESUME
要求は、サスペンド状態の期間中だけ受け付ければよい。
それ以外のときは無視する。
DC_CARDEVENT
に関しては、第2章 PC (PCMCIA) カードマネージャ仕様を参照のこと。
DC_USBEVENT
に関しては、第15章 USB マネージャ仕様を参照のこと。
デバイス属性データは、
基本的には個々のデバイスによって異なるが、
下記の属性についてはデータ番号を共通化する。
しかし、すべてのデバイスで下記の属性データが存在するとは限らない。
存在しない属性データに対するアクセスは ER_PAR
とする。
/* 共通デバイス属性データ番号 */ typedef enum { DN_EVENT = -1, /* 事象通知用メッセージバッファ ID */ DN_DISKINFO = -2, /* ディスク情報 */ DN_DISPSPEC = -3, /* 表示デバイス仕様 */ DN_PCMCIAINFO = -4, /* PC カード情報 */ /* -99 まで拡張用予備としてリザーブ */ } CommonDataNo;
-1 〜 -99 までを共通属性データ番号とする。 各デバイス別の属性データ番号には -100 以降を利用する。
DN_EVENT :
DN_DISKINFO :
typedef struct { DiskFormat format; /* フォーマット形式 */ Bool protect:1; /* プロテクト状態 */ Bool removable:1; /* 取り外し可否 */ UW rsv:30; /* 予約 (0) */ W blocksize; /* ブロックバイト数 */ W blockcont; /* 総ブロック数 */ } DiskInfo;
protect :
removable :
typedef enum { DiskFmt_MEMINIT = -2, /* メモリーディスク初期化 */ DiskFmt_MEM = -1, /* メモリーディスク */ DiskFmt_STD = 0, /* 標準 (HD等) */ DiskFmt_2DD = 1, /* 2DD 720KB */ DiskFmt_2HD = 2, /* 2HD 1.44MB */ DiskFmt_VHD = 3 /* フロプチカル 20MB */ DiskFmt_CDROM = 4, /* CD-ROM 640MB */ DiskFmt_2HD12 = 0x12 /* 2HD 1.2MB */ } DiskFormat;
フロッピーディスクの様に1台のドライブで複数種類のメディア
( フォーマット形式 ) を使用する様な場合を除き、
フォーマット形式は標準 ( DiskFmt_STD
) を使用する。
メモリーディスク ( DiskFmt_MEM
) は、
RAM Disk の様にメモリーとしてアクセスできる場合に使用する。
DN_DISPSPEC :
typedef struct { H attr; /* デバイス属性 */ H planes; /* プレーン数 */ H pixbits; /* ピクセルビット数 */ H hpixels; /* 横のピクセル数 */ H vpixels; /* 縦のピクセル数 */ H hres; /* 横の解像度 */ H vres; /* 縦の解像度 */ H color[4]; /* カラー情報 */ H resv[6]; } DEV_SPEC;
DP の DEV_SPEC
の仕様に準ずる
( BTRON3 仕様書「第2編 OS 仕様」-「2.3 基本関数」の gget_spc()
参照)。
この属性データがサポートされているデバイスは、
表示 ( 印刷 ) デバイスである。
したがって、DP は gopn_dev
でデバイス描画環境を生成する時、
このデータを読み出すことができれば、
描画環境を生成可能なデバイスと判定することができる。
DN_PCMCIAINFO :
typedef struct { UB major; /* 仕様バージョン(上位) */ UB minor; /* 仕様バージョン(下位) */ UB info[40]; /* 製品情報 */ } PCMCIAInfo;
現在挿入されている PC カードから、 カード属性情報の製品情報を読み出す。
PC カードが挿入されていない場合には、エラー ( ER_NOMDA
) となる。
デバイスが PC カードでない場合にはこの情報は読み出せず、
エラー ( ER_PAR
) となる。
事象通知用属性データ ( DN_EVENT
) にメッセージバッファ ID ( ≠0 )
が書き込まれると、
それ以降に発生した事象をメッセージバッファに送信する。
0 が書き込まれると、それ以降の事象通知は行わない。
ドライバの初期化の時点では、
デバイスドライバー起動パラメータ ( DevDrvParam
)
で指定されたメッセージバッファ ID がデフォルトとして設定される。
/* 事象種別 */ typedef enum { DE_unknown = 0, /* 未定義 */ DE_MOUNT = 0x01, /* メディア挿入 */ DE_EJECT = 0x02, /* メディア排出 */ DE_ILLMOUNT = 0x03, /* メディア不正挿入 */ DE_ILLEJECT = 0x04, /* メディア不正排出 */ DE_REMOUNT = 0x05, /* メディア再挿入 */ DE_CARDBATLOW = 0x06, /* カードバッテリ残量警告 */ DE_CARDBATFAIL = 0x07, /* カードバッテリ異常 */ DE_REQEJECT = 0x08, /* メディア排出要求 */ DE_PDBUT = 0x11, /* PDボタン変化 */ DE_PDMOVE = 0x12, /* PD位置移動 */ DE_PDSTATE = 0x13, /* PDの状態変化 */ DE_PDEXT = 0x14, /* PD拡張事象 */ DE_KEYDOWN = 0x21, /* キーダウン */ DE_KEYUP = 0x22, /* キーアップ */ DE_KEYMETA = 0x23, /* メタキー状態の変化 */ DE_POWEROFF = 0x31, /* 電源スイッチオフ */ DE_POWERLOW = 0x32, /* 電源残量警告 */ DE_POWERFAIL = 0x33, /* 電源異常 */ DE_POWERSUS = 0x34, /* 自動サスペンド */ DE_POWERUPTM = 0x35, /* 時計更新 */ DE_CKPWON = 0x41 /* 自動電源 ON 通知 */ } DevEvtKind; #define L_VD 0 typedef struct { DevEvtKind kind; /* 事象種別 */ /* VW info[L_VD]; 付加情報 */ } DevEvt;
kind :
info :
各事象の詳細は、対象のデバイスドライバー仕様を参照のこと。
メッセージバッファが一杯で事象通知を行えない場合は、 その事象が通知されないことで 事象の受信側の動作に悪影響が出ないようにしなければならない。 メッセージバッファが空くまで待ってから事象通知を行ってもよい。 その場合も原則として、 事象通知以外のデバイスドライバーの処理が滞ってはいけない。
デバイスドライバーでは、 ITRON システムコールといくつかのライブラリ関数を使用することができる。 デバイスドライバーでは、 原則として BTRON システムコールは使用できない。
下記を除く μITRON 3.0 システムコールが使用できる。
cre_mpl, vcre_mpl, del_mpl, get_blk, pget_blk, tget_blk, rel_blk,ref_mpl
cre_mpf, vcre_mpf, del_mpf, get_blf, pget_blf, tget_blf, rel_blf, ref_mpf
def_svc
ITRON の資源を獲得する場合は、 オブジェクトID やハンドラ番号の自動割り当て機能を使用する。 デバイスドライバーで固定のオブジェクトID やハンドラ番号を使用してはいけない。
次のような資源の自動割り当て機能があるので、これらを使用する。
vcre_tsk, vcre_sem, vcre_flg, vcre_mbx, vcre_mbf, vcre_por, vdef_cyc, vdef_alm
ITRON の詳細については、ITRON の仕様書を参照のこと
ID DefDevice(DevDef *devdef, DiskInfo *info)
*devdef
で指定したデバイスをシステムに登録し、
登録したデバイス ID を関数値として戻す。
devdef->attr.diskinfo = 1
の場合
info
にディスク情報を設定する。
devdef->attr.diskinfo = 0
の場合
info
は NULL
とする。
ERR SetTaskSpace(ID taskid)
taskid
で指定したタスクのアドレス空間、
およびアクセス権情報が自タスクに設定される。
これにより、taskid
のタスクと同じメモリーがアクセスできるようになり、
また、taskid
のタスクにアクセス権がないメモリーへのアクセスを不正アドレスのチェック
( CheckSpaceXX
)
により検出することができるようになる。
要求コマンドの cmd.adcnv = 1
の時は、memptr
で指定されたアドレスに対する不正アドレスのチェック、
およびメモリーアクセスの前に、
必ずアドレス空間を切り換えなくてはいけない。
taskid
に自タスクのタスク ID を指定することはできない。
ただし、TSK_SELF
により自タスクを指定した場合は、
自タスクが本来持つアクセス権 ( タスク生成直後のアクセス権 )
情報が設定される。このとき、アドレス空間は切り替わらない。
ER_INNER
: ITRON エラーコード )
ERR CheckSpaceR(VP address, W len) R チェック ERR CheckSpaceRW(VP address, W len) RW チェック ERR CheckSpaceRE(VP address, W len) RE チェック
指定した address
から len
バイトのメモリー領域に対するアクセスが正当かどうかチェックする。
自タスクの現在のアクセス権情報でアクセスが許可されていない領域が含まれていれば、
エラー ( ER_ADR
) を返す。
メモリーのアクセス権情報は次のように設定される。
SetTaskSpace()
を行うと、
その時点の対象タスクのアクセス権が自タスクに複写される。
要求コマンドの cmd.adcnv = 1
の時は、
memptr
で指定されたアドレスに対してアクセスする前に、
SetTaskSpace()
を行い、
不正アドレスのチェックを行わなくてはならない。
ER_ADR
)
WERR CheckStrSpaceR(TC *str, W max) R チェック WERR CheckStrSpaceRW(TC *str, W max) RW チェック
str
から TNULL
に達するか max
文字目に達するまでのメモリー領域に対するアクセスが正当かチェックする。
ただし max = 0
の場合は、文字数 ( max
) は無視する。
正当ならその文字数、または max
の値
( max != 0
で max
文字目に達するまでに TNULL
がない場合 ) を返し、
不当ならエラー ( ER_ADR
) を返す。
str
は偶数アドレスでなければならない。
ER_ADR
)
WERR CheckBStrSpaceR(UB *str, W max) R チェック WERR CheckBStrSpaceRW(UB *str, W max) RW チェック
str
から '\0' に達するか max
バイト目に達するまでのメモリー領域に対するアクセスが正当かチェックする。
ただし max = 0
の場合は、バイト数 ( max
) は無視する。
正当ならそのバイト数、または max
の値
( max != 0
で max
バイト目に達するまでに '\0' がない場合 )
を返し、不当ならエラー ( ER_ADR
) を返す。
ERR LockSpace(VP address, W len, ID taskid)
taskid
で指定したタスクのアドレス空間上の address
から
len
バイトのメモリー領域をロック ( 常駐化 ) する。
使用が終わったら、
必ず UnlockSapce()
によりアンロック ( 常駐化解除 ) しなければならない。
ERR UnlockSpace(VP address, W len, ID taskid)
LockSpace()
でロック ( 常駐化 ) したメモリー領域をアンロック ( 常駐化解除 ) する。
WERR CnvPhysicalAddr(VP addr, W len, VP *physical_addr)
指定した address
から len
バイトのメモリー領域の物理アドレスを求め、
*physical_address
に戻し、
物理アドレスの連続バイト長さを関数値に戻す。
連続した論理アドレスであっても物理アドレスは連続しているとは限らない。
関数値 < len
の場合は、
物理アドレス上では len バイトの領域が連続していないことを意味するため、
DMA アクセスを行う場合は分割して操作する必要がある。
指定したアドレスはロック ( 常駐化 ) されていなければいけない。
len
)
ERR CreateLock(FastLock *lock) void DeleteLock(FastLock *lock) void Lock(FastLock *lock) void Unlock(FastLock *lock)
排他制御を行うための高速ロック。
内部で ITRON のセマフォを使用しているが、 ITRON のセマフォを直接使用するより高速である。
CreateLock()
によりロックを生成し、
Lock()
、Unlock()
により排他制御を行う。
/* 高速セマフォ */ typedef struct { W cnt; ID semid; } FastLock;
ER_INNER
: ITRON エラーコード)
void WaitUsec(UW usec)
usec
μ秒待つ。待ち時間はあまり正確ではない。
この待ちは、ITRON の待ち ( WAIT
) 状態ではない。
積極的に他のタスクへ CPU を明け渡すようなことはしない。
したがって、長時間の待ちに使用すべきではない。
I/O ポートアクセスのタイミング調整等の極短時間の待ちに使用する。
void out_w(W port, UW data) W サイズ void out_h(W port, UH data) H サイズ void out_b(W port, UB data) B サイズ
I/O 空間の port
番地へ data
を書き込む。
UW in_w(W port) W サイズ UH in_h(W port) H サイズ UB in_b(W port) B サイズ
I/O 空間の port
番地から読み出す。
DI(UW imask) 割込禁止 EI(UW imask) 割込許可(imask の状態へ戻す)
CPU の割込禁止状態を制御する。DI
により割込を禁止し、
EI
により割込を許可する。
DI(imask)
は imask
に現在の割込禁止状態を保存した後、
割込を禁止する。
EI(imask)
は imask
に保存されている割込禁止状態へ復帰する。
つまり、EI
は DI
の直前の状態に戻す。
したがって、DI
の時点ですでに割込禁止となっていた場合には、
EI
で元の状態に戻しても割込禁止のままである。
imask
の内容は機種に依存している。
DI
、EI
はマクロである。
機種ごとに割込コントローラの制御方法は異なるので、 機種ごとに用意されている関数も異なる。 基本的に、異なる機種でも同等の機能であれば同じ関数名を使用している。
割り込みベクター番号 ( IntVector
) の定義も機種ごとに異なる。
void EnableInt(IntVector vector) void DisableInt(IntVector vector) void ClearInt(IntVector vector) void EndOfInt(IntVector vector) W CheckInt(IntVector vector) void EnableInt(IntVector vector)
vector
で指定した割り込みを許可する。
既に割り込み要求があった場合は、許可した直後に割り込みが発生する。
void DisableInt(IntVector vector)
vector
で指定した割り込みを禁止する。
割り込み禁止中に発生した割り込み要求は、保持される。
void ResetInt(IntVector vector)
vector
で指定した割り込み要求をリセットする。
void ClearInt(IntVector vector)
vector
で指定した割り込み要求をクリアする。
void EndOfInt(IntVector vector)
vector
で指定した割り込みの割り込み処理終了を通知する。
現在処理している割り込みレベルを示す vector
を指定しなければならない。
void LevelInt(IntVector vector)
vector
で指定した割り込み要求をレベルトリガに設定する。
void EdgeInt(IntVector vector)
vector
で指定した割り込み要求をエッジトリガに設定する。
W CheckInt(IntVector vector)
vector
で指定した割り込みの要求の有無をチェックする。
要求がある場合は、0 でない値が戻る。
デバイスコンフィグレーション情報 ( DEVCONF
) から、情報を取得する。
W GetDevConf(B *name, W val[L_DEVCONF_VAL])
name :
val :
W GetDevConfStr(B *name, B str[L_DEVCONF_STR])
name :
str :
デバイスコンフィグレーション情報は、
/SYS/DEVCONF
にファイルとして存在する。
このファイルは、システム起動時にメモリーに読み込まれる。
上記関数はこのメモリー上の情報を取得する。
したがって、DEVCONF
ファイルを変更しても、
システムを再起動しなければ、その変更は反映されない。
PC-AT の場合、下位 16MB のメモリー空間に対してしか DMA 転送を行うことができず、 また 64KB または 128KB 境界を含む領域に対して DMA 転送ができない。これらの制約から、 DMA 転送可能な領域を確保するための特殊なメモリー管理機能が用意されている。
ERR b_get_mbk(VP *adr, W nblk, UW atr)
adr :
nblk :
atr :
latr = M_DMA|M_SYSTEM|M_RESIDENT
の指定により、
DMA 専用メモリーを確保する。他のオプションの組み合わせは許されない。
得られるメモリーは 64KB 境界を含まないことが保証される。 したがって、最大で 64KB の連続領域しか確保できない。
得られるアドレスは論理アドレスである。
ERR b_rel_mbk(VP adr)
adr :
DMA 専用メモリーを解放する。
デバイス処理の応答メッセージに返す主なエラーコードには 下記のようなものがある。
ER_OK (=0) 正常終了
ErrCode.c.eclass
)EC_ADR 不正アドレス EC_PAR パラメータエラー、ユニットが存在しない EC_RONLY 書き込み保護メディア EC_BUSY ビジー状態 EC_NODEV デバイスへのアクセス不可(電源OFF, 非接続, など) EC_ERDEV 装置異常が発生した EC_NOMDA メディアが存在しない EC_IO 入出力エラーが発生した EC_MINTR 処理をアボートした EC_INNER ITRON システムコールのエラー
ErrCode.c.detail
)
デバイスごとに定義される。各デバイスドライバー仕様を参照のこと。
下記は、全デバイス共通の詳細エラーコードである。
EC_PAR: ED_CMD 不正コマンド ED_DEVID 不正デバイスID ED_DATANO 不正データ番号 ED_DATACNT 不正データ数 ED_DATA 不正データ EC_INNER: ITRON のエラーコード ER を UH にキャストした値