0から作るソフトウェア開発

日々勉強中。。。

0から作るOS開発

環境準備

環境設定

ブートローダ

カーネルローダ

GRUB

カーネル

ドライバーその他

0から作るOS開発 シンプルビデオドライバ

前回までの内容

これまでで、 ことがわかりました。それではカーネルを0から開発していきましょう!

シンプルビデオドライバ

今回は文字を表示する簡単なビデオドライバを開発していきます

VGA(Video Graphics Array)のドライバとCRTマイクロコントローラのドライバについて見ていきます

VGA(Video Graphics Array)

VGAは1987年にIBMのIBM PS/2のビデオとして採用された、画面表示の規格です

VGAの前のISA(Industry Standard Architecture)基盤では多数の

チップセットがありましたが、VGAでは1つのチップに"Array(配列)"してまとめられました

VGAの前にはISAにMDA、CGA、EGAが使われていました

VGAを見ていく前に、前身のMDA、CGA、EGAをみていきましょう

MDA、CGA、EGA

MDAはモノクロームディスプレイアダプタ(Monochrome Display Adapter)を省略したものです

同様にCGAはカラーグラフィックアダプタ(Color Graphics Adapter)、

EGAはエンハンスドグラフィックアダプタ(Enhanced Graphics Adapter)の略となります

MDA(Monochrome Display Adapter)

MDAは1981年にIBMが開発したパソコン用の標準ディスプレイカードです

MDAは現在言うビデオモードというものが無く、モノクロの文字を画面に80列×25行表示だけが

できます(このモードは現在でいうところのビデオモード7にあたります)

ビデオRAMは4kバイトで、アトリビュート(属性)を指定することができます

アトリビュートには”表示しない(invisible)”、”アンダーライン(underline)”、”ノーマル(normal)”、

”ボールド(bright)”、”反転(reverse video)”などがあります

ISAのMDAボード

CGA(Color Graphics Adapter)

CGAも1981年にIBMが開発した初のカラーグラフィックカードで、初のカラーコンピュータディスプレイ標準です

ビデオRAMは16kバイトで、NTSC準拠のモニタやコンポジットビデオ用のRCAコネクタ、

4ビットRGBIが接続できるCRTモニタに接続することができます

1ピクセルあたりにアトリビュートと文字色に4バイトだけしか使用できないので、

16色を使用できるカラーパレットしかありません。ビデオモードとしてテキストモードとグラフィックモードがあり

のモードがあります。CGAにより、文章以外の映像表示が簡単にできるようになりました

CGAの表示画面(NTSCのディスプレイ)

EGA(Enhanced Graphics Adapter)

EGAは1984年にIBMが開発した解像度640×350で64色のパレットから16色を同時表示できる

コンピュータディスプレイ標準です。EGAはCGAと完全互換でCGAで表示可能なモードは

EGAでも使用することができます

ISAのEGAボード

VGAの仕様

VGA(ビデオコントローラ)はビデオバッファ、ビデオDAC(Digital/Analog Converter)、

CRT(Cathode Ray Tube)コントローラ、シーケンサ、グラフィックコントローラ、

アトリビュートコントローラから構成されています

ビデオバッファ

ビデオバッファはビデオメモリ(VRAM)としてメモリ上にマップされています。起動時にBIOSが

メモリの0x000A0000にマップします。アドレスマップは カーネルローダその1 を参照してください。

VESAの仕様によれば、このアドレスは変更することができます

ビデオDAC(Digital/Analog Converter)

ビデオDACはカラーパレットを参照してVRAMのデジタルデータをアナログのビデオ信号に変換して、

ディスプレイに信号を送ります。ビデオDACから出力される信号はレッド、グリーン、ブルーの3つの色を

アナログ信号として出します

CRT(Cathode Ray Tube)コントローラ

CRTコントローラはVRAMに設定された通りに、ディスプレイの水平同期信号タイミング、垂直同期信号タイミング、

カーソルタイミング、アンダーラインタイミングを生成します

シーケンサ

シーケンサはVRAMにアクセスするために、メモリタイミングとVRAMからデータを読み出すキャラクタタイミングを生成します

これにより、CRTディスプレイを捜査している間に、CPUはメモリにアクセスすることができるようになります

グラフィックコントローラ

グラフィックコントローラはCRTディスプレイ捜査中はVRAMとアトリビュートコントローラのインターフェイスとし動作し、

CPUがVRAMにアクセスしている時は、CPUとVRAMのインターフェイスとして動作します



ディスプレイ捜査中は、VRAMのデータをアトリビュートコントローラに転送します。グラフィックモードの場合、

データが転送される前にパラレルからシリアルにデータ変換されてから転送します。テキストモードの場合、

パラレルデータのままアトリビュートコントローラに転送します



CPUがVRAMにアクセスしている時は、CPUがVRAMにデータを転送する前に、グラフィックコントローラが

そのデータを捜査することができます。

アトリビュートコントローラ

グラフィックコントローラがVRAMからアトリビュートコントローラにデータを転送します。この転送されるデータは、

グラフィックモードの時はシリアルデータで、テキストモードのときはパラレルデータとなります

