2013年4月11日 星期四

(F18) 安裝 HighPoint RocketRAID 2220 的 Kernel 3.8 驅動程式

事實上,在 Fedora 18 使用 HighPoint RocketRAID 的 RAID 卡,也快三個月了,『驅動程式的安裝程序』這個發文卻因故未完成。歷經 Linux 的核心版本從 3.6.10 ~ 3.8,這個操作步驟都通過考驗安裝成功,是該把本文完工了。
    前文 “在 Fedora 安裝 HighPoint RocketRAID 的驅動程式” 只在 Fedora 14 (kernel 2.6.35.14-106 以前的版本)中安裝過,在 Fedora 18 中其核心一開始就使用 3.6.10-4,前文編譯驅動程式的程序已不適用,再加上 Fedora 18 的安裝程式也大幅改寫。原本的安裝程序更是需要修正一下。
    本文內容將包含:驅動程式原始碼的修改、Fedora 18 首次安裝、核心更新後驅動程式的編譯三大部份。

一、安裝前的準備工作

官方網站下載原始碼(在各型號的『驅動程式下載』中,標示為『Linux Opensource』),編譯時並不需要 root 權限,用一般用戶帳號即可。下載後解壓縮,以 R2220 為例,
[SiB@Celeron-D ~]$ tar zxf rr222x-linux-src-v1.9-090924-1445.tar.gz
會在 SiB 的家目錄下產生一個新目錄『 ~/rr222x-linux-src-v1.9 』(:後續文章以『原始碼目錄』稱之),參考 Nagilum 的「修補檔」,這是 RocketRAID 2320 的「修補檔」不能直接用來修改 RocketRAID 2220,筆者參考後,再修改 RocketRAID 2220 所用的原始碼。
    為留存完整記錄,將修改處整理在後,避免將來網路下載不到修補檔。整理出的修改如下:(以 RocketRAID 2220 為例)
目錄檔案名修改處的列號
原始碼目錄/inc/linux/Makefile.def77
原始碼目錄/osm/linux/install.sh13
原始碼目錄/osm/linux/os_linux.c199, 210, 262
原始碼目錄/osm/linux/osm_linux.h11
原始碼目錄/osm/linux/osm_linux.c447, 477, 878, 1411
上表中修改處的數字為列數。因為檔案前面的修改都會加入文字,影響之後的列數,故由程式後端開始修改。

⑴ 檔案『原始碼目錄/inc/linux/Makefile.def』的修改

第 77 列,原文
KERNEL_VER := 2.$(shell expr `grep LINUX_VERSION_CODE $(KERNELDIR)/include/linux/version.h | cut -d\  -f3` / 256 % 256)

ifeq ($(KERNEL_VER),)
$(error Cannot find kernel version. Check $(KERNELDIR)/include/linux/version.h.)
endif

ifneq ($(KERNEL_VER), 2.6)
ifneq ($(KERNEL_VER), 2.4)
$(error Only kernel 2.4/2.6 is supported but you use $(KERNEL_VER))
endif
endif

ifeq ($(KERNEL_VER), 2.6)
修改為
VERS_HDR :=$(shell ls $(KERNELDIR)/include/linux/version.h $(KERNELDIR)/include/generated/uapi/linux/version.h 2>/dev/null|head -1)

KERNEL_VER := $(shell expr `grep LINUX_VERSION_CODE $(VERS_HDR)| cut -d\  -f3` / 256 / 256).$(shell expr `grep LINUX_VERSION_CODE $(VERS_HDR) | cut -d\  -f3` / 256 % 256)

ifeq ($(KERNEL_VER),)
$(error Cannot find kernel version. Check $(VERS_HDR).)
endif

KERNTWOFOUR := $(shell expr $(KERNEL_VER) \>= 2.4)
KERNTWOSIX := $(shell expr $(KERNEL_VER) \>= 2.6)
ifeq ($(KERNTWOFOUR), 1)
else
$(error Only kernel 2.4/2.6/3.x is supported but you use $(KERNEL_VER))
endif

