2011年2月8日 星期二

2011-02-08 13:56 老主機板不用關閉ACPI、如何讓PCI裝置在FreeBSD正常運作

在下鄙人我為了省錢、打算用一套老K6配合FreeNAS弄套窮人版NAS。算是跨出了進入FreeBSD的第一步(大概也不會跨更多步了!被GUI寵壞了 XD)。

沒想到第一步還沒落地就跌倒:該死的ACPI讓我的PCI裝置在FreeBSD下失靈了!!

這次窮人版FreeNAS的規格:K6-2 500、磐英MVP3C2、384MB SDRAM、ATI Radeon LE、偽3com 3C905C-TXM、另購SIL3114 RAIDcard以及IDE/CF轉卡搭配PhotoFast SuperCF 4G(我知道FreeNAS只要32MB = =,但沒比這更便宜高速的CF卡了!),稍後可能的儲存裝置為WD7500AACS*2。

早先已經先用VirtualPC2007大致上摸了一遍FreeNAS,功能相當不錯。除了飽經風霜的機殼,雖說是窮人版NAS但實際上也不比一般入門級專用NAS差到哪--更別說低價!(不過沒法取下VGA卡、電力耗用不會比專用NAS低就是,有得必有失)

廢話不多說、回到主題,老主機板啟用ACPI後、如何讓PCI裝置在FreeBSD下正常運作。話說先前的模擬運作相當滿意,進入實機安裝後...... 耶!怎麼網路不通了!還猛刷xl0:watchdog timeout!完蛋了剛出師就出事!趕緊上FreeNAS討論區、Google查詢,瞥見似乎與ACPI有關!趕緊把ACPI關閉了試試先~

哇!關閉ACPI後所有PCI裝置都正常了......咦、怎麼shutdown失效Power Button也失靈了!又是一陣搜尋,原來Soft Power on/off必須配合ACPI!頓時省錢高效能的美夢成了費事的惡夢......

由於FreeNAS本身是精簡版的FreeBSD、欠缺某些BSD核心功能,只能執行dmesg擷取log,為此又特地安裝FreeBSD 7.0RC1。

開機時選擇完整記錄(verbose)登入後再以dmesg取得開機記錄--結果不光PCI、連FDD都出問題(其實壓根也沒打算用FDD、NAS要FDD幹啥?!但修正後的FDD在之後的ACPI調試幫了大忙!)

ACPI Error (dsopcode-0671): Field [IRQL] at 208 exceeds Buffer [BUF0] size 192 (bits) [20070320]

ACPI Error (psparse-0626): Method parse/execution failed [\\_SB_.PCI0.ISA_.FDC0._CRS] (Node 0xc284cd60), AE_AML_BUFFER_LIMIT

ACPI Error (uteval-0309): Method execution failed [\\_SB_.PCI0.ISA_.FDC0._CRS] (Node 0xc284cd60), AE_AML_BUFFER_LIMIT

can't fetch resources for \\_SB_.PCI0.ISA_.FDC0 - AE_AML_BUFFER_LIMIT

acpi0: reservation of 0, a0000 (3) failed

acpi0: reservation of 100000, 17ef0000 (3) failed

ACPI timer: 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 -> 10

Timecounter "ACPI-fast" frequency 3579545 Hz quality 1000

acpi_timer0: <24-bit timer at 3.579545MHz> port 0x4008-0x400b on acpi0

pci_link0:        Index  IRQ  Rtd  Ref  IRQs

 Initial Probe       0   15   N     0  1 3 4 5 6 7 10 11 12 14 15

 Validation          0   15   N     0  1 3 4 5 6 7 10 11 12 14 15

acpi: bad read from port 0x4d1 (8)

acpi: bad write to port 0x4d1 (8), val 0xc

 After Disable       0  255   N     0  1 3 4 5 6 7 10 11 12 14 15

pci_link1:        Index  IRQ  Rtd  Ref  IRQs

 Initial Probe       0   10   N     0  1 3 4 5 6 7 10 11 12 14 15

 Validation          0   10   N     0  1 3 4 5 6 7 10 11 12 14 15

acpi: bad read from port 0x4d1 (8)

acpi: bad write to port 0x4d1 (8), val 0x8

 After Disable       0  255   N     0  1 3 4 5 6 7 10 11 12 14 15

pci_link2:        Index  IRQ  Rtd  Ref  IRQs

 Initial Probe       0    5   N     0  1 3 4 5 6 7 10 11 12 14 15

 Validation          0    5   N     0  1 3 4 5 6 7 10 11 12 14 15

acpi: bad read from port 0x4d0 (8)

acpi: bad write to port 0x4d0 (8), val 0x8

 After Disable       0  255   N     0  1 3 4 5 6 7 10 11 12 14 15