アトリビュートコントローラはデータを受け取ると、データをもとに64色のパレットから色を選びます(実際には色の値)

この色(の値)はビデオDAC(Digital/Analog Converter)でアナログ出力に変換されて、ディスプレイに表示されます

ブリンク(瞬くような表示)、アンダーライン、カーソル移動などをアトリビュートコントローラが制御します

ビデオモード

ビデオモードには大きく分けて2つあります。APA(All Points Addressable)グラフィックモードとテキストモードです

モードを変えることで、VRAMに書かれたデータをどのように表示するかが変わります

APA(All Points Addressable)グラフィックモード

APAグラフィックモード(このサイトでは単にグラフィックモードと記載します)は、VRAM上のデータを1つ1つのピクセルとして

表示するモードです。ディスプレイは”ピクセル”と呼ばれる枠(1つのドット)を表示の最小単位としています。

テキストモード

VRAM上のデータを文字として扱い、文字をディスプレイに表示するモードです

VGAコントローラはテキストモードで2つのバッファを使用します。キャラクタマップとスクリーンバッファです

キャラクタマップはどの文字を表示するかを設定するバッファで、

スクリーンバッファはディスプレイのどこに表示するかを設定します

テキストモードは他にアトリビュートで文字色、ブリンク、アンダーラインなどを設定できます

BIOSのビデオモード

起動時にBIOSはデフォルトのビデオモードを設定します

カラーディスプレイのデフォルトモーはBIOSビデオモード3+で、

モノクロディスプレイのデフォルトモードはBIOSビデオモード7+が設定されています

(モードの番号は16進数です)

デフォルトモードの文字表示数を下記表で確認できます

BIOSビデオモード
モード
HEX
Type 色数 文字表示数 VRAM開始アドレス ボックスサイズ 最大ページ 周波数 解像度
0, 1 テキスト 16 40x25 0x000B8000 8 x 8 8 70Hz 320x200
0*, 1* テキスト 16 40x25 0x000B8000 8 x14 8 70Hz 320x350
0+, 1+ テキスト 16 40x25 0x000B8000 9 x16 8 70Hz 360x400
2, 3 テキスト 16 80x25 0x000B8000 8 x 8 8 70Hz 640x200
2*, 3* テキスト 16 80x25 0x000B8000 8 x14 8 70Hz 640x350
2+, 3+ テキスト 16 80x25 0x000B8000 9 x16 8 70Hz 720x400
4, 5 グラフィック 4 40x25 0x000B8000 8 x 8 1 70Hz 320x200
6 グラフィック 2 80x25 0x000B8000 8 x 8 1 70Hz 640x200
7 テキスト - 80x25 0x000B0000 9 x14 8 70Hz 720x350
7+ テキスト - 80x25 0x000B0000 9 x16 8 70Hz 720x400
D グラフィック 16 40x25 0x000A0000 8 x 8 8 70Hz 320x200
E グラフィック 16 80x25 0x000A0000 8 x 8 4 70Hz 640x200
F グラフィック - 80x25 0x000A0000 8 x14 2 70Hz 640x350
10 グラフィック 16 80x25 0x000A0000 8 x14 2 70Hz 640x350
11 グラフィック 2 80x30 0x000A0000 8 x16 1 70Hz 640x480
12 グラフィック 16 80x30 0x000A0000 8 x16 1 70Hz 640x480
13 グラフィック 256 40x25 0x000A0000 8 x 8 1 70Hz 320x200


ここでモードの”*”と”+”はエンハンスモードを意味しています。グラフィックモードの色数は256K色あります

またグレーシェードは64色あります

VGAのVRAMアドレス

カーネルローダその1でメモリマップについて説明しました

メモリマップをもう一度見てみます

VRAMは0x000A000から0x000BFFFFまでを使用する

VRAMのそれぞれの領域は、

と、使用目的によって扱う領域が違います。このアドレスはビデオアダプタのCRTコントローラを

制御をすることで変更することができます

ディスプレイに文字を表示させてみる

ここまでで、色々難しいことがでてきましたが、やることは非常に簡単です

VRAMにアスキーコード1バイトと文字の色などを設定するアトリビュートを1バイト書けば

文字が1文字表示されるという仕組みになっています

まずは0x0008B000に好きなアスキーコードと、0x00008B001に適当な数字をいれてみましょう


#define	VRAM_TEXTMODE	0x000B8000

/*
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
	Funtion     :displaySample
	Input       :void
	Output      :void
	Return      :void

	Description :print a character with setting color in text mode
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
*/
void displaySample( void )
{
	unsigned short *vram_TextMode;
	
	vram_TextMode = ( unsigned short *)VRAM_TEXTMODE;
	
	*vram_TextMode = ( 0x07 << 8 ) | 'A';
}



このような感じで表示できます


#define	VRAM_TEXTMODE	0x000B8000



VRAMのアドレス定義です


	unsigned short *vram_TextMode;



VRAMのアドレスを格納するポインタ変数です。short型にしたのは1文字を表示したいときに

VRAMに書き込む値がアスキーコード1文字(1バイト)+アトリビュート1バイト=2バイトだからです

