PocketLinux Technical Document <author>神木一也, <tt/kamiki@geocities.com/ <date>v0.1/0618, Jun. 19, 1999. <abstract> この文書は IBM-PC と MobileGear MC-MK32 のアーキテクチャ上の差異と、 linux version 2.0.36 を Mobile Gear で動作させるための実装について説明したものです。 パッチ <tt/patch-0618/ に基づいて記述されています。 </abstract> <toc> <sect>概要 <p> Mobile Gear MC-MK32 はほぼ IBM-PC に互換であり、 <itemize> <item> CPU: i486SX25 12.5MHz <item> メモリ: 8.5M バイト <item> ディスプレイ: 640x240 グレースケール 4 階調 <item> サウンド: 10bit DAC <item> PC カード: PCMCIA II x 1 <item> シリアル: シリアル x 1, モデム(max 14400 bps) x 1, IrDA x 1. <item> APM: 16bit APM BIOS ver. 1.0 </itemize> という資源を有します。 0618 現在 IrDA, サウンドを除きすべての資源を使うことが可能になっています。 IBM-PC との違いは次の通り。 <descrip> <tag/ブートシーケンス/ 通常のブートマーカ(55AA) 以外に専用のブートマーカが必要です。 LILO による bootloader 登録後、rdev することで対処しています。 <tag/ディスプレイ/ TEXT VRAM を持っていません。Graphics Video RAM の配置は素直ですが 従来のどの IBM-PC Graihpcs Adapter とも互換性がありません。 PocketLinux では自力でフォント展開するドライバが組みこまれています。 <tag/キーボード/ キーボード配列はほぼ旧 JIS 配列になっていますが、 scancode は 106jp と部分的に互換性がありません。 ハードウエア的にも、 IBM-PC/AT でも XT でもありません。 また、キーリピート/ディレイが固定(18.5cps, 500ms)です。 PocketLinux ではキーリピート/ディレイについては kernel 側でソフト的に発生させています。 <tag/サウンドポート/ 10bit DAC を経由して出力します。DMA や割り込みはありません。 現在 pcsnd-1.0 を改造してドライバを作成中です。 <tag/モデムポート/ 8250 相当です。圧縮やエラー訂正のためのハードウエア支援はありません。 割り込みは IRQ 9 に固定されています。 現在モデムとしては使えますが、圧縮/エラー訂正はサポートされていません。 <tag/APM/ 32bit BIOS を持っていません。しかも ver. 1.0 です。 電池電圧の取得、CPU 速度の変更は可能ですが、 内部的に standby mode を持っていません。 現在ハードウエアを叩いて情報を直接得て BIOS を emulate しています。 standby mode に相当するものは作成中です。 <tag/フォント/ JIS X 0201 として 6x12, 8x16, 12x24, 8x8, JIS X 0208 として 12x12, 16x16, 24x24 を ROM に持っています。 <tag/ROM ディスク/ MS-DOS の FAT 互換の ROM ディスクが一つ。またその中に doublespace 互換の 圧縮ドライブが 2 つ入っています。 <tag/IrDA ポート/ 専用カスタム LSI のようです。16550A 互換にも見えるようです。 </descrip> <sect>メモリマップ <p> MC-MK32 は 8.5 M バイトの主記憶を持っています。 0x00100000 以下は普通の IBM-PC と同様のメモリマップを持ち、 0x00e00000 〜 0x01c00000 に ROM Disk Drive Image (FAT16 format) を持っています。 また、ROM Disk Drive Image の中の 0x01400000 〜 0x01600000 の領域に FONT ROM が置かれています。 この FONT ROM 領域は ROM Disk からは un_font.bin という名前で参照可能です。 ROM Disk Drive Image の詳細については <ref id="mgdisk" name="ROM ディスクドライバの章">を、 FONT ROM の内部構造とそのアクセスについては <ref id="mgfont" name="FONT ROM ドライバの章">を参照してください。 <tscreen><verb> 000A0000- Optional ROM (CARDLITE etc.) 000B0000- Graphics RAM 000F0000- ROM BIOS 00E00000- ROM Disk Drive Image 00E00000- Partition Table 00E04000- IPL 00E04200- FAT 00E06E00- Root Dir. 00E08000- File Area (IO.SYS,MSDOS.SYS,...) 01400020- Font Image (un_font.bin というファイルとして領域予約) 01400020- 12x12 2byte char font (32byte/char) 0143F000- 06x12 1byte char font (16byte/char) 01444820- 16x16 2byte char font (32byte/char) 01444820- 16x08 2byte char font (32byte/char) 01444820- 08x08 2byte char font (32byte/char) 01483800- 08x16 1byte char font (16byte/char) 01483800- 04x08 1byte char font (16byte/char) 01489000- 08x08 1byte char font (08byte/char) 01489850- 24x24 2byte char font (80byte/char) 01527000- 12x24 1byte char font (48byte/char) </verb></tscreen> <sect>I/O マップ <p> IBM-PC と同様の I/O マップを持ちますが、ところどころ拡張された I/O が 埋め込まれています。また 0xf12 以降に APM I/O があります。 <tscreen><verb> 0022 0023 0028 002A 0F02 0F08 0F12 0F14 0F15 0F18 0F19 </verb></tscreen> <sect>ブートシーケンス <p> <sect>FONT ROM ドライバ <p> この章では ROM フォントの構造と PocketLinux のドライバの内部について説明します。 <sect1>フォントの ROM 上の配置 <p> ROM 上のフォントは <tscreen><verb> /* necmg.h */ #define NECMG_FONTROM_BASE 0x01400000UL /* mgfont.c */ #define p_K12x12 0x00000 #define p_A6x12 0x3f000 #define p_K16x16 0x44800 #define p_A8x16 0x83800 #define p_K24x24 0x89800 #define p_A12x24 0x127000 #define p_A8x8 0x89000 </verb></tscreen> において、たとえば JIS X 0201 6x12 フォント全体は <tt/p_A6x12 + NECMG_FONTROM_BASE/から始まる物理アドレスに存在し、 個々のフォントは JIS X 0201 (0x00 〜 0xff)の場合、 <tscreen><verb> static inline unsigned char* sfont_pos(unsigned short ch){ return &(necmg_sfont->p[ch * necmg_sfont->byte_size]); } </verb></tscreen> JIS X 0208 フォント(0x21 0x21 〜 0x7e 0x7e)の場合、 <tscreen><verb> static inline unsigned char* wfont_pos(unsigned char ch, int ch_2){ /* * ch 第一オクテット。 * ch_2 第二オクテット(先に走る側; LSB) */ int adr = (int )(ch - 0x21) * 96 + (ch_2 - 0x20); return &(necmg_wfont->p[adr * necmg_wfont->byte_size]); } </verb></tscreen> で計算されるアドレスからグリフイメージが存在します。それぞれのグリフは LSB が左に、各バイト内は msb が左に、そして上から下に向けて pixel が置かれています。 24x24pixel font (<tt/byte_width = 3/) の場合、 <tscreen><verb> <-- 左 ---------------- 右 --> <-- LSB -><-- 2 --><-- MSB -> LSB/MSB: Least/Most significant Byte <76543210><76543210><76543210> lsb/msb: Least/Most significant bit msb lsb <---------- グリフ ----------> </verb></tscreen> のように配置されており、<tt>24x24/8 = 72 バイト</tt> ですが グリフ下に空白があり、これを含めて 1 グリフ毎に 80 バイト(<tt/byte_size = 80/) 使われています。 同じフォーマットながら 12x12 pixel font や 12x24 pixel font は注意を要し、 <tscreen><verb> <-- LSB -><-- MSB--> <76543210><76543210> <-- グリフ--><空き-> </verb></tscreen> となっているため unsigned short (<tt/sizeof(unsigned short) = 16/) で読み出すと語内でグリフが連続していません。 <sect1>Linux 上でフォントが使えるようになるタイミング <p> <tt/necmg_mgfont_init()/内部で フォントが <tt/necmg_fontrom_base/ に <tt/vremap()/ されて以後 初めて ROM フォントを使えるようになりますが、 <tt/con_init()/ によって console を初期化する時点では <tt/vremap()/ がまだ使えません。 <tt/vremap()/ は kernel 内のメモリ管理システムを通じて物理アドレスをカーネル空間にマップしますが、 それは<tt/mem_init()/によって初期化されていなければなりません。 そして <tt/con_init()/ は <tt/mem_init()/ などが出すエラーメッセージをいち早く コンソールに出力しなければならない必要から、<tt/mem_init()/ の後に置くことができません。 そこで <tt/vremap()/ が使えるようになるまでの間 カーネル空間に最初からおかれている <tt/clB8x8/ をフォントとして使うことができるようにしてあります。 ただ、このフォントは内部構造が上記の ROM フォントとかなり違うことに注意してください(<ref id="clB8x8" name="後述">)。 <sect1>struct necmg_fontmetric <p> PocketLinux 上では 各 ROM Font は struct necmg_fontmetric を通じて管理されています: <tscreen><verb> /* necmg.h */ struct necmg_fontmetric { unsigned char *p; /* グリフ先頭のアドレス */ unsigned long size; /* フォント全体のサイズ */ int type; /* 0: ascii, 1: jis x0208, 2: internal ascii */ int allocated; /* 0: not allocated, 1: romfont, 2: kmalloced font */ int pixel_width; int pixel_height; int byte_width; /* font 1 scanline あたりバイト数 */ int byte_size; /* font 1 文字あたりバイト数 */ necmg_font_draw draw; unsigned char* shift_mask[4]; }; </verb></tscreen> <descrip> <tag/type/ アドレスを <tt/sfont_pos()/ で計算するものは 0, <tt/wfont_pos/ で 計算しるものは 1. <tt/font_clB8x8_data/ は例外的に 2 になります。 <tag/allocated/ その font が使えるかどうか、<tt/kfree()/ できるかどうかを表します。 <tag/pixel_width/ フォントの幅(pixel 単位)です。 <tag/pixel_height/ フォントの高さ(pixel 単位)です。 <tag/byte_width/ フォントの ROM 上での幅(バイト単位)です。 <tag/byte_size/ フォントの ROM 上での大きさ(バイト単位)です。 <tag/draw/ このフォントをディスプレイに描くための renderer です。 これを通じて汎用のレンダラ以外の、 そのフォント固有のレンダラを使うことができ、現在 6x12, 8x16 の場合は実際に専用のレンダラを持っています。プロトタイプは <tscreen><verb> typedef void (*necmg_font_draw)(unsigned short ch, mgfb_t ppos, ...); </verb></tscreen> と宣言されていて、ディスプレイ上 <tt/ppos/ の位置にフォント<tt/ch/を rendering します。 実際には JIS X 0201 のフォントの場合、 <tscreen><verb> draw( (ch & 0xff) | (ch_attribute << 8) , ppos); </verb></tscreen> JIS X 0208 のフォントの場合、 <tscreen><verb> draw( (ch & 0x7f) | (ch_attribute << 8) , ppos, (ch_2 & 0x7f)); </verb></tscreen> として使われます。ここで ch は 0x00 〜 0xff のフォント、 ch ch_2 は 0x21 0x21 〜 0x7e 0x7e のフォント、ch_attribute は表示の際の 文字属性を表します。 現在 JIS X 0208 はスクリーン上 JIS X 0201 の倍のサイズをとりますが、 文字の右側の属性を左側と異なるようにすることはできません。 Font rendering の詳細については後述の FONT レンダラの章を参照してください。 <tag/shift_mask/ ディスプレイ上バイト境界にないところから文字を描く時のための 補助マスクです。事前に計算したものが置かれています。 </descrip> <sect1>/dev/mgfont <p> デバイスファイル<tt>/dev/mgfont</tt>は FONT ROM 領域を ユーザースペースから <tt/mmap/ するためにあるデバイスです。 <tscreen><verb> cr--r--r-- 1 root root 58, 0 Mar 22 22:56 mgfont cr--r--r-- 1 root root 58, 0 Mar 22 22:56 mgfont0 cr--r--r-- 1 root root 58, 1 Mar 22 22:56 mgfont1 cr--r--r-- 1 root root 58, 2 Mar 22 22:56 mgfont2 cr--r--r-- 1 root root 58, 3 Mar 22 22:56 mgfont3 cr--r--r-- 1 root root 58, 4 Mar 22 22:56 mgfont4 cr--r--r-- 1 root root 58, 5 Mar 22 22:56 mgfont5 cr--r--r-- 1 root root 58, 6 Mar 22 22:56 mgfont6 cr--r--r-- 1 root root 58, 7 Mar 22 22:56 mgfont7 cr--r--r-- 1 root root 58, 3 Mar 22 22:56 mgfonts </verb></tscreen> として用意され、それぞれ <itemize> <item> mgfont0: clB8x8 のフォント <item> mgfont1: JIS X 0201 の 8x8pixel size の内蔵 ROM フォント <item> mgfont2: JIS X 0201 の 6x12pixel size の内蔵 ROM フォント <item> mgfont3: JIS X 0208 の 12x12pixel size の内蔵 ROM フォント <item> mgfont4: JIS X 0201 の 8x16pixel size の内蔵 ROM フォント <item> mgfont5: JIS X 0208 の 16x16pixel size の内蔵 ROM フォント <item> mgfont6: JIS X 0201 の 12x24pixel size の内蔵 ROM フォント <item> mgfont7: JIS X 0208 の 24x24pixel size の内蔵 ROM フォント <item> mgfonts: 内蔵 ROM フォント全体(mgfont0 は含みません) </itemize> を扱います。mgfonts と mgfont3 が重複していますが、これは JIS X 0208 の 12x12pixel size の内蔵 ROM フォントがフォント領域の先頭に あることによる共有(手抜き)です。 効率的な問題から実用上は mgfonts だけが使われるでしょう。 <tscreen><verb> /* mgl-1.5-0610/mgl.c */ int fn = open("/dev/mgfonts", O_RDONLY); if(fn < 0){ perror("open /dev/mgfonts"); exit(1); } font_base = (unsigned char *) mmap((caddr_t)0, 0x200000, PROT_READ, MAP_SHARED | MAP_FILE, fn, 0); </verb></tscreen> などとして使います。read や seek することもできますが、 FONT イメージをまるごと取得する以外に使い道があるとは思えません。 <sect2>ioctl <p> <tt>/dev/mgfont*</tt> に対する ioctl は二つ定義されています。 <descrip> <tag/MGFONT_GETSIZE/ 返り値は unsigned long でフォント全体のサイズが返ります。 <tt/mgfonts/ と <tt/mgfont3/ が共有されている都合から、 <tt/mgfonts/ の場合は 全体でなく 12x12 フォントのサイズが返されてしまいます。 <tag/MGFONT_GETMETRIC/ 返り値は sizeof(struct necmg_fontmetric) で、 そのフォントの現在の fontmetric が返ります。 もちろん p, draw, shift_mask はカーネル内のアドレスなので ユーザー空間からアクセスしても何もありません。 p (フォントアドレス) は mmap して取得すればいいとして、draw はカーネル内の関数をユーザー空間から call するのは たかだか 1 文字描くにはあまりにオーバーヘッドが大きいので 用意されていません。 <tt/mgfonts/ と <tt/mgfont3/ の問題はこちらの場合も同じです。 </descrip> <sect1>clB8x8 フォント <p> カーネル内部の RAM に置かれた clB8x8 フォントは rendering の簡便さを目的として ROM フォントと内部構造が異なります。 clB8x8 は 1 pixel について 2 bit を使い、 <tscreen><verb> <- 左 ------ 右 -> <- LSB -><- MSB -> <0011223344556677> <-- グリフ ------> </verb></tscreen> LSB を左において上から下に pixel を配置し 0x00 〜 0xff に対するグリフを 持っています。 <sect2>clB8x8 に関する注意事項 <p> 1 pixel が 2 bit に展開されているのはディスプレイが 2bpp だからですが、 カーネルメモリが無駄に消費されているので将来 ROM フォントと同じ構造になるか、 あるいはカーネルから削除されるかもしれません。 また、日本語コンソール移行後は非バイトバウンダリでの font rendering が 発生しますが、clB8x8 は rendering function ( <tt/necmg_font_draw_iascii()/ ) の手抜きから非バイトバウンダリでの 表示ができるようになっていません。 もっともデフォルトフォントが 8x8 になるように(i.e. 80x30) コンソールサイズを切替えた場合は ROM フォントの 8x8 pixel size のものにデフォルトフォントが切り替わり clB8x8 が使われることはありませんから、 この問題がユーザーサイドで露見することはないはずです。 <sect>ディスプレイドライバ <p> この章ではモバイルギアのディスプレイの構造と PocketLinux のコンソール出力の implementation について説明します。 <sect1>低レベル関数 <p> Linux 2.0.x では console でテキスト表示するための関数として、 <itemize> <item> <tt/void scr_writew(unsigned short val, unsigned short * addr);/ <item> <tt/void memcpyw(unsigned short *to, unsigned short *from, unsigned int count);/ <item> <tt/void memsetw(void * s, unsigned short c, unsigned int count);/ </itemize> が必要です。それぞれ 1 文字描き、スクロール、空白塗りつぶし、を担当しています。 PocketLinux では効率向上のため、<tt/scr_writew()/ が類似の二つの関数<tt/mg_scr_writew()/,<tt/mg_scr_writew2()/ に分けられています。 <sect2>カーネル 2.2.x の場合の注釈 <p> Llinux version 2.2.x では低レベル関数が一新されました。 Virtual console への書き込みと実 RAM への書き込み関数が分離され、 実 RAM の処理を担当する関数は <itemize> <item> <tt/void scr_putc()/ <item> <tt/void scr_putcs()/ <item> <tt/void scr_bmove()/ <item> <tt/void scr_clear()/ <item> <tt/void scr_revc()/ <item> <tt/void scr_cursor()/ </itemize> となりました。それぞれ一文字描き、複数文字描き、スクロール、 空白塗りつぶし、文字反転、カーソル処理、となっています。 <sect1>仮想コンソール <p> <sect>フォントレンダラ <p> <sect1>非バイトバウンダリへの描き込み <p> <sect1>汎用レンダラ <p> <sect1>6x12 専用レンダラ <p> デフォルトスクリーン 106x20 で最も多用されるフォントであり、 その高速化は最優先事項の一つといえますが、 非バイトバウンダリでの描き込みが発生するため遅くなりやすく、 専用のレンダラが使われています。 6 pixel width のフォントですから、 <tscreen><verb> <-- 左 ---- 右 --> <0011223300112233> : VRAM アドレス <554433221100> : FONT データ </verb></tscreen> <tscreen><verb> <-- 左 ---- 右 --> <0011223300112233> <554433221100> </verb></tscreen> <tscreen><verb> <-- 左 ---- 右 --> <0011223300112233> <554433221100> </verb></tscreen> <tscreen><verb> <-- 左 ------------ 右 --> <001122330011223300112233> <554433221100> </verb></tscreen> の 4 パターンの描き込みが発生し得ます。 このうち前 3 つは 16bit 長の書き込み 1 回で終わらせることができ、 <tscreen><verb> const unsigned short glyph_mask = shift_mask_6[offset]; /* 文字を描くべき場所 */ const unsigned short r_glyph_mask = ~ glyph_mask; /* 文字を描いてはならない場所 */ offset <<= 1; for(iy = necmg_sfont->pixel_height; iy--; ){ unsigned short gl = make_glyph(*font++, ch); gl <<= offset; /* VRAM 上、グリフを右へシフト */ *(unsigned short *)qpos = (*(unsigned short *)qpos & r_glyph_mask) | (gl & glyph_mask); qpos += NECMG_SCREEN_LINESIZE; /* VRAM 上、1 scanline 真下へ */ } </verb></tscreen> という処理になっています。 8x16 も同様のアルゴリズムによっています。 <sect>キーボードデバイス <p> この章ではモバイルギアのキーボードと IBM-PC の違い、 及び PocketLinux 上での取り扱いについて述べます。 <sect1>キーボードハードウエア <p> どちらかといえば IBM-PC/XT 的ですが、ハンドシェイク用 I/O アドレスが 0x61 でなく 0x64 にあります。キーボード割り込みを受け付けた時、scancode は <tscreen><verb> /* keyboard.c */ int retry = 1000; for(;retry >= 0; retry --){ if(0 != (scancode = inb_p(0x60))){ unsigned char status; status = inb_p(0x64); outb_p(status | 0x80, 0x64); outb_p(status & 0x7f, 0x64); handle_scancode(scancode); break; } udelay(10); } </verb></tscreen> として取得され、<tt/handle_scancode()/ を通じて keycode に変換されます。 また、keycode は <tt/translate_keymap()/ でさらにキーマップテーブルにあわせて再変換されます。 <sect1>スキャンコード <p> モバイルギアのキーボードが発生するスキャンコードの表です。 [電源] キーはスキャンコードを発生せず、APM ハンドラ内で polling 取得されています。 また、[NUM] キーは他のキーのスキャンコードを実際に変更してしまうため、 keymap レベルで他の keycode に割り当てることはできません。 <tscreen><verb> with NUM lock ------------------------------ keytop scancode keycode keytop scancode keycode -------------- -------------- ------ ------ -------------- ------ [ESC] 01 01 [AP切替] (F1) 3B 3B [F1] (F2) 3C 3C [F2] (F3) 3D 3D [F3] (F4) 3E 3E [F4] (F5) 3F 3F [F5] (F6) 40 40 [F6] (F7) 41 41 [F7] (F8) 42 42 [F8] (F9) 43 43 [F9] (F10) 44 44 [F10 (SCLK) 46 46 [INS] E0-52 6E(E0_INS) E0-2A-E0-52 6E [DEL] E0-53 6F(E0_DEL) E0-2A-E0-53 6F [NUM] 45 45 [電源] N/A N/A [1] 02 02 [2] 03 03 [3] 04 04 [4] 05 05 [5] 06 06 [6] 07 07 [7] 08 08 [7] 47 47 [8] 09 09 [8] 48 48 [9] 0A 0A [9] 49 49 [0] 0B 0B [ ] 37 37 [-] 0C 0C [^] 0D 0D [\] 2B 2B [BS] 0E 0E [TAB] 0F 0F [Q] 10 10 [W] 11 11 [E] 12 12 [R] 13 13 [T] 14 14 [Y] 15 15 [U] 16 16 [4] 4B 4B [I] 17 17 [5] 4C 4C [O] 18 18 [6] 4D 4D [P] 19 19 [*] 4A 37 [@] 1A 1A [/] 1A 62(E0_KPSLASH) [[] 1B 1B [RET] 1C 1C E0-1C 1C [CTRL] 1D 1D [A] 1E 1E [S] 1F 1F [D] 20 20 [F] 21 21 [G] 22 22 [H] 23 23 [J] 24 24 [1] 4F 4F [K] 25 25 [2] 50 50 [L] 26 26 [3] 51 51 [;] 27 27 [+] 4E 4E [:] 28 28 [-] 28 4A []] (PGDN) E0-51 6D E0-2A-E0-51 6D 左[SHIFT] 2A 2A [Z] 2C 2C [X] 2D 2D [C] 2E 2E [V] 2F 2F [B] 30 30 [N] 31 31 [M] 32 32 [0] 52 52 [,] 33 33 [,] 33 63 [.] 34 34 [.] 53 53 [/] 35 35 [=] E0-35 5B [ろ] (RCTL) E0-1D 61 [ENTER] E0-1D 60(E0_KPENTER) [↑] E0-48 67(E0_UP) E0-2A-E0-48 67 右[SHIFT] 36 36 [CAPS] 3A 3A [かな] (PRTSCR) E0-2A-E0-37 63 [メニュー](ALT) 38 38 [無変換] (RALT) E0-38 64 [SPACE] 39 39 [変換](`~) 29 29 [次頁PDN] (F11) 57 57 [前頁PUP] (F12) 58 58 [←] E0-4B 69(E0_LEFT) E0-2A-E0-4B 69 [↓] E0-50 6C(E0_DOWN) E0-2A-E0-50 6C [→] E0-4D 6A(E0_RIGHT) E0-2A-E0-4D 6A </verb></tscreen> ここでの scancode はすべて make 時のもので、break 時には make 時に XX とすれば break 時には XX | 0x80 のコードが返ります。 特に make sequence が E0-2A-E0-XX となっているものは break 時には E0-YY-E0-AA と返ってきます。 <sect1>キーコード <p> scancode → keycode の変換規則は、 NUM LOCK していないケースに ついてはキー刻印にかかわらず linux のデフォルトのままになっています。 NUM LOCK しているケースについては、モバイルギアの発生するコードが すこし特殊なので積極的に他の IBM-PC キーボードのキーパッドにあわせたものになっています。 <sect1>拡張キーコード <p> モバイルギアの UNISHELL 上では液晶濃度を ctrl+F9, F10 で変更するなど出来ますが、 もちろん linux のデフォルトでそういう keysym は用意されていません。 以下はそういった PocketLinux 特有の keysym に使える 16 進値です。 <descrip> <tag/0x0219/ LCD表示を濃くします。 標準のキーマップでは ctrl+F10 に割り当てられています。 <tt/keyboard.c/ では <tt/lcd_darker()/ が担当しています。 <tag/0x021a/ LCD表示を薄くします。 標準のキーマップでは ctrl+F9 に割り当てられています。 <tt/keyboard.c/ では <tt/lcd_brighter()/ が担当しています。 <tag/0x021b/ console を直前のものと切替えます。 いままで一つしか console を使っていなかった場合には 新しい console を起動する点が 0x0206 (lastcons) と異なります。 <tt/keyboard.c/ では <tt/toggle_console()/ が担当しています。 <tag/0x021c/ console を 106x20 に切替えます。 <tt/keyboard.c/ では <tt/decr_fontsize()/ が担当しています。 <tag/0x021d/ console を 80x15 に切替えます。 <tt/keyboard.c/ では <tt/incr_fontsize()/ が担当しています。 <tag/0x021e/ console を 80x15 と 106x20 の間で切替えます。 <tt/keyboard.c/ では <tt/toggle_fontsize()/ が担当しています。 </descrip> 0618 ではまだ 0x021c 〜 0x21e の実装は不完全です。切替えることは出来ますが 数回切替えると kernel panic を起こすので注意してください。 <sect1>リピートレート/ディレイの変更 <p> ハードウエア上はリピートレート/ディレイは 18.5cps/500ms に固定されています。 PocketLinux ではハードウエアによるリピートを無視し、カーネル内のタイマによって keycode を発生させることでキーリピートを実現し、 リピートレート/ディレイ可変可能にしています。 カーネルタイマは 10ms ステップなのでリピートタイムもディレイタイムも 10ms ステップになっています。 したがって IBM-PC のキーリピートレートは ... 10.0cps, 10.9, 12.0, 13.3, 15.0, 16.0, 17.1, 18.5, 20.0, 21.8, 24.0, 26.7, 30.0 という系列のはずですが PocketLinux では 10.0cps, 11.1, 12.5, 14.3, 16.6, 20.0, 25.0, 33.3, 50.0 という系列になっています。 <sect2>リピートレート/ディレイの変更に関する注意事項 <p> scancode をタイマで発生させることはできますが、scancode レベルでは break 判定が困難なため、scancode レベル(RAW モード)では ハードウエアリピートが有効のままになっています。 Linux キーボードは scancode をプロセスに渡す VC_RAW モード以外に (keymap で変換しない) keycode をプロセスに渡す VC_MEDIUMRAW モードを持っています。 こちらはリピートレート/ディレイ可変になっていますので、 RAW モードが必要な場合も出来るだけ VC_MEDIUMRAW を使うべきです。 scancode のような E0 から始まる複数バイトのシーケンスでなく、 1 バイトのコードが返って来る点でも VC_MEDIUMRAW のほうが使いやすいはずです。 <sect1>電源キー <p> 電源キーはキーボードハードウエアの管理下になく、APM ハードウエアが管理しています。 詳細は APM ドライバの<ref id="powerkey" name="電源キーの項">を参照してください。 <sect>APM ハードウエア <p> Linux は標準ではハードウエアが持っている 32bit APM BIOS をそのまま呼び出して APM ハンドリングしていますが、Mobile Gear は 32bit APM BIOS を持っていません。 したがって PocketLinux では APM BIOS そのものが新たに実装されています。 <sect1>MobileGear の APM ハードウエアモデル <p> <sect1>電池容量の取得 <p> <sect1>電源キーの状態の取得 <p> <sect1>CPU 速度の設定と読みだし <p> APM ハードウエアが正常に機能していれば CPU 速度の設定と読みだしは 0x2a に CPU 用 I/O が見えるように 0x28 に 0 を書き込むことで行ないます。 <tscreen><verb> /* apm_io.c */ static int do_get_cpu_speed(void){ unsigned char port, speed; port = inb_p(0x28); outb_p(0, 0x28); speed = inb_p(0x2a); outb_p(port, 0x28); return(speed & 0x7); } static void do_set_cpu_speed(unsigned short speed){ unsigned short port, data; port = inb_p(0x28); outb_p(0, 0x28); data = inb_p(0x2a); outb(0, 0x28); speed = (data & 0xf0) | ((speed + 8) & 0x000f); outb(speed, 0x2a); outb(port, 0x28); } </verb></tscreen> 以上によって speed は <tscreen><verb> /* necmg.h */ #define NECMG_SPEED_HI 1 /* 16.0 MHz/7.99 BogoMips */ #define NECMG_SPEED_MID_PLS 2 /* 8.0 MHz/3.97 */ #define NECMG_SPEED_MID 3 /* 4.0 MHz/1.95 */ #define NECMG_SPEED_LO_PLS 4 /* 2.0 MHz/0.93 */ #define NECMG_SPEED_LO 5 /* 0.9 MHz/0.82? */ #define NECMG_SPEED_LO_MNS 6 /* 0.4 MHz/0.82? */ </verb></tscreen> という値が設定、あるいは読みだすことができます。 1 〜 4 までが半数系列になっていますが、5, 6 は実測では半数よりすこし遅い周波数になっているようです。 <sect1>液晶濃度の変更 <p> <sect1>液晶のオン/オフ <p> <code> void do_set_lcd_on(){ outb((inb_p(0xf12) & 0xfe), 0xf12); } void do_set_lcd_off(){ outb((inb_p(0xf12) | 0x01), 0xf12); } </code> <sect>APM ドライバ <p> <sect1>APM イベントループ <p> <sect1>サスペンド/レジュームの動作 <p> <sect1>スタンバイモード <p> <sect>ROM ディスクドライバ <p> <sect>シリアルデバイス <p> <sect>サウンドドライバ <p> <sect>謝辞 <p> </article>