在下鄙人我為了省錢、打算用一套老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一併修改)。