/*
define SAVE_ALL \
"cld; \n\t"
"pushq %rax; \n\t"
"pushq %rax; \n\t"
"pushq %es, %rax; \n\t"
"pushq %rax; \n\t"
"pushq"
...
上面的這段匯編代碼的宏定義就是在執行中斷程序的時候調用的現場保留的操作, 和異常的現場保留是類似的
不同的是, 在異常中是處理器產生的任務暫停, 而在中斷中是外部設備產生的任務暫停
也和異常一樣, 在執行中斷處理函數之前就需要執行現場保留的代碼
*/
/*
- 執行的流程, 通過處理函數的入口函數, 先執行現場保留的代碼,接着下來就和異常處理程序有一點不一樣了, 在中斷處理中, 調用一個do_IRQ函數, do_IRQ函數寄存器中的參數調用
- 對應的處理函數, 在異常中, 我們通過處理函數的入口函數執行了現場保留的代碼之后, 在調用明確的異常處理函數, 當然程序的返回地址都是要記錄的, 這樣才能返回我們原來的程序
*/
/*
- 上面講到的是在遇到了異常的時候CPU是怎么處理的, 前提是我們現在為中斷提供了入口函數 --> 注意: 入口函數和程序處理函數不是完全一樣的, 入口函數中包含有程序處理函數,
- 在入口函數中調用程序處理函數, 在異常和中斷中都是這樣的, 只不過正如上面提到的那樣, 在中斷中的程序處理函數都是交給了一個do_IRQ函數通過參數判斷要調用對應的中斷處理函數
- 我們現在就是要使用set_intr_gate函數將中斷的入口函數們一一注冊好, 注意: 這里的set_intr_gate函數雖然接受的參數是我們入口函數的地址, 但是他在中斷向量表對應的index
- 寫入的數據是一個門描述符, 該門描述符不僅僅是簡單的是入口函數的地址在Linux中, 有一個函數指針數組, 在該數組中保存這的就是所有的中斷處理函數的入口函數的地址, 也就是
- 函數指針, 需要注意的是, 我們使用for循環進行注冊的時候, 起始的i是應該為32, 因為前32個中斷向量號已經被異常時候, 但是有不是32個異常, 用到的是20個異常, 剩下的12個異常中斷
- 向量號為Intel所保留
*/
/*
- 注冊好了之后, 我們需要初始化好ICW和OCW寄存器中的數據
*/
/*
- 下面是一個do_IRQ的demo示例
- 功能: 在屏幕上打印出時鍾中斷的中斷向量號
*/
void do_IRQ(unsigned long regs, unsigned long nr) {
color_printk(RED, BLACK, "do_IRQ:%#08x\t", nr);
io_out(0x20, 0x20);
}
/*
- 通過閱讀建議的鍵盤驅動, 發現所以的驅動編寫就是在編寫一個中斷處理函數, 我們已經知道了, CPU根據中斷向量表中的index找到鍵盤中斷的入口函數, 在該入口函數中調用do_IRQ函數, 在
- do_IRQ函數中調用驅動程序, 就是這樣而已, 所以編寫驅動程序僅僅是內核中的冰山一角
*/