linux-0.11核心 硬碟驅動程式

來源:互聯網
上載者:User

一、概述

首先要說明的是核心每次讀寫的資料量以一個邏輯塊為單位,即1024B,而塊裝置控制器則是以扇區(512B)為單位。

對硬碟的讀寫操作是通過中斷處理常式進行的,使用讀寫請求項等待隊列來順序緩衝一次讀寫多個邏輯塊的操作。進程讀

硬碟上的一個邏輯塊時向緩衝區管理程式提出申請,然後進入睡眠狀態。緩衝區管理程式檢查緩衝區以前是否已經讀取過

這塊資料,如有直接將對應的緩衝區塊頭指標返回給進程並喚醒它,否則,調用ll_rw_block()向相應的裝置驅動程式發出

一個讀資料區塊的操作請求。該函數建立一個請求結構項,插入隊列,插入時採用電梯演算法(至今還沒讀懂電梯演算法)。如對應

裝置的請求項隊列空,則裝置不忙,立即向該裝置控制器發出讀資料命令。當裝置控制器將資料讀入到指定的緩衝塊中後,就

會發出插斷要求訊號,並調用相應的讀命令後處理函數,處理繼續讀扇區操作或者結束本次請求項的過程。(引自趙炯老師)

二、資料結構

塊裝置項

struct blk_dev_struct {
 void (*request_fn)(void);//請求項操作的函數指標
 struct request * current_request;//當前請求項指標
};

 

塊裝置表

extern struct blk_dev_struct blk_dev[NR_BLK_DEV];//每種塊裝置都在表中佔有一項,共7項

 

請求項

struct request {
 int dev;  /* -1 if no request */
 int cmd;  /* READ or WRITE */
 int errors;//錯誤次數
 unsigned long sector;//起始扇區(********?*******)
 unsigned long nr_sectors;//讀寫扇區數
 char * buffer;//資料緩衝區
 struct task_struct * waiting;//發請求的進程

 struct buffer_head * bh;//緩衝區頭
 struct request * next;
};

 

請求項數組

extern struct request request[NR_REQUEST];//共32項

 

請求項隊列由請求項數組中的項構成,

 

三、硬碟驅動程式

涉及的檔案:blk.h,hd.c,ll_rw_block.c

 

blk.h定義如上列出的資料結構,電梯演算法(竟然是用一宏定義實現的),還有解鎖指定的緩衝塊,結束請求處理等extern inline類型

的函數(僅作為嵌入使用)。

 

hd.c是硬碟控制器驅動程式。在對硬碟控制器進行控制時,需要同時發送參數(6B)和命令(1B)。按照這個步驟,將hd.c檔案中的幾乎所有函數串起來。

  1.檢測控制器空閑狀態:讀主狀態寄存器,若BUSY_STAT(位7)為0,表示空閑,若在規定時間內控制器一直忙,則逾時出錯。該部分由

controller_ready函數實現:

static int controller_ready(void)
{
 int retries=10000;

 while (--retries && (inb_p(HD_STATUS)&0xc0)!=0x40);
 return (retries);
}

  2.檢測磁碟機就緒:判斷主狀態寄存器的READY_STAT(位6)是否為1;

static int drive_busy(void)
{
 unsigned int i;

 for (i = 0; i < 10000; i++)
  if (READY_STAT == (inb_p(HD_STATUS) & (BUSY_STAT|READY_STAT)))
   break;
 i = inb(HD_STATUS);
 i &= BUSY_STAT | READY_STAT | SEEK_STAT;
 if (i == (READY_STAT | SEEK_STAT))
  return(0);
 printk("HD controller times out/n/r");
 return(1);
}

  3.輸出命令塊,向對應連接埠輸出參數和命令,hd_out函數實現。

static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
  unsigned int head,unsigned int cyl,unsigned int cmd,
  void (*intr_addr)(void))
{
 register int port asm("dx");

 if (drive>1 || head>15)
  panic("Trying to write bad sector");
 if (!controller_ready())
  panic("HD controller not ready");
 do_hd = intr_addr;
 outb_p(hd_info[drive].ctl,HD_CMD);
 port=HD_DATA;
 outb_p(hd_info[drive].wpcom>>2,++port);
 outb_p(nsect,++port);
 outb_p(sect,++port);
 outb_p(cyl,++port);
 outb_p(cyl>>8,++port);
 outb_p(0xA0|(drive<<4)|head,++port);
 outb(cmd,++port);
}
  4.等待中斷產生。命令執行後,由硬碟控制器產生插斷要求訊號或置控制器狀態為空白閑,表明操作結束或請求扇區傳輸。hd.c中在中斷

處理過程中調用的函數有5個,分別是,void unexpected_hd_interrupt(void),static void bad_rw_intr(void),static void read_intr(void),static void write_intr(void),static void recal_intr(void)。

  5.操作檢測結果:cpu再次讀主狀態寄存器,若位0為0,則表示命令執行成功,否則失敗,若失敗,還可以進一步查詢錯誤寄存器(HD_ERROR)取錯誤碼。相關的函數是static int win_result(void)。

static int win_result(void)
{
 int i=inb_p(HD_STATUS);

 if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
  == (READY_STAT | SEEK_STAT))
  return(0); /* ok */
 if (i&1) i=inb(HD_ERROR);
 return (1);
}

 

整個流程由void do_hd_request(void)控制執行。

 

ll_rw_block.c程式主要用於執行底層塊裝置的讀寫操作,為快裝置建立裝置讀寫項,並插入到指定塊裝置請求隊列中。其調用關係,

到檔案系統時再講。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.