ifeq ($(KERNTWOSIX), 1)
完成以上修改後,存檔備用。

⑵ 檔案『原始碼目錄/osm/linux/install.sh』的修改

第 13 列,原文
    2.6 )
    OBJ=ko
    MODVER=`modinfo -F vermagic ${PWD}/${TARGETNAME}.${OBJ} | cut -d' ' -f1`
    ;;
修改為
    2.6 )
    OBJ=ko
    MODVER=`modinfo -F vermagic ${PWD}/${TARGETNAME}.${OBJ} | cut -d' ' -f1`
    ;;
    3.* )
    OBJ=ko
    MODVER=`modinfo -F vermagic ${PWD}/${TARGETNAME}.${OBJ} | cut -d' ' -f1`
    ;;
完成以上修改後,存檔備用。

 檔案『原始碼目錄/osm/linux/os_linux.c』的修改(由後而前)

第 262 列,原文
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
    blkdev_get(bdev, FMODE_READ)
#else 
    blkdev_get(bdev, FMODE_READ, 0 __BDEV_RAW)
#endif
修改為
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
    blkdev_get(bdev, FMODE_READ, NULL)
#else 
    blkdev_get(bdev, FMODE_READ)
#endif
#else 
    blkdev_get(bdev, FMODE_READ, 0 __BDEV_RAW)
#endif
第 210 列,原文
    if ((HPT_UPTR)ptr >= (HPT_UPTR)high_memory)
        kunmap_atomic(ptr, HPT_KMAP_TYPE);
修改為
    if ((HPT_UPTR)ptr >= (HPT_UPTR)high_memory)
        #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
        kunmap_atomic(ptr);
        #else
        kunmap_atomic(ptr, HPT_KMAP_TYPE);
        #endif
第 199 列,原文
    if (page)
        return (PageHighMem(page)?
                    (char *)kmap_atomic(page, HPT_KMAP_TYPE) :
                    (char *)page_address(page))
                + (psg->addr.bus & 0xffffffff);
    else
修改為
    if (page)
        return (PageHighMem(page)?
                    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
                    (char *)kmap_atomic(page) :
                    #else
                    (char *)kmap_atomic(page, HPT_KMAP_TYPE) :
                    #endif
                    (char *)page_address(page))
                + (psg->addr.bus & 0xffffffff);
    else
完成以上修改後,存檔備用。

 檔案『原始碼目錄/osm/linux/osm_linux.h』的修改

第 11 列,原文,將這幾列文字刪除
#ifndef AUTOCONF_INCLUDED
#include <linux/config.h>
#endif
或註解掉
//#ifndef AUTOCONF_INCLUDED
//#include <linux/config.h>
//#endif 
完成以上修改後,存檔備用。

 檔案『原始碼目錄/osm/linux/osm_linux.c』的修改(由後而前)

