【我所認知的BIOS】—>SPD
2019-04-14 16:14发布
生成海报
【我所認知的BIOS】—>SPD
By LightSeed
2009-7-22
1、什麼是 SPD?
存在SPD是Serial Presence Detect的縮寫,中文意思是模組存在的串列檢測。也即是通過上面講的I2C串列介面的EEPROM堆記憶體插槽中的模組存在的資訊檢查。這樣的話,模組有關的資訊都必須紀錄在EEPROM中。習慣的,我們把這顆EEPROM IC就稱為SPD了。以往開機時BIOS必須偵測memory,但有了SPD就不必再去作偵測的動作,而由BIOS直接讀取 SPD取得記憶體的相關資料。那我們來看看事物的SPD吧,先看我們的SPD位於記憶體的哪個部位,比如說圖1中紅線框住的地方就是SPD。然後我們再放大來看看我們的SPD,比如說其他記憶體上的SPD放大圖見圖2.
圖1 記憶體的實物圖
圖2 SPD放大圖
2、SPD內容
SPD是一組關於記憶體模組的配置資訊,如P-Bank數量、電壓、行位址/列地址數量、位寬、各種主要操作時序(如CL、tRCD、tRP、tRAS等)……它們存放在一個容量為256位元組的EEPROM(Electrically Erasable Programmable Read Only Memory,電擦除可編程唯讀記憶體)中。讓我們來看看SPD的spec的一個截圖,見圖3。
圖3 SPD的內容截圖
實際上在SPD中,JEDEC規定的標準資訊只用了128個位元組(還有128位元組,屬於廠商自己的專用區)。一般的,一個位元組至少對應一種參數,有的參數需要多個位元組來表述(如產品續列號,生產商在JEDEC組織中的代碼)。
其中,一個位元組中的每個bit都可能用來表示這一參數的具體數值。由於SPD的資訊很多,在此就不一一列出了,有興趣的讀者可以參閱相關文檔。
3、SPD的作用
SPD內的時序資訊由模組生產商根據所使用的記憶體晶片的特點編寫並寫入至EEPROM,主要用途就是協助北橋晶片精確調整記憶體的物理/時序參數,以達到最佳的使用效果。如果在BIOS中將記憶體設置選項定為“By SPD”。那麼在開機時,北橋會根據SPD中的參數資訊來自動配置相應的記憶體時序與控制寄存器,避免人為出現調校錯誤而引起故障。當然,對於DIYer來說,也可以自由調整時序與控制參數(物理參數仍要借助SPD或北橋自己檢測來確定)。前面所說的 “by SPD”在AWXXX的setup介面就會出現了。
上面這三部分,主要是參考百度里的資訊,另外加了自己的截圖等等。
4、讀取SPD(read by byte的實戰)
既然SPD裏面存儲有這麼重要的資訊,而且又和整個系統有這麼密切關係,那麼我們應該怎麼讀取出來呢?
關於SPD裏的資訊,要讀取它的話就要說到上一章講的SMBUS的操作了。因為SPD是通過SMBUS來讀取的。在這裏我把主要的讀取演算法寫出來,然後加注我想就可以了。因為如果能夠有心情看這篇文章的人,我想也應該對BIOS有一定興趣的,那麼自己再加點週邊的code肯定是不成問題的啦。
通過SMBUS來讀取SPD大約要有這麼幾個重要的步驟要去做。但是我們要首先明確是以什麼的方式去讀取呢?因為SMBUS的讀取可以分read by byte,read by word和read by block。不過現在我們從read by byte開始說起。
①通過遍曆PCI設備,比較class code來找到SMbus controller的base address。這個base address我們可以參考ICH6的datasheet的相關說明。(當然只要是ICH系列的datasheet都是可以查閱的。)它代表了SMBUS的system I/O base address。也就是前面我們提到的SMBUS的IO埠。(因為我們都要通過這些IO來實現我們動作比如說read、write等等。關於怎麼在我們的板子上獲取這個base address,如果您有興趣可以參考我的好友peterhu的blog“戲說BIOS之clock generator”裏有相應的程式操作。)
②根據SMBUS的協定,我們要先向controller的offset 04h也就是(Transmit Slave Address)發送slave address。然後等帶這個SMBUS準備ok。
③以上兩步ok了以後,我們就可以讀取相應的寄存器了。這是向controller的Host Command(0ffset 03h)發的命令。內容就是對應的寄存器index就ok了。
④有了上面的準備,那麼我們就準備給controller說開始讀取資料吧,這個動作是通過向Host Control(offset 02h)發送讀取的命令48h。(如果不太清楚就自己對應到ICH的datasheet詳細看看是什麼意思。)
⑤經過SMbus準備好了以後,我們就可以從data0這個埠取得我們需要的資料了(offset 05h)。
如果想要把SPD的內容(128個bytes)一下子全部讀出來,那麼就直接用加了迴圈就ok了,迴圈②~⑤。
溫馨提示,在通過SMBUS controller來讀取SPD的內容的時候,一定要去等待SMBUS準備ok才能去讀或者其他操作哦。只需要一直去判斷狀態位元就好了。
下面我提供一段核心代碼,希望以此抛磚引玉的效果,當然我也是參考了別人的代碼:
;[]============================[]
;Input : CL - register index
; CH - device ID
;Output : AL - Value read
;[]============================[]
Smbus_ReadByte Proc Near
Push cx ;保存cx
mov dx,05000h ;SMBus Base address,在我的機器上的
mov dl,04h ;選擇Transmit Slave Address
or ch,01h ;read 讀
mov al,ch ;ID cmd(read)
out dx,al
IODELAY
call Chk_SMBus_Ready ;如SMbus不ok就一直停在這裏,直到超過規定的時間,如果SMbus還不ok那麼就報錯。
pop ax ;恢復cx到ax中
mov dl,03h ;選擇Host Command Register
out dx,al ;把要讀取的寄存器index送出去
IODELAY
mov dl,02h ;選擇Host Control Register
mov al,48h ;下命令開始讀取by Byte Data:
out dx,al ;Read data
IODELAY
mov cx, 100h
@@:
IODELAY
loop short @B ;這裏這個迴圈是為了讓smbus準備好而加的延時
call Chk_SMBus_Ready
mov dl,05 ;選擇Host Data 0 Register
in al,dx ;Data0
IODELAY
ret
Smbus_ReadByte Endp
讀取的顯示效果如圖4
圖4 以byte形式讀取的SPD顯示截圖
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