これで1文字単位で制御することができるようになりますので、作りが簡単になるかと思います


	vram_TextMode = ( unsigned short *)VRAM_TEXTMODE;



VRAMのアドレスを格納します


	*vram_TextMode = ( 0x07 << 8 ) | 'A';



VRAMに文字Aのアスキーコードとアトリビュート0x07を格納します

シフトしているのは下位バイト(0x000B8000)に'A'を格納し、

上位バイト(0x000b8001)に0x07を格納したいので、

short型の値0x0741を作りたいためです

VRAMのアドレスをunsgined char*で宣言して制御しても面白いとおもいます



実際にやってみると思ったよりも結構簡単だったのではないでしょうか

ディスプレイに文字列を表示する

VRAMに書き込み文字とアトリビュートとディスプレイの関係について見ていきます

起動時にBIOSが設定するデフォルトモードはモード3+でした

このモードでは文字の表示数は80(列)×25(行)となります

80x25の文字位置とVRAMのアドレスの対応関係は次の図のようになります

VRAMのアドレスとディスプレイに表示される文字の位置

アスキーコードとアトリビュートの2バイトで1文字を表しますので、アドレスは2バイトずつ増えていきます

1行は80文字ですので、アドレス0x000B80A0は2行目の最初の1文字になります

このようにアドレスとディスプレイの文字の位置は決まっていますので、計算して求めることができます

80x25の座標のうち表示したい位置を( x, y )とすると、VRAM上のアドレスは

	VRAM上のアドレス = x + ( y * 80 )



と計算できます。ここで注意していただきたいのが、上記の式はunsigned short型の

ポインタで計算しているという点です。unsigned char型のポインタであれば


	VRAM上のアドレス = x * 2 + ( y * 80 ) * 2



と×2をする必要があります。この計算を行うため、defineで定義しておきます


#define	MAX_Y	25
#define	MAX_X	80
#define	MAX_XY	(80*25)



のように適当な名前をつけて定義しておけば、よいかと思います

アトリビュートの設定

最初の1バイトは表示したいアスキーコードを入れました。アトリビュートは次のように設定します

アトリビュートのビットアサイン

アトリビュートのビットアサイン
ビット フラグ アトリビュート 説明
0-2 Foreground Color フォアグランドカラー 文字の色を決定します。0から2の各ビットがRGBに対応しています
ビット0:B ブルー
ビット1:G グリーン
ビット2:R レッド
3 I/CS 文字の明度または文字のフォントを選択
(1ビットなので、どちらの場合でも0か1かで選択)
アトリビュートモード制御レジスタ(I/Oアドレス:0x03C0-0x03C1)の
設定によって文字の明度を変えるのか文字のフォントを変えるかの
機能が変わります。デフォルトでは文字の明度を変更する機能となります
4-6 background color バックグラウンドカラー 文字の背景色を決定します。4から6の各ビットがRGBに対応しています
ビット4:B ブルー
ビット5:G グリーン
ビット6:R レッド
7 B/I 文字をブリンク(点滅)または文字の背景色の明度を変更
(1ビットなので、どちらの場合でも0か1かで選択)
アトリビュートモード制御レジスタ(I/Oアドレス:0x03C0-0x03C1)の
設定によって文字をブリンクさせるのか文字の背景色の明度を変えるかの
機能が変わります。デフォルトではブリンクさせる機能が選択されています


文字色と文字の背景色に使用できるカラーは以下のようになります

(Iビットの明度を入れた合計4ビットで表現できるカラーです)

RGBの設定とカラー
設定値 カラー
0x0 ブラック
0x1 ブルー
0x2 グリーン
0x3 シアン
0x4 レッド
0x5 マゼンタ
0x6 ブラウン
0x7 ライトグレイ
0x8 ダークグレイ
0x9 ライトブルー
0xA ライトグリーン
0xB ライトシアン
0xC ライトレッド
0xD ライトマゼンタ
0xE ライトブラウン
0xF ホワイト

文字の表示まとめ

アスキーコードとアトリビュートの文字色、背景色と、( x、 y )座標を指定して

文字を表示するサンプルドライバです


#define	VRAM_TEXTMODE	0x000B8000

/*
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
	Funtion     :displaySample
	Input       :char c
		     < a character to print >
		     unsigned char foreColr
		     < foreground color >
		     unsigned char backColor
		     < background color >
		     int x
		     < x-axis position where a character is printed >
		     int y
		     < y-axis position where a character is printed >
	Output      :void
	Return      :void

	Description :print a character with setting color in text mode
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
*/
void displaySample( char c, unsigned char  foreColor, unsigned char backColor,
		int x, int y )
{
	unsigned short	*vram_TextMode;
	unsigned short	color;
	
	vram_TextMode	= ( unsigned short *)VRAM_TEXTMODE;
	
	color		= ( backColor << 4 ) | ( foreColor & 0x0F );
	
	vram_TextMode	+= x + y * MAX_X;
	
	*vram_TextMode	= ( color << 8 ) | c;
}



文字列を表示する場合はfor文、while文などで繰り返しこの関数をコールすることで

表示します。

inserted by FC2 system