之後以acpidump取得DSDT。後來發現以CBROM將ACPITBL.BIN由BIOS取出後,以HexEditor如Ultraedit將前端部分砍除,保留DSDT[ .....以下部分、透過ACPICA iasl以參數 -d 一樣可decompile還原出所需的DSDT。


先看看DSDT關於Device (FDC0)的敘述


               Device (FDC0)

               {

                   Name (_HID, EisaId ("PNP0700"))

                   Method (_STA, 0, NotSerialized)

                   {

                       ENFG ()

                       If (LEqual (0xFC, CR20))

                       {

                           EXFG ()

                           Return (0x0F)

                       }

                       Else

                       {

                           EXFG ()

                           Return (0x0D)

                       }

                   }

                   Method (_DIS, 0, NotSerialized)

                   {

                       ENFG ()

                       Store (0x00, CR20)

                       EXFG ()

                   }

                   Method (_CRS, 0, NotSerialized)

                   {

                       Name (BUF0, ResourceTemplate ()

                       {

                           IO (Decode16,

                               0x03F2,             // Range Minimum

                               0x03F2,             // Range Maximum

                               0x00,               // Alignment

                               0x04,               // Length

                               _Y0C)

                           IO (Decode16,

                               0x03F7,             // Range Minimum

                               0x03F7,             // Range Maximum

                               0x00,               // Alignment

                               0x01,               // Length

                               )

                           IRQNoFlags ()

                               {6}

                           DMA (Compatibility, NotBusMaster, Transfer8, )

                               {2}

                       })

                       CreateByteField (BUF0, \_SB.PCI0.ISA.FDC0._CRS._Y0C._MIN, IOLO)

                       CreateByteField (BUF0, 0x03, IOHI)

                       CreateByteField (BUF0, \_SB.PCI0.ISA.FDC0._CRS._Y0C._MAX, IORL)

                       CreateByteField (BUF0, 0x05, IORH)

                       CreateByteField (BUF0, 0x19, IRQL)

                       CreateByteField (BUF0, 0x1C, DMAV)

                       Return (BUF0)

                   }

                   Name (_PRS, ResourceTemplate ()

                   {

                       StartDependentFnNoPri ()

                       {

                           IO (Decode16,

                               0x03F2,             // Range Minimum

                               0x03F2,             // Range Maximum

                               0x00,               // Alignment

                               0x04,               // Length

                               )

                           IO (Decode16,

                               0x03F7,             // Range Minimum

                               0x03F7,             // Range Maximum

                               0x00,               // Alignment

                               0x01,               // Length

                               )

                           IRQNoFlags ()

                               {6}

                           DMA (Compatibility, NotBusMaster, Transfer8, )

                               {2}

                       }

                       EndDependentFn ()

                   })

                   Method (_SRS, 1, NotSerialized)

                   {

                       CreateByteField (Arg0, 0x02, IOLO)

                       CreateByteField (Arg0, 0x03, IOHI)

                       CreateWordField (Arg0, 0x19, IRQL)

                       CreateByteField (Arg0, 0x1C, DMAV)

                       ENFG ()

                       Store (0xFC, CR20)

                       EXFG ()

                   }

               }


哈哈、有看沒有懂!再看PCI的(太多了!點這看吧)應該是Device (LNKx)那些吧?更看不懂了!頓時兩腿發軟......


FDD算是最早獲得解答的,搜尋Google後根據一位老外的說法,要將FDC0當中Method (_CRS, 0, NotSerialized)的

                       CreateByteField (BUF0, 0x19, IRQL)

                       CreateByteField (BUF0, 0x1C, DMAV)

改為

                       CreateByteField (BUF0, 0x11, IRQL)

                       CreateByteField (BUF0, 0x14, DMAV)

以及下面的Method (_SRS, 1, NotSerialized)當中

                       CreateWordField (Arg0, 0x19, IRQL)

                       CreateByteField (Arg0, 0x1C, DMAV)

改為

                       CreateWordField (BUF0, 0x11, IRQL)

                       CreateByteField (BUF0, 0x14, DMAV)


接著將改好的DSDT重新compile為AML掛回去......FDD正常了!(這下測試工作可省事了、不用為了靠網路傳檔來來回回啟用關閉ACPI。 沒辦法、我不會用vi,所有log檢視、DSDT的修改、AML的compile仍在Windows下進行 = = 稍後研究AX59Pro的DSDT時發現Aopen也早已對FDC0做同樣修正)。


跳過跳過再跳過(大約一週的時間 = =),無窮無盡的搜尋,由M$網站得知目前Windows ACPI限制BIOS本身經直接存取並嘗試操控系統硬體資源、FreeBSD應當也是有此限制--而本次的問題就是在MVP3C2的BIOS透過ACPI要取得ELCR的控制、結果FreeBSD就出事了(我也搞不清自己在說啥XD)。


接著以Abit NF7-S運作FreeBSD 7.0RC1測試,也是一切正常。顯然MVP3C2的ACPI確實有問題。問題是總不可能把K7的ACPI table套在K6頭上吧!更別說完全不同的廠商與晶片組!

總之又回到了原點、知道不能讓BIOS進行控制、但要如何修改迴避?比對眾家MVP3主機板BIOS、竟在Aopen AX59Pro的BIOS找到答案!


回到MVP3C2的DSDT,看看關於0x4D0、ELCR中斷暫存器的部分


    OperationRegion (ELCR, SystemIO, 0x04D0, 0x02)

    Field (ELCR, ByteAcc, NoLock, Preserve)

    {

       ELC1,   8,

       ELC2,   8

    }


找到了、AX59Pro的DSDT也找到了。再找找ELC1/ELC2,在PCI0/LNKx中,以DEVICE (LNKA)為例,原本MVP3C2的Method (_DIS, 0, NotSerialized)內容如下


                   Method (_DIS, 0, NotSerialized)

                   {

                       Store (0x01, Local3)

                       And (PIRA, 0xF0, Local1)

                       ShiftRight (Local1, 0x04, Local1)

                       Store (Local1, Local2)

                       If (LGreater (Local1, 0x07))

                       {

                           Subtract (Local1, 0x08, Local1)

                       }

                       ShiftLeft (Local3, Local1, Local3)

                       Not (Local3, Local3)

                       If (LGreater (Local2, 0x07))

                       {

                           And (ELC2, Local3, ELC2)

                       }

                       Else

                       {

                           If (LNotEqual (Local2, 0x00))

                           {

                               And (ELC1, Local3, ELC1)

                           }

                       }

                       And (PIRA, 0x0F, PIRA)

                   }

再看看AX59Pro的

                   Method (_DIS, 0, NotSerialized)

                   {

                                               And (PIRA, 0x0F, PIRA)

                   }


哇差那麼多!這部分跟NF7-S的DSDT相當相近!趕緊將MVP3C2的比照修改、上機測試......看看載入修正的AML所跑出的dmesg(FDC0正常運作錯誤訊息從缺!)


ACPI timer: 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 -> 10

Timecounter "ACPI-fast" frequency 3579545 Hz quality 1000

acpi_timer0: <24-bit timer at 3.579545MHz> port 0x4008-0x400b on acpi0

pci_link0:        Index  IRQ  Rtd  Ref  IRQs

 Initial Probe       0   15   N     0  3 4 5 7 9 10 11 12 14 15

 Validation          0   15   N     0  3 4 5 7 9 10 11 12 14 15

 After Disable       0  255   N     0  3 4 5 7 9 10 11 12 14 15

pci_link1:        Index  IRQ  Rtd  Ref  IRQs

 Initial Probe       0   10   N     0  3 4 5 7 9 10 11 12 14 15

 Validation          0   10   N     0  3 4 5 7 9 10 11 12 14 15

 After Disable       0  255   N     0  3 4 5 7 9 10 11 12 14 15

pci_link2:        Index  IRQ  Rtd  Ref  IRQs

 Initial Probe       0   12   N     0  3 4 5 7 9 10 11 12 14 15

 Validation          0   12   N     0  3 4 5 7 9 10 11 12 14 15

 After Disable       0  255   N     0  3 4 5 7 9 10 11 12 14 15

pci_link3:        Index  IRQ  Rtd  Ref  IRQs

 Initial Probe       0    5   N     0  3 4 5 7 9 10 11 12 14 15

 Validation          0    5   N     0  3 4 5 7 9 10 11 12 14 15

 After Disable       0  255   N     0  3 4 5 7 9 10 11 12 14 15


爽呼、不再發生ACPI read/write error!就算插上3張網卡都由FreeBSD正確控制也沒一張會watchdog timeout啦!


Aopen 工程師好樣的、最後的改版竟然已經改到這一步,AX59Pro同時也在DSDT中加入OS_敘述讓作業系統決定ACPI控制權,將過時的MVP3板子進一 部提升對WinXP ACPI相容性(FreeBSD也因此跟著受惠......更意外的是MVP3C2以及其他老主機板與現有OS ACPI衝突的因此雨露均霑 XD)


到此對於磐英MVP3C2與FreeBSD ACPI造成FDD與PCI裝置失效的處理算是告一段落、非MVP3的晶片組應當也是差不多的方式迴避BIOS直接存取中斷暫存器所造成的裝置失效問題(起碼看過NF7-S的DSDT也是如此)~


修改過的磐英MVP3C2 AML / BIOS可由此取得(擔心BIOS刷出毛病的可用掛載AML方式overide FreeBSD ACPI。不怕刷BIOS出問題想一勞永逸的就刷吧!記得備份!)


後記:

1. 過程當中、首先以1806版的BIOS修改、結果以CBROM重新打包後發生寫入錯誤、BIOS失效的情況(完蛋了、上哪弄ISA顯卡?)。幸好插上 SiS6326 PCI後可進入緊急救援畫面。救援模式重刷BIOS時必須先將BIOS檔改名為AWARDEXT.ROM才可正常回刷!

2.由於習慣Windows的工具、包含磁碟偵錯(HDDtune/HDDscan以及各廠商的HD diagnostic tool),打算將CF卡另搞分割區安裝WinPE以執行這類工具。

結果WinPE掛了!趕緊刷回原本BIOS、WinPE可正常執行!幾經週折,發現以iasl compile AML時不可採最佳化模式,需要以參數 -oa 取消最佳化。另外原本的ASL也存在error,若不想修正的情況下也需以參數 -f 強制compile(強制compile過程中的error並未造成稍後運作的顯著問題。不過在下的修正AML已將有問題的code一併修改)。

 

沒有留言:

張貼留言