第 1411 列,原文為空白列,在這裏要加入這 5 列文字
#ifdef DEF_SCSI_QCMD
DEF_SCSI_QCMD(hpt_queuecommand)
#else
#define hpt_queuecommand hpt_queuecommand_lck
#endif
第 878 列,原文
static int hpt_queuecommand (Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
修改為
static int hpt_queuecommand_lck (Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
第 477 列,原文
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
    struct scatterlist *sg;
    sg = scsi_sglist(cmd);
    kunmap_atomic((char *)buf - sg->offset, HPT_KMAP_TYPE);
#else
修改為
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
    struct scatterlist *sg;
    sg = scsi_sglist(cmd);
    /* 1-argument form of k[un]map_atomic was introduced in 2.6.37-rc1;
       2-argument form was deprecated in 3.4-rc1 */
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
    kunmap_atomic((char *)buf - sg->offset);
    #else
    kunmap_atomic((char *)buf - sg->offset, HPT_KMAP_TYPE);
    #endif
#else
第 447 列,原文
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
    struct scatterlist *sg;
    sg = scsi_sglist(cmd);
    *pbuf = kmap_atomic(HPT_SG_PAGE(sg), HPT_KMAP_TYPE) + sg->offset;
    buflen = sg->length;
#else
修改為
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
    struct scatterlist *sg;
    sg = scsi_sglist(cmd);
    /* 1-argument form of k[un]map_atomic was introduced in 2.6.37-rc1;
       2-argument form was deprecated in 3.4-rc1 */
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
    *pbuf = kmap_atomic(HPT_SG_PAGE(sg)) + sg->offset;
    #else
    *pbuf = kmap_atomic(HPT_SG_PAGE(sg), HPT_KMAP_TYPE) + sg->offset;
    #endif
    buflen = sg->length;
#else
完成以上修改後,存檔備用。

 編譯「驅動程式的核心模組」

以編譯 kernel 3.6.10-4 (註:Fedora 18 初始安裝的核心版本)為例,編譯的命令為
[SiB@Celeron-D ~]$ cd ~/rr222x-linux-src-v1.9/product/rr2220/linux/
[SiB@Celeron-D linux]$ make KERNELDIR=/lib/modules/3.6.10-4.fc18.i686/build/ KERNEL_VER=3.6
就可以在 ~/rr222x-linux-src-v1.9/product/rr2220/linux/ 這個目錄得到一個 hptmv6.ko 的『驅動程式核心模組』。相關的詳細操作,請參考以前的發文:
如果是要編譯用來安裝 Fedora 18 之用,就要用另一台電腦或虛擬機器編譯這個「核心模組」。本文以『整個 Fedora 系統都安裝在 RocketRAID 2220 的硬碟組』為主,故編譯好的『核心模組』複製到以 “適用 Fedora 18 的「可選版本 USB 安裝隨身碟」”製做成的 USB 隨身碟中的 FedoraUISO 根目錄中,待會安裝時要使用。

:如果是將 RAID 做為資料碟而非系統碟,整個操作會更簡單。

二、開始安裝

插入『Fedora 18 的可選版本 USB 安裝隨身碟』,設定 BIOS 由 USB 啟動。在『開機選單倒數計時』結束前,
在『Install Fedora』選項按【Tab】鍵,在啟動命令列最後,加入參數『modprobe.blacklist=sata_mv』抑制 stat_mv 這個驅動程式的載入(註:這個 Linux 偵測到的硬體,若載入它則系統會無『硬體加速的 RAID』之功能,只有多幾個硬碟而已 )。接著,在『安裝語言選擇』視窗出現時,先暫停一下,

載入驅動程式的「核心模組」

為載入 RocketRAID 的正確「核心模組」,要同時按下 [Alt]-[Ctrl]-[F2] 三個鍵,切換到「主控台(Console)」,將隨身碟掛載到一個臨時性目錄,用命令『modprobe hptmv6』或『insmod hptmv6.ko』將核心模組載入。
mkdir /tmp/dd
mount /dev/sda2 /tmp/dd
insmod /tmp/dd/hptmv6.ko
若成功載入,當切換到第四「終端機」(同時按 [Alt]-[Ctrl]-[F4] 可切換過去)時,可以看到系統偵測到 RocketRAID 的訊息。
    同時按 [Alt]-[Ctrl]-[F6] 三個鍵,將畫面切換回原安裝圖形畫面,選「中文(臺灣)」,除安裝時為中文介面外,安裝後整個系統也是中文。接著,按【Next】鈕繼續平常的安裝步驟。

:上例是筆者安裝時,Fedora 系統所偵測到的 USB 隨身碟編號(/dev/sdx 表示第 x 個硬碟,而 2 是第二個分割區),讀者如果在 mount 命令執行後,用『ls /tmp/dd』看不到 hptmv6.ko 這個核心模組,就要換個硬碟編號試試。

三、安裝好 Fedora 後,重新開機之前的操作

安裝好 Fedora 後,重新開機之前
  1. 當 Fedora 系統安裝完後,在重開機前會停在一個有【重新開機】或【Reboot】按鈕的畫面。別急著按下去!
  2. 同時按【Alt + Ctrl + F2】三個鍵,切換至「終端機」,開始接下來安裝驅動程式的核心模組的操作。
  3. 待會要切換到新系統做些操作,要先複製隨身碟中的驅動程式之核心模組到新系統的 tmp 目錄中,以方便切換根目錄後還能找到這個核心模組。
    [anaconda root@localhost ~]# cp hptmv6.ko /mnt/sysimage/tmp/
    其中『 /mnt/sysimage/ 』是新安裝作業系統的根目錄,而『 /mnt/sysimage/tmp/ 』則是新系統的命令中的暫時目錄 /tmp。hptmv6.ko 是 RR2220 的核心模組。
切換到新系統的根目錄,進行核心模組安裝
  1. 這個操作有些複雜,請小心操作。新安裝的系統的根目錄在『 /mnt/sysimage 』,因為驅動程式是要裝在新系統上,所以要將目前檔案的根目錄切換過去,
    [anaconda root@localhost ~]# chroot /mnt/sysimage/
    
    接下來的操作,就會作用在新系統上。
  2. 抑制系統載入程式使用『 sata_mv.ko 』這個模組,它會測試到 RocketRAID 所用的晶片,並載入系統執行,但是又不支援 RocketRAID 的 RAID 功能,導致其不能正常運作。要抑制『 sata_mv.ko 』這個模組的載入,有兩個作法:
    [anaconda root@localhost ~]# echo "blacklist sata_mv" >> /etc/modprobe.d/blacklist.conf
    
    將『 sata_mv.ko 』列入開機載入模組的測試「黑名單」。或是直接刪除『 sata_mv.ko 』這個模組,
    [anaconda root@localhost ~]# rm -f /lib/modules/3.6.10-4.fc18.x86_64/kernel/drivers/ata/sata_mv.ko
    
    其中,3.6.10-4.fc18.x86_64 是 Fedora 18 DVD 中 Linux 核心的編號。

    注意:如果用直接刪除,則每次更新 Linux 核心後,都要刪除一次。
  3. 複製暫時目錄 /tmp 中的驅動程式核心模組到新系統的驅動程式目錄中
    [anaconda root@localhost ~]# cp /tmp/hptmv6.ko /lib/modules/3.6.10-4.fc18.x86_64/kernel/drivers/ata/
    命令中的 hptmv6.ko 是 RR2220 的核心模組。
  4. 準備建立開機載入 ramdisk 的映像檔,先檢查各模組的相依性,
    [anaconda root@localhost ~]# depmod -a 3.6.10-4.fc18.x86_64
    做為重新建立開機載入 ramdisk 的映像檔之用。
  5. 接著,建立載入 ramdisk 的映像檔的命令為
    [anaconda root@localhost ~]# dracut --add-drivers hptmv6 --omit-drivers sata_mv /boot/initramfs-3.6.10-4.fc18.x86_64.img 3.6.10-4.fc18.x86_64
    命令中的 hptmv6.ko 是 RR2220 的核心模組,而『--omit-drivers sata_mv』這個參數要強制令 dracut 不將 stat_mv 置入 ramdisk。
注意一:建立 ramdisk 映像檔命令中的『--omit-drivers sata_mv』,如果是將整個系統都裝在 RocketRAID 2220 的 RAID 模組中時,一定要加入。不然,因系統啟動時,在『/tmp/modprobe.d/blacklist.conf』中的『blacklist stat_mv』這的抑制參數尚不能讀取,所以仍會被載入。
注意二:如果忘了加『--omit-drivers sata_mv』這個參數,就要在系統的啟動命令(在 /boot/grub2/grub.conf 中)加上『modprobe.blacklist=sata_mv』。

切換回原安裝過程,進行最後的安裝操作
  1. 在「終端機」中鍵入命令『 exit 』,將根目錄切換回原安裝過程。

    注意:如果不能確定自已目前的根目錄在哪個系統,可以用命令『 ls /mnt 』測試一下,如果有其它目錄在其下,這時你應該已經回到『原安裝過程』中;如果沒有任何目錄,那就是還在『新系統」中。
      
  2. 同時按【Alt + Ctrl + F6】三個鍵,將畫面切換回原安裝圖形畫面,按【重新開機】或【Reboot】按鈕繼續安裝步驟,應該是重新開機了。
  3. 重新開機後,依一般安裝過程設定,可以先使用新系統,不要急著更新,看完下一段文章後,再進行更新。

五、舊系統或系統更新後,加裝驅動程式的核心模組

因為驅動程式的核心模組是用 HighPoint 提供的「開源碼驅動程式」編譯而得,因此每次只要 Linux 核心更新,這個核心模組就要再編譯一次。所幸,Linux 核心更新後,編譯驅動程式核心模組的過程比較簡單。
    假定更新後的 Linux 核心為 3.8.5-201.fc18.x86_64,而從 HighPoint 下載的「開源碼驅動程式」,將其解壓縮後的目錄在 root 之下,則所需的命令如下:
[root@Celeron-D ~]# cd ~/rr222x-linux-src-v1.9/product/rr2220/linux/
[root@Celeron-D linux]# make KERNELDIR=/lib/modules/3.8.5-201.fc18.x86_64/build/ KERNEL_VER=2.6
[root@Celeron-D linux]# cp hptmv6.ko /lib/modules/3.8.5-201.fc18.x86_64/kernel/drivers/ata/
[root@Celeron-D linux]# depmod -a 3.8.5-201.fc18.x86_64
[root@Celeron-D linux]# mv /boot/initramfs-3.8.5-201.fc18.x86_64.img /boot/initramfs-3.8.5-201.fc18.x86_64.img.save
[root@Celeron-D linux]# dracut --add-drivers hptmv6 --omit-drivers sata_mv /boot/initramfs-3.8.5-201.fc18.x86_64.img 3.8.5-201.fc18.x86_64
其中,『 mv ... 』那一列命令是將原來之映像檔換個檔名,做個備份。其他命令與文章前段相同,請參考前面說明。做個『懶人包』方便讀者剪貼使用:
cd ~/rr222x-linux-src-v1.9/product/rr2220/linux/
make KERNELDIR=/lib/modules/3.8.5-201.fc18.x86_64/build/ KERNEL_VER=2.6
cp hptmv6.ko /lib/modules/3.8.5-201.fc18.x86_64/kernel/drivers/ata/
depmod -a 3.8.5-201.fc18.x86_64
mv /boot/initramfs-3.8.5-201.fc18.x86_64.img /boot/initramfs-3.8.5-201.fc18.x86_64.img.save
dracut --add-drivers hptmv6 --omit-drivers sata_mv /boot/initramfs-3.8.5-201.fc18.x86_64.img 3.8.5-201.fc18.x86_64
接著,就可以重新開機,測試新系統了。

六、其它安裝時的經驗

如果整個 RAID 硬碟模組的總容量大於 2TB 以上,用一般的 MBR 分割硬碟會失敗,或效能變得很差。而 Fedora 18 在安裝時,用 GPT 分割碟碟又不太方便,有些網路的解決辦法是先用別的將 RAID 碟碟模組掛到別的系統去分割。筆者也有試過,試了幾次都沒安裝成功,最後用了一個比較偷懶的辦法。這個辦法就是:
在安裝 Fedora 18 時,在分割硬碟這個步驟時,使用系統『自動分割碟碟』功能。這個功能會將硬碟分割為:『/boot』:500MB,『swap』:約是記憶體的兩倍(當記憶體超過 4GB 以上時,會降低倍數),『/root」:50GB,而其它容量全部切到『/home』這個分割。
反正安裝時的分割又不常做,而且 Linux 系統的『/root』分割如果不足,可以將某些目錄用『鏈結(link)』的方式使用『/home』這個分割的空間。

已測試版本:

  • Fedora: 18 (kernel 3.6.10-4 ~ 3.8.5-201)
  • HighPoint RocketRAID: 2220

參考資料:

沒有留言:

張貼留言

感謝你耐心看完本文,歡迎留下任何指正、建議,筆者會儘快回應。(English is also welcome.)