0から作るソフトウェア開発
日々勉強中。。。 |
Follow @Nina_Petipa |
0から作るOS開発 DMAドライバ |
DMAのチャンネルとデバイスの割り当て | ||
---|---|---|
チャンネル | 仕様 | 割り当てられるデバス |
チャンネル0 | XTとAT | システムによって予約されていますので利用できません。(DRAMのリフレッシュに使用されています) |
チャンネル1 | XTとAT | 標準仕様のデバイスは割り当てられていませんので、自由に利用可能です |
チャンネル2 | XTとAT | フロッピーディスクドライブが割り当てられています |
チャンネル3 | XTとAT | ハードディスクドライブが割り当てられています。(通常はUDMAを使用します) |
チャンネル4 | ATのみ | DMAコントローラのスレーブとマスターが接続されています |
チャンネル5 | ATのみ | 標準仕様のデバイスは割り当てられていませんので、自由に利用可能です |
チャンネル6 | ATのみ | 標準仕様のデバイスは割り当てられていませんので、自由に利用可能です |
チャンネル7 | ATのみ | 標準仕様のデバイスは割り当てられていませんので、自由に利用可能です |
8237Aのピンアサイン | ||||
---|---|---|---|---|
シンボル | ピン番号 | I/O | 名称 | 説明 |
Vcc | 31 | 電源 | +5V電源です。 | |
Vss | 20 | グラウンド | グラウンドです | |
CLK | 12 | I | クロック入力 | 8237Aを駆動するクロック及び、データ転送に使用するクロックです。 8237Aは3MHzまでのクロックに対応します(8237A-2は5MHz) |
CS | 11 | I | チップセレクト | Lowアクティブのピンです。 IN/ OUT命令でCPUが8237Aに アクセスするときにLowにします。 |
RESET | 13 | I | リセット | リセット端子をHighにすることで コマンドレジスター、 ステータスレジスター、 リクエストレジスター、 テンポラリーレジスターをクリアします。 また、ファースト/ラストフリップフロップもクリアし、マスクレジスターを セットします。リセット後8237Aはアイドル状態となります。 |
READY | 6 | I | レディ | レディピンに入力があると8237Aが出力するメモリー読み込み/書き込みパルス間隔を 広げます(遅くします)。これにより、低速なメモリーやデバイスとのデータ転送が可能となります。 |
HLDA | 7 | I | ホールド応答 | CPUがDMAコントローラにバスを解放するときにこのピンをHighにします。 |
DREQ0-DREQ3 | 16-19 | I | DMA要求 | DMAコントローラにある4つある各チャンネルに対してDMA転送を要求するピンとなります。 各ピンはデバイスコントローラと接続されていて、DMA転送が必要なときにデバイスのコントローラが このピンをアクティブにします。DMA要求には優先度があり、DREQ0が最も高く、DREQ3が最も低くなります。 DREQ0-3がアクティブになってDMA要求を受けた後、応答としてDACK0-3ピンをアクティブにします。 |
DB0-DB7 | 21-23, 26-30 | I/O | データバス | 8ビットの双方向データバスです。 |
IOR | 1 | I/O | I/Oリード | Lowアクティブで双方向のピンです。アイドル状態のときには CPUが8237Aのレジスターを読み込むときにLowにします。 DMA転送時には8237Aが、デバイスからデータを読み込むときにLowにします。 |
IOW | 2 | I/O | I/Oライト | Lowアクティブで双方向のピンです。アイドル状態のときには CPUが8237Aのレジスターにデータを書き込むときにLowにします。 DMA転送時には8237Aが、デバイスにデータを書き込むときにLowにします。 |
EOP | 36 | I/O | 処理終了 | Lowアクティブで双方向のピンです。アイドル状態のときには Lowの場合、DMA転送が完了している(DMA転送が可能な)ことを示します。 DMA転送中にこのピンがLowになるとDMA転送を中止します。 また、DMA転送バイト数がTC(ターミナルカウント)に に達したときに8237AがこのピンをLowにします。このときに自動初期化機能が 有効になているとベースレジスターに現在のレジスター値が書き換えられます。 自動初期化機能が無効の場合は、 ステータスレジスターのTCビットと マスクビットがセットされます。(マスクビットはクリアされた状態となります)。 |
A0-A3 | 32-35 | I/O | アドレス | 下位のアドレスビットで双方向のラインです。 アイドル状態の場合8237Aのレジスターを指定するのに使用します。 DMA転送中は、8237Aがメモリーなどのアドレスを指定するのに使用します。 |
A4-A7 | 37-40 | O | アドレス | 上位のアドレスで出力専有です。 DMA転送時のみ有効です。 |
HRQ | 10 | O | ホールド要求 | システムバスの使用許可をCPUに要求するピンです。 各チャンネルに対応するマスクビットが クリアされている場合にDREQピンに要求があるとこのピンをアクティブにします。 HLDAピンの入力が入る前にこのピンをアクティブにします。 |
DACK0-DACK3 | 14-15, 24-25 | O | DMA応答 | 各チャンネルのDMA転送が許可された場合にこの応答ピンをHighにします。 リセット時にはLowになっています。 |
AEN | 9 | O | アドレス有効 | 上位のアドレスビットが有効かどうかを示すピンです。 DMA転送中にこのピンがアクティブになっていると アドレスバス以外のシステムバスが無効となります。 Highアクティブです。 |
ADSTB | 8 | O | アドレスストローブ | Highアクティブで外部ラッチに上位アドレスビットをストローブするときに使用します。 DMA転送中にこのピンがアクティブになることでDB0-DB7がアドレスの上位となります。 (DMAの転送アドレスは16ビットで下位はA0-A7で指定します) |
MEMR | 3 | O | メモリー読み込み | DMA読み込み転送中かメモリーからメモリーの転送中にアクティブにします。 Lowアクティブで指定したメモリーアドレスからデータを読み込むときに使用します。 |
MEMW | 4 | O | メモリー書き込み | DMA書き込み転送中かメモリーからメモリーの転送中にアクティブにします。 Lowアクティブで指定したメモリーアドレスにデータを書き込むときに使用します。 |
DMAコントローラ0の制御レジスター(スレーブ) | ||
---|---|---|
ポートアドレス | Read/Write | 説明 |
0x008 | Read | ステータスレジスター |
0x008 | Write | コマンドレジスター |
0x009 | Write | リクエストレジスター |
0x00A | Write | シングルチャンネルマスクレジスター |
0x00B | Write | モードレジスター |
0x00C | Write |
クリアーバイトポインタレジスター
(フリップフロップリセットレジスター) |
0x00D | Read | テンポラリーレジスター |
0x00D | Write | マスタークリアーレジスター |
0x00E | Write | マスクリセットレジスター |
0x00F | Read/Write | オールマスクレジスター |
DMAコントローラ1の制御レジスター(マスター) | ||
---|---|---|
ポートアドレス | Read/Write | 説明 |
0x0D0 | Read | ステータスレジスター |
0x0D0 | Write | コマンドレジスター |
0x0D2 | Write | リクエストレジスター |
0x0D4 | Write | シングルチャンネルマスクレジスター |
0x0D6 | Write | モードレジスター |
0x0D8 | Write |
クリアーバイトポインタレジスター
(フリップフロップリセットレジスター) |
0x0DA | Read | テンポラリーレジスター |
0x0DA | Write | マスタークリアーレジスター |
0x0DC | Write | マスクリセットレジスター |
0x0DE | Read/Write | オールマスクレジスター |
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Description :8237 High Performance Programmable DMA Controllerr ( DMAC 0 ) _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ /* ================================================================================== ISA DMAC Ports ( Generic Registers ) DMAC 0 ================================================================================== */ /* DMAC0 Ports( Slave ) */
#define DEF_PORT_DMAC0_STATUS 0x0008
/* status register */
#define DEF_PORT_DMAC0_COMMAND 0x0008
/* command register */
#define DEF_PORT_DMAC0_REQUEST 0x0009
/* request register */
#define DEF_PORT_DMAC0_SINGLE_MASK 0x000A
/* single mask register */
#define DEF_PORT_DMAC0_MODE 0x000B
/* mode register */
#define DEF_PORT_DMAC0_CLEAR_BP 0x000C
/* clear byte pointer register */
#define DEF_PORT_DMAC0_TEMPORARY 0x000D
/* temporary register */
#define DEF_PORT_DMAC0_MASTER_CLEAR 0x000D
/* master clear register */
#define DEF_PORT_DMAC0_MASK_RESET 0x000E
/* mask reset register */
#define DEF_PORT_DMAC0_ALL_MASK 0x000F
/* all mask register */
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Description :8237 High Performance Programmable DMA Controllerr ( DMAC 1 ) _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ /* ================================================================================== ISA DMAC Ports ( Generic Registers ) DMAC 1 ================================================================================== */ /* DMAC1 Ports( Master ) */
#define DEF_PORT_DMAC1_STATUS 0x00D0
/* status register */
#define DEF_PORT_DMAC1_COMMAND 0x00D0
/* command register */
#define DEF_PORT_DMAC1_REQUEST 0x00D2
/* request register */
#define DEF_PORT_DMAC1_SINGLE_MASK 0x00D4
/* single mask register */
#define DEF_PORT_DMAC1_MODE 0x00D6
/* mode Register */
#define DEF_PORT_DMAC1_CLEAR_BP 0x00D8
/* clear byte pointer register */
#define DEF_PORT_DMAC1_TEMPORARY 0x00DA
/* temporary Register */
#define DEF_PORT_DMAC1_MASTER_CLEAR 0x00DA
/* master clear Register */
#define DEF_PORT_DMAC1_MASK_RESET 0x00DC
/* mask reset Register */
#define DEF_PORT_DMAC1_ALL_MASK 0x00DE
/* all mask Register */
DMC0ベースアドレスレジスターとベースワードカウントレジスター(スレーブ) | ||
---|---|---|
ポートアドレス | Read/Write | 説明 |
0x000 | Write |
チャンネル0 ベースアドレスレジスター
DRAMリフレッシュ用にシステムが使用しますので 使用できません。 |
0x001 | Write |
チャンネル0 ベースワードカウントレジスター
DRAMリフレッシュ用にシステムが使用しますので 使用できません。 |
0x002 | Write | チャンネル1 ベースアドレスレジスター |
0x003 | Write | チャンネル1 ベースワードカウントレジスター |
0x004 | Write | チャンネル2 ベースアドレスレジスター |
0x005 | Write | チャンネル2 ベースワードカウントレジスター |
0x006 | Write | チャンネル3 ベースアドレスレジスター |
0x007 | Write | チャンネル3 ベースワードカウントレジスター |
DMC1ベースアドレスレジスターとベースワードカウントレジスター(マスター) | ||
---|---|---|
ポートアドレス | Read/Write | 説明 |
0x0C0 | Write |
チャンネル4 ベースアドレスレジスター
マスターとスレーブの連結用で使用できません |
0x0C2 | Write |
チャンネル4 ベースワードカウントレジスター
マスターとスレーブの連結用で使用できません |
0x0C4 | Write | チャンネル5 ベースアドレスレジスター |
0x0C6 | Write | チャンネル5 ベースワードカウントレジスター |
0x0C8 | Write | チャンネル6 ベースアドレスレジスター |
0x0CA | Write | チャンネル6 ベースワードカウントレジスター |
0x0CC | Write | チャンネル7 ベースアドレスレジスター |
0x0CE | Write | チャンネル7 ベースワードカウントレジスター |
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Description :8237 High Performance Programmable DMA Controllerr ( DMAC 0 ) _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ /* ================================================================================== ISA DMAC Channel Ports ( Channel Register ) DMAC 0 ================================================================================== */ /* DMAC0 Ports( Slave ) */
#define DEF_PORT_DMAC0_CH0_ADDRESS 0x0000
/* Channel 0 base address register */
#define DEF_PORT_DMAC0_CH0_COUNTER 0x0001
/* Channel 0 base count register */
#define DEF_PORT_DMAC0_CH1_ADDRESS 0x0002
/* Channel 1 base address register */
#define DEF_PORT_DMAC0_CH1_COUNTER 0x0003
/* Channel 1 base count register */
#define DEF_PORT_DMAC0_CH2_ADDRESS 0x0004
/* Channel 2 base address register */
#define DEF_PORT_DMAC0_CH2_COUNTER 0x0005
/* Channel 2 base count register */
#define DEF_PORT_DMAC0_CH3_ADDRESS 0x0006
/* Channel 3 base address register */
#define DEF_PORT_DMAC0_CH3_COUNTER 0x0007
/* Channel 3 base count register */
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Description :8237 High Performance Programmable DMA Controllerr ( DMAC 1 ) _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ /* ================================================================================== ISA DMAC Channel Ports ( Channel Register ) DMAC 1 ================================================================================== */
/* DMAC1 Ports( Master ) */ #define DEF_PORT_DMAC1_CH4_ADDRESS 0x00C0
/* Channel 4 base address register */
#define DEF_PORT_DMAC1_CH4_COUNTER 0x00C2
/* Channel 4 base count register */
#define DEF_PORT_DMAC1_CH5_ADDRESS 0x00C4
/* Channel 5 base address register */
#define DEF_PORT_DMAC1_CH5_COUNTER 0x00C6
/* Channel 5 base count register */
#define DEF_PORT_DMAC1_CH6_ADDRESS 0x00C8
/* Channel 6 base address register */
#define DEF_PORT_DMAC1_CH6_COUNTER 0x00CA
/* Channel 6 base count register */
#define DEF_PORT_DMAC1_CH7_ADDRESS 0x00CC
/* Channel 7 base address register */
#define DEF_PORT_DMAC1_CH7_COUNTER 0x00CE
/* Channel 7 base count register */
#define DEF_DMA_OK 0 #define DEF_DMA_ERROR (-1)
/* ================================================================================== Description :Channel of ISA DMA ================================================================================== */
typedef enum { E_DMA_CHANNEL0 = 0, E_DMA_CHANNEL1 = 1, E_DMA_CHANNEL2 = 2, E_DMA_CHANNEL3 = 3, E_DMA_CHANNEL4 = 4, E_DMA_CHANNEL5 = 5, E_DMA_CHANNEL6 = 6, E_DMA_CHANNEL7 = 7 }E_DMA_CHANNEL;
/* ============================================================================== Funtion :dmaSetAddress Input :E_DMA_CHANNEL channel < dma channel > unsigned short address < dma transfer start address > Output :void Return :STATUS Description :set dma transfer start address to address register ============================================================================== */
PRIVATE STATUS dmaSetAddress( E_DMA_CHANNEL channel, unsigned short address ) { unsigned short port_address; if( E_DMA_CH7 < channel ) { return( DEF_DMA_ERROR ); } switch( channel ) { case E_DMA_CHANNEL0: port_address = DEF_PORT_DMAC0_CH0_ADDRESS; break; case E_DMA_CHANNEL1: port_address = DEF_PORT_DMAC0_CH1_ADDRESS; break; case E_DMA_CHANNEL2: port_address = DEF_PORT_DMAC0_CH2_ADDRESS; break; case E_DMA_CHANNEL3: port_address = DEF_PORT_DMAC0_CH3_ADDRESS; break; case E_DMA_CHANNEL4: port_address = DEF_PORT_DMAC1_CH4_ADDRESS; break; case E_DMA_CHANNEL5: port_address = DEF_PORT_DMAC1_CH5_ADDRESS; break; case E_DMA_CHANNEL6: port_address = DEF_PORT_DMAC1_CH6_ADDRESS; break; case E_DMA_CHANNEL7: port_address = DEF_PORT_DMAC1_CH7_ADDRESS; break; default: return( DEF_DMA_ERROR ); break; } outPortByte( port_address, ( 0x00FF ) & address ); outPortByte( port_address, ( ( 0xFF00 ) & address ) >> 8 ); return( DEF_DMA_OK ); }
/* ============================================================================== Funtion :dmaSetCounter Input :E_DMA_CHANNEL channel < dma channel > unsigned short count < dma transfer data length > Output :void Return :STATUS Description :set dma transfer data length to base count register ============================================================================== */
PRIVATE STATUS dmaSetCounter( E_DMA_CHANNEL channel, unsigned short count ) { unsigned short port_address; if( E_DMA_CH7 < channel ) { return( DEF_DMA_ERROR ); } switch( channel ) { case E_DMA_CHANNEL0: port_address = DEF_PORT_DMAC0_CH0_COUNTER; break; case E_DMA_CHANNEL1: port_address = DEF_PORT_DMAC0_CH1_COUNTER; break; case E_DMA_CHANNEL2: port_address = DEF_PORT_DMAC0_CH2_COUNTER; break; case E_DMA_CHANNEL3: port_address = DEF_PORT_DMAC0_CH3_COUNTER; break; case E_DMA_CHANNEL4: port_address = DEF_PORT_DMAC1_CH4_COUNTER; break; case E_DMA_CHANNEL5: port_address = DEF_PORT_DMAC1_CH5_COUNTER; break; case E_DMA_CHANNEL6: port_address = DEF_PORT_DMAC1_CH6_COUNTER; break; case E_DMA_CHANNEL7: port_address = DEF_PORT_DMAC1_CH7_COUNTER; break; default: return( DEF_DMA_ERROR ); } outPortByte( port_address, ( 0x00FF ) & count ); outPortByte( port_address, ( ( 0xFF00 ) & count ) >> 8 ); return( DEF_DMA_OK ); }
ISA DMA拡張ページアドレスレジスター | ||
---|---|---|
ポートアドレス | 昔のパソコン | AT以降の現在のパソコン |
0x080 | チャンネル0 | 拡張/診断ポート |
0x081 | チャンネル1 | チャンネル2 |
0x082 | チャンネル2 | チャンネル3 |
0x083 | チャンネル3 | チャンネル1 |
0x084 | その他 | その他 |
0x085 | その他 | その他 |
0x086 | その他 | その他 |
0x087 | その他 | チャンネル0 |
0x088 | その他 | その他 |
0x089 | その他 | チャンネル6 |
0x08A | その他 | チャンネル7 |
0x08B | その他 | チャンネル5 |
0x08C | その他 | その他 |
0x08D | その他 | その他 |
0x08E | その他 | その他 |
0x08F | その他 | チャンネル4/DRAMリフレッシュ/スレーブ接続 |
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Description :8237 High Performance Programmable DMA Controllerr ISA DMAC Extended Page Address Registers _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
#define DEF_PORT_DMAC_PAGE_CH0_ORG 0x0080
/* channel 0 ( for original pc ) */
#define DEF_PORT_DMAC_DIAG 0x0080
/* extra/diagnostic port */
#define DEF_PORT_DMAC_PAGE_CH1_ORG 0x0081
/* channel 1 ( for original pc ) */
#define DEF_PORT_DMAC_PAGE_CH2 0x0081
/* channel 2 ( for at ) */
#define DEF_PORT_DMAC_PAGE_CH2_ORG 0x0082
/* channel 2 ( for original pc ) */
#define DEF_PORT_DMAC_PAGE_CH3 0x0082
/* channel 3 ( for at ) */
#define DEF_PORT_DMAC_PAGE_CH3_ORG 0x0083
/* channel 3 ( for original pc ) */
#define DEF_PORT_DMAC_PAGE_CH1 0x0083
/* channel 1 ( for at ) */
#define DEF_PORT_DMAC_EXTRA1 0x0084
/* reserved */
#define DEF_PORT_DMAC_EXTRA2 0x0085
/* reserved */
#define DEF_PORT_DMAC_EXTRA3 0x0086
/* reserved */
#define DEF_PORT_DMAC_PAGE_CH0 0x0087
/* channel 0 ( for at ) */
#define DEF_PORT_DMAC_EXTRA4 0x0088
/* reserved */
#define DEF_PORT_DMAC_PAGE_CH6 0x0089
/* channel 6 ( for at ) */
#define DEF_PORT_DMAC_PAGE_CH7 0x008A
/* channel 7 ( for at ) */
#define DEF_PORT_DMAC_PAGE_CH5 0x008B
/* channel 8 ( for at ) */
#define DEF_PORT_DMAC_EXTRA5 0x008C
/* reserved */
#define DEF_PORT_DMAC_EXTRA6 0x008D
/* reserved */
#define DEF_PORT_DMAC_EXTRA7 0x008E
/* reserved */
#define DEF_PORT_DMAC_PAGE_CH4 0x008F
/* channel 4 ( for at ) / to slave */
/* ============================================================================== Funtion :dmaSetPageAddress Input :E_DMA_CHANNEL channel < dma channel > unsigned char page < page number > Output :void Return :STATUS Description :set page number to extended page address register ============================================================================== */
PRIVATE STATUS dmaSetPageAddress( E_DMA_CHANNEL channel, unsigned char page ) { unsigned short port_address; if( E_DMA_CH7 < channel ) { return( DEF_DMA_ERROR ); } switch( channel ) { case E_DMA_CHANNEL0: port_address = DEF_PORT_DMAC_PAGE_CH0; break; case E_DMA_CHANNEL1: port_address = DEF_PORT_DMAC_PAGE_CH1; break; case E_DMA_CHANNEL2: port_address = DEF_PORT_DMAC_PAGE_CH2; break; case E_DMA_CHANNEL3: port_address = DEF_PORT_DMAC_PAGE_CH3; break; case E_DMA_CHANNEL4:
/* exclusive for the connection to the slave */
return( DEF_DMA_OK ); break; case E_DMA_CHANNEL5: port_address = DEF_PORT_DMAC_PAGE_CH5; break; case E_DMA_CHANNEL6: port_address = DEF_PORT_DMAC_PAGE_CH6; break; case E_DMA_CHANNEL7: port_address = DEF_PORT_DMAC_PAGE_CH7; break; default: return( DEF_DMA_ERROR ); } outPortByte( port_address, page ); return( DEF_DMA_OK ); }
DMAコントローラのコマンドレジスター | |||
---|---|---|---|
ビット | シンボル | 名称 | 説明 |
0 | NMT | メモリー間転送有効 |
0:メモリーからメモリー間転送を無効にします 1:メモリーからメモリー間転送を有効にします |
1 | ADHE | チャンネル0アドレス保持有効 |
0:チャンネル0のアドレス保持を無効にします 1:チャンネル0のアドレス保持を有効にします (ビット0のNMTビットが0の場合はこのビットは機能しません) |
2 | COND | コントローラ無効 |
0:コントローラを有効にします 1:コントローラを無効にします |
3 | COMP | タイミング |
0:通常のサイクルタイミングで転送します 1:圧縮サイクルタイミングで転送します (圧縮サイクルタイミングを使用すると転送速度が速くなりますが、 パソコンでは互換性を確保するため、通常使用できません) |
4 | PRIO | 優先度変更 |
0:固定優先度 1:ローテート優先度 (このビットを1にすることで優先度をローテーションすることができますが、 パソコンでは互換性を確保するため、通常使用できません) |
5 | EXTW | 拡張ライト選択 |
0:遅延ライト選択(通常) 1:拡張ライト選択 (ビット3のCONDビットが1の場合はこのビットは無視されます また、このビットを1にすることで拡張ライト選択が使用できますが、 パソコンでは互換性確保のため、使用できません) |
6 | DRQP | DREQ入力 |
0:DREQピンがHighの場合にDMA転送要求を受付ます 1:DREQピンがLowの場合にDMA転送要求を受付ます |
7 | DACKP | DACK出力 |
0:DACKをLowで出力します 1:DACKをHighで出力します |
/********************************************************************************* File:dma.h Description:definition for DMA Controller *********************************************************************************/
#ifndef __DMA_CONTROLLER__H #define __DMA_CONTROLLER__H
/* ================================================================================== Command Register structure < bit number > < discription > 0 0:Memory to memory disable 1:Memory to memory enable 1 0:Channel 0 address hold disable 1:Channel 0 address hold enable ( if bit 0 == 0 : don't care ) 2 0:Controller enable 1:Controller disable 3 0:Normal timing 1:Compressed timing ( if bit 0 == 1 : don't care ) 4 0:Fixed priority 1:Rotating priority 5 0:late write selection 1:Extended write selection 6 0:DREQ sense active high 1:DREQ sense active low 7 0:DACK sense active low 1:DACK sense active high x only bit 2 is used for AT ================================================================================== */
#define DEF_DMAC_COMMAND_REG_MMT 0x01 #define DEF_DMAC_COMMAND_REG_ADHE 0x02 #define DEF_DMAC_COMMAND_REG_COND 0x04 #define DEF_DMAC_COMMAND_REG_COMP 0x08 #define DEF_DMAC_COMMAND_REG_PRIO 0x10 #define DEF_DMAC_COMMAND_REG_EXTW 0x20 #define DEF_DMAC_COMMAND_REG_DRQP 0x40 #define DEF_DMAC_COMMAND_REG_DACKP 0x80 #endif
/*__DMA_CONTROLLER__H */
DMCコントローラのモードレジスター | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ビット | シンボル | 名称 | 説明 | ||||||||||||||
0-1 | SEL0-SEL1 | チャンネル選択 |
チャンネルを選択します
|
||||||||||||||
2-3 | TRA0-TRA1 | 転送タイプ |
DMA転送時の動作を設定します
|
||||||||||||||
4 | AUTO | 自動初期化 |
0:DMA転送完了後の自動初期化を無効にします 1:DMA転送完了後の自動初期化を有効にします 1を設定した場合DMA転送完了後にカレントアドレスレジスターとカレントカレントレジスターを ベースアドレスレジスターとベースカウントレジスターの値に初期化します。フロッピーディスクの トラックデータ転送時に設定しておくと次のトラックのDMA転送が直ぐにできますので便利です。 (サウンドカードの中には自動初期化に対応していないカードがありますので注意します。 サウンドブラスター2.0以降は対応しています) |
||||||||||||||
5 | DOWN | 転送アドレスデクリメント |
0:1回の転送毎に転送アドレスをインクリメントします 1:1回の転送毎に転送アドレスをデクリメントします |
||||||||||||||
6-7 | MOD0-MOD1 | DMA転送モード選択 |
DMA転送モードを選択します
|
/* =============================================================================== Mode Register structure < bit number > < discription > 0-1 00:Channel 0 select 01:Channel 1 select 10:Channel 2 select 11:Channel 3 select 2-3 00:Verify transfer 01:Write transfer 10:Read transfer 11:Illegal ( if bits 6-7 = 11 : don't care ) 4 0:Auto initialization disable 1:Auto initialization enable 5 0:Address Increment select 1:Address decrement select 6-7 00:Demand mode select 01:Single mode select 10:Block mode select 11:Cascade mode select =============================================================================== */ /* channel select */
#define DEF_DMAC_MODE_MASK_SEL 0x03 #define DEF_DMAC_MODE_SEL_CH0 0x00 #define DEF_DMAC_MODE_SEL_CH1 0x01 #define DEF_DMAC_MODE_SEL_CH2 0x02 #define DEF_DMAC_MODE_SEL_CH3 0x03
/* transfer type */
#define DEF_DMAC_MODE_MASK_TRA 0x0C #define DEF_DMAC_MODE_TRA_VERIFY 0x00 #define DEF_DMAC_MODE_TRA_WRITE 0x04 #define DEF_DMAC_MODE_TRA_READ 0x08 #define DEF_DMAC_MODE_TRA_ILLEGAL 0x0C
/* automatic initialization */
#define DEF_DMAC_MODE_AUTO_DISABLE 0x00 #define DEF_DMAC_MODE_AUTO_ENABLE 0x10
/* address increment */
#define DEF_DMAC_MODE_DOWN_DEC 0x00 #define DEF_DMAC_MODE_DOWN_INC 0x20
/* transfer mode */
#define DEF_DMAC_MODE_MASK_MOD 0xC0 #define DEF_DMAC_MODE_MOD_ONDEMAND 0x00 #define DEF_DMAC_MODE_MOD_SINGLE 0x40 #define DEF_DMAC_MODE_MOD_BLOCK 0x80 #define DEF_DMAC_MODE_MOD_CASCADE 0xC0
/* ================================================================================== Funtion :dmaSetModeReg Input :E_DMA_CHANNEL channel < dma channel > unsigned char mode < mode value to set to mode register > Output :void Return :STATUS Description :set value to mode register ================================================================================== */
PRIVATE STATUS dmaSetModeReg( E_DMA_CHANNEL channel, unsigned char mode ) { unsigned short port_address; if( E_DMA_CH7 < channel ) { return( DEF_DMA_ERROR ); } switch( channel ) {
/*--------------------------------------------------------------------------*/ /* for slave */ /*--------------------------------------------------------------------------*/
case E_DMA_CHANNEL0: case E_DMA_CHANNEL1: case E_DMA_CHANNEL2: case E_DMA_CHANNEL3: port_address = DEF_PORT_DMAC0_MODE; break;
/*--------------------------------------------------------------------------*/ /* for master */ /*--------------------------------------------------------------------------*/
case E_DMA_CHANNEL4: case E_DMA_CHANNEL5: case E_DMA_CHANNEL6: case E_DMA_CHANNEL7: port_address = DEF_PORT_DMAC1_MODE;
/* adjust channel value to mode register bit */
channel = ( E_DMA_CHANNEL )( channel - E_DMA_CHANNEL4 ); break; default: return( DEF_DMA_ERROR ); }
/*--------------------------------------------------------------------------*/ /* write value to mode register */ /*--------------------------------------------------------------------------*/
mode = mode | channel; outPortByte( port_address, mode ); return( DEF_DMA_OK ); }
/* ================================================================================== Funtion :dmaSetReadTransferMode Input :E_DMA_CHANNEL channel < dma channel > Output :void Return :STATUS Description :set dmac to a read transfer mode ================================================================================== */
PRIVATE INLINE STATUS dmaSetReadTransferMode( E_DMA_CHANNEL channel ) { unsigned char mode; mode = DEF_DMAC_MODE_TRA_READ | DEF_DMAC_MODE_MOD_SINGLE | DEF_DMAC_MODE_AUTO_ENABLE; return( dmaSetModeReg( channel, mode ) ); }
/* ================================================================================== Funtion :dmaSetWriteTransferMode Input :E_DMA_CHANNEL channel < dma channel > Output :void Return :STATUS Description :set dmac to a write transfer mode ================================================================================== */
PRIVATE INLINE STATUS dmaSetReadTransferMode( E_DMA_CHANNEL channel ) { unsigned char mode; mode = DEF_DMAC_MODE_TRA_WRITE | DEF_DMAC_MODE_MOD_SINGLE | DEF_DMAC_MODE_AUTO_ENABLE; return( dmaSetModeReg( channel, mode ) ); }
DMCコントローラのリクエストレジスター | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ビット | シンボル | 名称 | 説明 | ||||||||||||
0-1 | SEL0-SEL1 | チャンネル選択 |
チャンネルを選択します
|
||||||||||||
2 | REQ | リクエスト |
0:選択したチャンネルのDREQを無効にします 1:選択したチャンネルのDREQをアクティブにします |
DMCコントローラのシングルチャンネルマスクレジスター | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ビット | シンボル | 名称 | 説明 | ||||||||||||
0-1 | SEL0-SEL1 | チャンネル選択 |
チャンネルを選択します
|
||||||||||||
2 | MASK | マスク |
0:選択したチャンネルのマスクを解除します 1:選択したチャンネルをマスクします |
DMCコントローラのオールマスクレジスター | |||
---|---|---|---|
ビット | シンボル | 名称 | 説明 |
0 | CH0 | チャンネル0マスク |
0:チャンネル0のマスクを解除します 1:チャンネル0をマスクします |
1 | CH1 | チャンネル1マスク |
0:チャンネル1のマスクを解除します 1:チャンネル1をマスクします |
2 | CH2 | チャンネル2マスク |
0:チャンネル2のマスクを解除します 1:チャンネル2をマスクします |
3 | CH3 | チャンネル3マスク |
0:チャンネル3のマスクを解除します 1:チャンネル3をマスクします |
/* ================================================================================== Funtion :dmaMaskChannel Input :E_DMA_CHANNEL channel < dma channel to mask > Output :void Return :void Description :set mask bit of designated channel ================================================================================== */
PRIVATE INLIN VOID dmaMaskChannel( E_DMA_CHANNEL channel ) { unsigned char bit_ch; unsigned short port_address;
/*--------------------------------------------------------------------------*/ /* read current mask bit */ /*--------------------------------------------------------------------------*/
if( E_DMA_CHANNEL3 < channel ) { bit_ch = inPortByte( DEF_PORT_DMAC0_ALL_MASK );
/* adjust mask bit for all mask register */
channel = channel - E_DMA_CHANNEL4; port_address = DEF_PORT_DMAC0_ALL_MASK } else { bit_ch = inPortByte( DEF_PORT_DMAC1_ALL_MASK ); port_address = DEF_PORT_DMAC1_ALL_MASK; }
/*--------------------------------------------------------------------------*/ /* set designated channel bit */ /*--------------------------------------------------------------------------*/
bit_ch = bit_ch | ( 1 << channel ); outPortByte( port_address, bit_ch ); }
/* ================================================================================== Funtion :dmaUnmaskChannel Input :E_DMA_CHANNEL channel < dma channel to unmask > Output :void Return :void Description :set unmask bit of designated channel ================================================================================== */
PRIVATE INLIN VOID dmaUnmaskChannel( E_DMA_CHANNEL channel ) { unsigned char bit_ch; unsigned short port_address;
/*--------------------------------------------------------------------------*/ /* read current mask bit */ /*--------------------------------------------------------------------------*/
if( E_DMA_CHANNEL3 < channel ) { bit_ch = inPortByte( DEF_PORT_DMAC0_ALL_MASK );
/* adjust mask bit for all mask register */
channel = channel - E_DMA_CHANNEL4; port_address = DEF_PORT_DMAC0_ALL_MASK } else { bit_ch = inPortByte( DEF_PORT_DMAC1_ALL_MASK ); port_address = DEF_PORT_DMAC1_ALL_MASK; }
/*--------------------------------------------------------------------------*/ /* set designated channel bit */ /*--------------------------------------------------------------------------*/
bit_ch = bit_ch & ~( 1 << channel ); outPortByte( port_address, bit_ch ); }
DMCコントローラのステータスレジスター | |||
---|---|---|---|
ビット | シンボル | 名称 | 説明 |
0 | TC0 | チャンネル0 DMA転送完了 |
0:チャンネル0のDMA転送は完了していません 1:チャンネル0のDMA転送は完了しました |
1 | TC1 | チャンネル1 DMA転送完了 |
0:チャンネル1のDMA転送は完了していません 1:チャンネル1のDMA転送は完了しました |
2 | TC2 | チャンネル2 DMA転送完了 |
0:チャンネル2のDMA転送は完了していません 1:チャンネル2のDMA転送は完了しました |
3 | TC0 | チャンネル3 DMA転送完了 |
0:チャンネル3のDMA転送は完了していません 1:チャンネル3のDMA転送は完了しました |
4 | CH0 | チャンネル0 DMAリクエスト保留中 |
0:チャンネル0はデバイスからのDMA要求を保留していません 1:チャンネル0はデバイスからのDMA要求を保留しています |
5 | CH1 | チャンネル1 DMAリクエスト保留中 |
0:チャンネル1はデバイスからのDMA要求を保留していません 1:チャンネル1はデバイスからのDMA要求を保留しています |
6 | CH2 | チャンネル2 DMAリクエスト保留中 |
0:チャンネル2はデバイスからのDMA要求を保留していません 1:チャンネル2はデバイスからのDMA要求を保留しています |
7 | CH3 | チャンネル3 DMAリクエスト保留中 |
0:チャンネル3はデバイスからのDMA要求を保留していません 1:チャンネル3はデバイスからのDMA要求を保留しています |
typedef enum { E_DMA_CLASS_MASTER = 0x00, E_DMA_CLASS_SLAVE = 0x01 }E_DMA_CLASS; #define DEF_DMAC_CLR_DATA 0xFF
/* ================================================================================== Funtion :dmaResetFlipFlop Input :E_DMA_CLASS class < select DMAC 0 or 1 > Output :void Return :STATUS Description :Reset flip-flop ================================================================================== */
STATUS dmaResetFlipFlop( E_DMA_CLASS class ) { unsigned char port_address; if( E_DMA_CLASS_SLAVE < class ) { return( DEF_DMA_ERROR ); } switch( class ) { case E_DMA_CLASS_MASTER: port_address = DEF_PORT_DMAC1_CLEAR_BP; break; case E_DMA_CLASS_SLAVE: port_address = DEF_PORT_DMAC0_CLEAR_BP; break; default: return( DEF_DMA_ERROR ); } outPortByte( port_address, DEF_DMAC_CLR_DATA ); return( DEF_DMAC_OK ); }
/* ============================================================================== Funtion :dmaResetAllMask Input :E_DMA_CLASS class < select DMAC 0 or 1 > Output :void Return :STATUS Description :Reset all masks ============================================================================== */
STATUS dmaResetAllMask( E_DMA_CLASS class ) { BYTE port_address; if( E_DMA_CLASS_SLAVE < class ) { return( DEF_DMA_ERROR ); } switch( class ) { case E_DMA_CLASS_MASTER: port_address = DEF_PORT_DMAC1_MASK_RESET; break; case E_DMA_CLASS_SLAVE: port_address = DEF_PORT_DMAC0_MASK_RESET; break; default: return( DEF_DMA_ERROR ); } outPortByte( port_address, DEF_DMAC_CLR_DATA ); return( DEF_DMAC_OK ); }
/* ============================================================================== Funtion :dmaClearMaster Input :E_DMA_CLASS class < select DMAC 0 or 1 > Output :void Return :STATUS Description :clear master ============================================================================== */
STATUS dmaClearMaster( E_DMA_CLASS class ) { BYTE port_address; if( E_DMA_CLASS_SLAVE < class ) { return( DEF_DMA_ERROR ); } switch( class ) { case E_DMA_CLASS_MASTER: port_address = DEF_PORT_DMAC1_MASTER_CLEAR; break; case E_DMA_CLASS_SLAVE: port_address = DEF_PORT_DMAC0_MASTER_CLEAR; break; default: return( DEF_DMA_ERROR ); } outPortByte( port_address, DEF_DMAC_CLR_DATA ); return( DEF_DMAC_OK ); }
PUBLIC STATUS fddReadSector( unsigned char drive, unsigned int lba, unsigned char *trasfered_address, unsigned int data_length ) { unsigned char head; unsigned char track; unsigned char sector; STATUS status; if( DEF_FDC_DOR_DRIVE3 < drive ) { return( DEF_FDD_ERROR ); }
/*--------------------------------------------------------------------------*/ /* set up DMA controller for fdd */ /*--------------------------------------------------------------------------*/
status = initDMAforReadFDD( trasfered_address, data_length - 1 );
/*--------------------------------------------------------------------------*/ /* start the motor of specified dirve */ /*--------------------------------------------------------------------------*/ startFdc0Motor( drive ); /*--------------------------------------------------------------------------*/ /* convert lba to chs */ /*--------------------------------------------------------------------------*/ head = convertLBA2Head( lba ); track = convertLBA2Track( lba ); sector = convertLBA2Sector( lba ); /*--------------------------------------------------------------------------*/ /* seek specified track */ /*--------------------------------------------------------------------------*/ status = fddSeek( drive, head, track ); if( status != DEF_FDD_OK ) { return( status ); } /*--------------------------------------------------------------------------*/ /* issue read data command to read a sector */ /*--------------------------------------------------------------------------*/ status = writeFdc0CmdReadData( drive, head, track, sector ); /*--------------------------------------------------------------------------*/ /* wait until irq of dma is fired */ /*--------------------------------------------------------------------------*/ dmaWaitIrq( E_DMA_CHANNEL2 ); /*--------------------------------------------------------------------------*/ /* stop the motor of specified dirve */ /*--------------------------------------------------------------------------*/ stopFdc0Motor( drive ); return( status ); }
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Funtion :initDMAforReadFDD Input :unsigned char *phy_adr < physical address of dma transfer > unsigned int length < length of dma transfer > Output :void Return :void Description :initialize dma for reading Floppy Disc _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
PUBLIC INLINE STATUS initDMAforReadFDD( unsigned char *phy_adr, unsigned int length ) { return( dmaInitDMA( E_DMA_TRANSFER_TYPE_WRITE, E_DMA_CHANNEL2, ( VOID* )phy_adr, length ) ); }
/* ================================================================================== Funtion :dmaInitDMAforFDD Input :E_DMA_TRANSFER_TYPE type < type of transfer > E_DMA_CHANNEL channel < dma channel > unsigned char *phy_adr < physical address of dma transfer > unsigned int length < length of dma transfer > Output :void Return :void Description :initialize dma for device ================================================================================== */
PRIVATE STATUS dmaInitDMA( E_DMA_TRANSFER_TYPE type, E_DMA_CHANNEL channel, void *phy_adr, unsigned int length ) { STATUS status; unsigned short trans_adr; if( USHRT_MAX < length ) { return( DEF_DMA_ERROR ); }
/*--------------------------------------------------------------------------*/ /* mask the channel */ /*--------------------------------------------------------------------------*/
status = dmaMaskChannel( channel ); if( DEF_DMA_OK != status ) return DEF_DMA_ERROR;
/*--------------------------------------------------------------------------*/ /* clear the flip flop of dmc1 */ /*--------------------------------------------------------------------------*/
status = dmaResetFlipFlop( E_DMA_CLASS_MASTER ); if( DEF_DMA_OK != status ) return DEF_DMA_ERROR;
/*--------------------------------------------------------------------------*/ /* set transfered address */ /*--------------------------------------------------------------------------*/
trans_adr = ( unsigned short )( ( unsigned int )phy_adr & DEF_DMAC_ADDRESS ); status = dmaSetAddress( channel, trans_adr ); if( DEF_DMA_OK != status ) return DEF_DMA_ERROR;
/*--------------------------------------------------------------------------*/ /* clear the flip flop of dmc1 again */ /*--------------------------------------------------------------------------*/
status = dmaResetFlipFlop( E_DMA_CLASS_MASTER ); if( DEF_DMA_OK != status ) return DEF_DMA_ERROR;
/*--------------------------------------------------------------------------*/ /* set the length of transfered data */ /*--------------------------------------------------------------------------*/
status = dmaSetCounter( channel, ( unsigned short )length ); if( DEF_DMA_OK != status ) return DEF_DMA_ERROR;
/*--------------------------------------------------------------------------*/ /* set transfer type */ /*--------------------------------------------------------------------------*/
switch( type ) { case E_DMA_TRANSFER_TYPE_WRITE: status |= dmaSetWirteTransferMode( channel ); break; case E_DMA_TRANSFER_TYPE_READ: status |= dmaSetReadTransferMode( channel ); break; default: return( DEF_DMA_ERROR ); }
/*--------------------------------------------------------------------------*/ /* unmask the channel */ /*--------------------------------------------------------------------------*/
status = dmaUnmaskChannel( channel ); return( status ); }