官术网_书友最值得收藏!

5 初始化PIC(harib03d)

那好,現在欠債(指昨天沒講完的部分)也還清了,就繼續往后講吧。我們接著昨天繼續做鼠標指針的移動。為達到這個目的必須使用中斷,而要使用中斷,則必須將GDT和IDT正確無誤地初始化。

那就趕緊使用中斷吧……但是,還有一件該做的事沒做——還沒有初始化PIC。那么我們現在就來做。

所謂PIC是“programmable interrupt controller”的縮寫,意思是“可編程中斷控制器”。PIC與中斷的關系可是很密切的喲。它到底是什么呢?在設計上,CPU單獨只能處理一個中斷,這不夠用,所以IBM的大叔們在設計電腦時,就在主板上增設了幾個輔助芯片?,F如今它們已經被集成在一個芯片組里了。

PIC是將8個中斷信號英文是interrupt request,縮寫為IRQ。集合成一個中斷信號的裝置。PIC監視著輸入管腳的8個中斷信號,只要有一個中斷信號進來,就將唯一的輸出管腳信號變成ON,并通知給CPU。IBM的大叔們想要通過增加PIC來處理更多的中斷信號,他們認為電腦會有8個以上的外部設備,所以就把中斷信號設計成了15個,并為此增設了2個PIC。

那它們的線路是如何連接的呢?如下頁圖所示。

與CPU直接相連的PIC稱為主PIC(master PIC),與主PIC相連的PIC稱為從PIC(slave PIC)。主PIC負責處理第0到第7號中斷信號,從PIC負責處理第8到第15號中斷信號。master意為主人,slave意為奴隸,筆者搞不清楚這兩個詞的由來,但現在結果是不論從PIC如何地拼命努力,如果主PIC不通知給CPU,從PIC的意思也就不能傳達給CPU?;蛟S是從這種關系上考慮,而把它們一個稱為主人,一個稱為奴隸。

另外,從PIC通過第2號IRQ與主PIC相連。主板上的配線就是這樣,無法用軟件來改變。

為什么是第2號IRQ呢?事實上筆者也搞不清楚。是不是因為第0號和第1號已經被占用了,而第2號現在還空著,所以就用它了呢。嗯……如果有人想進一步了解這個問題,請一定打電話問問IBM的大叔們。

■■■■■

有人可能會納悶兒,怎么突然講起硬件來了?這是因為,如果不懂得這部分的硬件結構,就無法順利設定PIC。

int.c的主要組成部分

void init_pic(void)
/* PIC的初始化 */
{
    io_out8(PIC0_IMR,  0xff  ); /* 禁止所有中斷 */
    io_out8(PIC1_IMR,  0xff  ); /* 禁止所有中斷 */

    io_out8(PIC0_ICW1, 0x11  ); /* 邊沿觸發模式(edge trigger mode)*/
    io_out8(PIC0_ICW2, 0x20  ); /* IRQ0-7由INT20-27接收 */
    io_out8(PIC0_ICW3, 1 << 2); /* PIC1由IRQ2連接 */
    io_out8(PIC0_ICW4, 0x01  ); /* 無緩沖區模式 */

    io_out8(PIC1_ICW1, 0x11  ); /* 邊沿觸發模式(edge trigger mode)*/
    io_out8(PIC1_ICW2, 0x28  ); /* IRQ8-15由INT28-2f接收 */
    io_out8(PIC1_ICW3, 2      ); /* PIC1由IRQ2連接 */
    io_out8(PIC1_ICW4, 0x01  ); /* 無緩沖區模式 */

    io_out8(PIC0_IMR,  0xfb  ); /* 11111011 PIC1以外全部禁止 */
    io_out8(PIC1_IMR,  0xff  ); /* 11111111 禁止所有中斷 */

    return;
}

以上是PIC的初始化程序。從CPU的角度來看,PIC是外部設備,CPU使用OUT指令進行操作。程序中的PIC0和PIC1,分別指主PIC和從PIC。PIC內部有很多寄存器,用端口號碼對彼此進行區別,以決定是寫入哪一個寄存器。

具體的端口號碼寫在bootpack.h里,請參考這個程序。但是,端口號相同的東西有很多,可能會讓人覺得混亂。不過筆者并沒有搞錯,寫的是正確的。因為PIC有些很細微的規則,比如寫入ICW1之后,緊跟著一定要寫入ICW2等,所以即使端口號相同,也能夠很好地區別開來。

■■■■■

現在簡單介紹一下PIC的寄存器。首先,它們都是8位寄存器。IMR是“interrupt mask register”的縮寫,意思是“中斷屏蔽寄存器”。8位分別對應8路IRQ信號。如果某一位的值是1,則該位所對應的IRQ信號被屏蔽,PIC就忽視該路信號。這主要是因為,正在對中斷設定進行更改時,如果再接受別的中斷會引起混亂,為了防止這種情況的發生,就必須屏蔽中斷。還有,如果某個IRQ沒有連接任何設備的話,靜電干擾等也可能會引起反應,導致操作系統混亂,所以也要屏蔽掉這類干擾。

