A20地址線

http://hi.baidu.com/xshaonan/blog/item/6a3fca976ec5e26755fb965d.html

A20地址線
2009年12月01日 星期二 22:55

;********************************************
; A20.inc
; --- Enable A20 address line
; 方法一: 系統控制端口A
; 方法二: BIOS中斷例程
; 方法三: 鍵盤控制器
; 方法四: 鍵盤控制器輸出端口

;********************************************

%ifndef __A20_INC_67343546FDCC56AAB872_INCLUDED__
%define __A20_INC_67343546FDCC56AAB872_INCLUDED__

bits 16
;---------------------------------------
; 方法一: (system control)系統控制IO端口0x92,可用來實現對A20的開啓與關閉,但因爲0x92端口的細節與功能
; 和製造商有很多關係,所以這種方法移植性比較差
; Bit 0 - Setting to 1 causes a fast reset (Used to switch back to real mode)
; Bit 1 - 0: disable A20; 1: enable A20
; Bit 2 - Manufacturer defined
; Bit 3 - power on password bytes (CMOS bytes 0x38-0x3f or 0x36-0x3f). 0: accessible, 1: inaccessible
; Bits 4-5 - Manufacturer defined
; Bits 6-7 - 00: HDD activity LED off; any other value is "on"
;-----------------------------------------

;----------------------
; 打開地址線
;----------------------
EnableA20_SysControlA:
push ax
in   al, 92h
or    al, 00000010b
out   92h, al
pop   ax
ret

;----------------------
; 關閉地址線
;----------------------
DisableA20_SysControlA:
push ax
in al, 92h
and al, 11111101b
out 92h, al
pop   ax
ret


;-----------------------------------------
;方法二: 使用BIOS INT 0x15
; ax=2400h --- 關閉A20地址線
; ax=2401h --- 開啓A20地址線
; ax=2402h --- 獲取A20當前狀態
; ax=2403h --- 查詢A20
;-----------------------------------------
;----------------------
; 打開地址線
;----------------------
EnableA20_Bios:
pusha
mov   ax, 2401h
int   0x15
popa
ret

;----------------------
; 關閉地址線
;----------------------
DisableA20_Bios:
pusha
mov ax, 2400h
int   0x15
popa
ret

;-----------------------------------------
;方法三: 使用鍵盤控制器(KBC)(這裏指的都是8043 keyboard Controller), 這個方法用得比較好,可移植性比較高
; Note: 設備控制器位於CPU與設備之間,它既要與CPU通信,又要與設備通信,還具有按照CPU所發來的
;    命令去控制設備工作的功能,因此,現有的大多數控制器有以下三部分:
; 1)設備控制器與處理機的接口
; 2)設備控制器與設備的接口
; 3)I/O控制邏輯
;爲了更好地理解控制器,必須先知道控制器內部IO端口所包含的寄存器及其端口映射地址
; *************************
; 端口 讀/寫 描述
; 0x60 讀   讀輸入緩衝
; 0x60 寫   寫輸出緩衝
; 0x64 讀   讀狀態寄存器
; 0x64 寫   發送命令到控制器
; **************************
; 通過寫0x64端口命令字節來發生命令給控制器. 如果這命令帶有參數,則被髮送到0x60端口.
;-----------------------------------------
;-----------------------------------------
; 從0x64端口讀取控制器的狀態信息
;Bit 0: Output Buffer Status
; 0: Output buffer empty, dont read yet
; 1: Output buffer full, please read me :)
;Bit 1: Input Buffer Status
; 0: Input buffer empty, can be written
; 1: Input buffer full, dont write yet
;-----------------------------------------
; Note:在操作系統課程中,CPU與外設之間交換信息即I/O控制方式的宗旨就
; 是: 儘量減少主機對I/O控制的干預,把主機從繁雜的I/O控制事務中
; 解脫出來(因爲CPU的運行速度比I/O設備的運行速度遠快得多),以便
; 更多地去完成數據處理的任務.
wait_input:
in   al, 0x64   ;讀取狀態寄存器
test al, 0x10   ;測試輸入緩衝
jnz   wait_input   ;如果輸入緩衝非空,則繼續等待
ret

wait_output:
in   al, 0x64
test al, 0x01   ;測試輸出緩衝
jz   wait_output   ;如果輸出緩衝非空,則繼承等待
ret


;---------------------------
; 方法三: 通過控制器
;---------------------------
EnableA20_KKbrd:
cli
push ax
mov   al, 0xdd   ;comand 0xdd: 開啓a20
out   0x64, al   ;發送command到控制器
pop   ax
ret

;---------------------------
; 方法四: 通過控制器的輸出端口
;----
; 鍵盤控制器的命令
; 0xD0 Read Output Port
; 0xD1 Write Output Port
; 0xDD Enable A20 Address Line
; 0xDF Disable A20 Address Line

;Note: I/O控制方式有: 程序I/O方式(即程序查詢); 中斷驅動; DMA方式; I/O通道
;---------------------------
EnableA20_KKbrd_Out:
cli
pusha

call wait_input
mov   al, 0xad
out   0x64, al   ; CPU發送關閉鍵盤命令給I/O控制器
call wait_input
  
mov   al, 0xd0   ; CPU發送命令讓控制器去讀輸出端口
out   0x64, al
call wait_output

in   al, 0x60
push eax     ;獲取輸出端口數據並存放在堆棧中
call wait_input

mov   al, 0xd1
out   0x64, al   ; 讓控制器去寫輸出端口
call wait_input

pop   eax
or   al, 2
out   0x60, al

call wait_input
mov   al, 0xae   ; 開啓鍵盤
out   0x64, al

call wait_input
popa
sti
ret

%endif

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章