ICW是“initial control word”的縮寫,意為“初始化控制數據”。因為這里寫著word,所以我們會想,“是不是16位”?不過,只有在電腦的CPU里,word這個詞才是16位的意思,在別的設備上,有時指8位,有時也會指32位。PIC不是僅為電腦的CPU而設計的控制芯片,其他種類的CPU也能使用,所以這里word的意思也并不是我們覺得理所當然的16位。

ICW有4個,分別編號為1~4,共有4個字節的數據。ICW1和ICW4與PIC主板配線方式、中斷信號的電氣特性等有關,所以就不詳細說明了。電腦上設定的是上述程序所示的固定值,不會設定其他的值。如果故意改成別的什么值的話,早期的電腦說不定會燒斷保險絲,或者器件冒煙電路上,+5V與GND(地)短路時,就會發生保險絲熔斷、器件冒煙的現象。這可不是嚇唬你,而是真的會發生。;最近的電腦,對這種設定起反應的電路本身被省略了,所以不會有任何反應。

ICW3是有關主—從連接的設定,對主PIC而言,第幾號IRQ與從PIC相連,是用8位來設定的。如果把這些位全部設為1,那么主PIC就能驅動8個從PIC(那樣的話,最大就可能有64個IRQ),但我們所用的電腦并不是這樣的,所以就設定成00000100。另外,對從PIC來說,該從PIC與主PIC的第幾號相連,用3位來設定。因為硬件上已經不可能更改了,如果軟件上設定不一致的話,只會發生錯誤,所以只能維持現有設定不變。

■■■■■

因此不同的操作系統可以進行獨特設定的就只有ICW2了。這個ICW2,決定了IRQ以哪一號中斷通知CPU?!鞍??怎么有這種事?剛才不是說中斷信號的管腳只有1根嗎?”嗯,話是那么說,但PIC還有個挺有意思的小竅門,利用它就可以由PIC來設定中斷號了。

大家可能會對此有興趣,所以再詳細介紹一下。中斷發生以后,如果CPU可以受理這個中斷,CPU就會命令PIC發送2個字節的數據。這2個字節是怎么傳送的呢?CPU與PIC用IN或OUT進行數據傳送時,有數據信號線連在一起。PIC就是利用這個信號線發送這2個字節數據的。送過來的數據是“0xcd 0x? ? ”這兩個字節。由于電路設計的原因,這兩個字節的數據在CPU看來,與從內存讀進來的程序是完全一樣的,所以CPU就把送過來的“0xcd 0x? ? ”作為機器語言執行。這恰恰就是把數據當作程序來執行的情況。這里的0xcd就是調用BIOS時使用的那個INT指令。我們在程序里寫的“INT 0x10”,最后就被編譯成了“0xcd 0x10”。所以,CPU上了PIC的當,按照PIC所希望的中斷號執行了INT指令。

這次是以INT 0x20~0x2f接收中斷信號IRQ0~15而設定的。這里大家可能又會有疑問了?!爸苯佑肐NT 0x00~0x0f就不行嗎?這樣與IRQ的號碼不就一樣了嗎?為什么非要加上0x20? ”不要著急,先等筆者說完再問嘛。是這樣的,INT 0x00~0x1f不能用于IRQ,僅此而已。

之所以不能用,是因為應用程序想要對操作系統干壞事的時候,CPU內部會自動產生INT 0x00~0x1f,如果IRQ與這些號碼重復了,CPU就分不清它到底是IRQ,還是CPU的系統保護通知。

這樣,我們就理解了這個程序,把它保存為int.c。今后要進行中斷處理的還有很多,所以我們就給它另起了一個名字。從bootpack.c的HariMain調用init_pic。

我們來運行一下“make run”。因為這只是內部設定,所以畫面上沒有什么變化,雖然覺得不過癮沒有特別大的成就感,但看起來可以正常運行。

主站蜘蛛池模板: 英德市| 桐乡市| 宣汉县| 密云县| 来凤县| 冷水江市| 勐海县| 榆社县| 个旧市| 绍兴县| 大关县| 威宁| 东丰县| 齐河县| 商水县| 新宁县| 同仁县| 嘉黎县| 临安市| 台中县| 阿坝| 广河县| 军事| 淮安市| 夏河县| 屯留县| 五台县| 忻州市| 上思县| 高清| 冕宁县| 阿克陶县| 双辽市| 阿克苏市| 元江| 榆中县| 任丘市| 虹口区| 乐山市| 洛川县| 巴里|