2018年9月20日 星期四

[轉貼 | 備份] PCI Read/Write 0xcf8 0xcfc

出處
http://blog.xuite.net/huaanvgs/blog/137026031-PCI+Read%2FWrite


20204PCI
    BIOS入門的第一課大部分都會遇到PCI的作業,前輩們往往都會出個簡單的作業,要求我們去讀寫PCI configuaration space,到底我們該如何去做呢?
    根據PCI Local Bus Specification 3.0有提到,"Every device, other than host bus bridges, must implement Configuration Address Space. Host bus bridges may optionally implement Configuration Address Space. In the Configuration Address Space, each function is assigned a unique 256-byte space that is accessed differently than I/O or Memory Address Spaces"
    也就是說讀寫PCI的方式有兩種,一種是透過I/O(CF8/CFC)而另一種則是利用MMIO的方式來去讀寫PCI configuration space.
    在介紹這兩種讀寫方法以前,我們先來看PCI spec.如何定義Configuration commands。為了支援階層式的PCI buses,在此使用兩種類型的configuration transactions,如Figure 1所示。

Figure 1
在Figure 1中我們可以看到兩種不同的configuration commands,分別為Type0Type1,其中
    Type0: A Type 0 configuration transaction (when AD[1::0] = “00”) is used to select a device on the bus where the transaction is being run.
    Type1: A Type 1 configuration transaction (when AD[1::0] = “01”) is used to pass a configuration request to another bus segment.
    而IDSEL(Initialization Device Select)是指"it used as a chip select during configuration
read and write transactions." 這部分會連接到PCI AD[31:11],是由硬體拉線所決定的。
    其中IDSEL可以辨別PCI的身分,當硬體解出來的configuration cycle為Type0時,會做以下兩件事:1.遮罩[31:11],2.解碼Device number。相反的,當硬體解出的configuration cycle為Type1時,他會做以下的事:1.當bus number和secondary bus number一致時,會將Type1轉成Type0,也就是Bit0設為1,並做Type0該做的事;當bus number和secondary bus number不一致時,則會往下一層送。
    透過IDSEL辨別Type0和Type1的方式,我們可以完成PCI的Scan,但在Type0的configuration transactions中好像沒有定義Bus number與Devce number,那麼如何去做transactions呢?還記得Type0的定義,他是在相同的bus下去選擇device,而device number我們又可以透過解碼的方式去獲得,因此就不會有找不到的問題。

Software Generation of Configuration Transactions
    系統必須提供一種機制來讓軟體有辦法去Access PCI configuration space,前面有提到可以透過I/O space及MMIO space的方式去存取,但PCI device還沒分配resource之前,還是只能透過I/O space的方式去access。
 "Two DWORD I/O locations are used to generate configuration transactions for PC-AT compatible systems. The first DWORD location (CF8h) references a read/write register that is named CONFIG_ADDRESS. The second DWORD address (CFCh) references a read/write register named CONFIG_DATA."
    Figure 2為針對CONFIG_ADDRESS所定義的Layout,其中:

Figure 2 
where
Bit[31]: It is an enable flag for determining when accesses to CONFIG_DATA are to be translated to configuration transactions on the PCI bus.
Bit[30:24]: Reserved
Bit[23:16]: Bits 23 through 16 choose a specific PCI bus in the system.
Bit[15:11]: Bits 15 through 11 choose a specific device on the bus.
Bit[10:8]: Bits 10 through 8 choose a specific function in a device.
Bit[7:2]: Bits 7 through 2 choose a DWORD in the device's Configuration Space.
Bit[1:0]: Bits 1 and 0 are read-only and must return 0's when read.

    由上面定義可以得知最多支援的Bus number為256(2的8次方),最多支援的device number為32(2的5次方),最多支援的function number為8(2的3次方),可以讀取的configuration space為256(2的8次方),速記為8538
    看到這邊,或許會對configuration space有疑問,在Figure 2不是只有用Bit[7:2]去定義嗎,為什麼可以讀到256個呢?這是因為上面定義Bit[1:0]在Read的時候必須是0,所以如果我們要去Read/Write的space剛好在Bit[1:0]不為0的時候只能利用偏移的方式去做讀取,我們之後會有一個小小的範例做說明。
    接著我們看這兩種Type的configuration commands如何與SW做結合。

Figure 3

     自Figure 3我們可以看到,假設IDSEL辨別為Type0,自然就知道Bus number,而device number可以透過解碼方式獲得,並填到Bit[31:11]中的其中一個,剩下的Function number和Register number則複製到PCI AD BUS當中。
    如果IDSEL辨別為Type1,則是將CONFIG_ADDRESS全部複製到PCI AD line當中,當然Bit0也必須是1。

PCI R/W sample:
參考Figure 4,如下:

Figure 4
    如圖Figure 所示,假設我們要讀取Bus00, Dev1B,Fun00的Offset3C(Interrupt Line),那麼我們應該如何做呢?步驟描述如下:
Step1:
          我們知道透過I/O space(CF8/CFC)可以Read/Write Configuration space,其中把要讀取該Space的PFA填入Config_Address(CF8)後,在Config_Data(CFC)就可以得到該資料。
Step2:
          有了步驟1的知識後,我們要先計算出PFA,回顧Figure 2所示,我們必須將要讀取的BUS,Dev,Fun及Offset填入Config_Address所對應的Layout,其中Bit31必須為1,Bit[1:0]必須為0(如果剛好不為0可以用偏移方式讀取),其分析如下:
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2   1  0
 1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  0  1  1  0  0  0  0  0  1  1  1  1  0  0

PFA = 8000D83C h
    以Tool RW來示範的話就是利用I/O CF8填入PFA,然後在CFC的Offset 00h可以得到Interrupt Line的值16h,如圖Figure 5所示。

Figure 5

如果用組合語言來表示我們可以描述如下:
mov dx, cf8h
mov eax, 8000d83ch (PFA)
out dx, eax
mov dx, cfch
in eax, dx
如此,我們可以在EAX的Offset 00h得到我們要讀取的值。

2018年9月18日 星期二

[ 轉貼 | 備份] Blogger 變更字型,更換中文字型如:微軟正黑體、標楷體

出處
https://www.xiaoyao.tw/2017/07/blogger-font.html

備份

Blogger 筆記:網頁中文字型變更為正黑體或標楷體。

使用 Blogger 主題設計工具可以設定部落格版面各項字型,網站標題、文章標題、文章內容、側邊欄工具、、等等,每個項目都可逐一設定大小顏色與字體。只是預設的字型並沒有中文字型可以選擇,不管挑選哪種字型,變化的都是英文跟數字的部分,中文字始終顯示新細明體。想要更換部落格中文字體,可以編輯 HTML 添加喜歡的字型上去。



操作說明:
(編輯HTML前先備份範本,備份說明)




Blogger 管理後台「主題」→「自訂」開啟主題設計工具,可修改部落格主題。


「主題設計工具」→「進階」可調整文字字型、大小、顏色。


想要使用 Blogger 預設以外的字型,「編輯 HTML」將字型加入主題。


編輯 HTML:點擊第一個箭頭處,將隱藏的段落展開(行數不一定,依主題修改程度有所差異)。


Variable definitions:定義各項設定值,Page Text:網頁文字。


body.font:文章內文字型。


Variable name="body.font" description="Font" type="font"
default="normal normal 15px Arial, Tahoma, Helvetica, FreeSans, sans-serif" value="normal normal 15px 'Trebuchet MS',Trebuchet,sans-serif"


上段指令中「default」預設使用字型;「value」指定使用字型。將字型添加到 「value」段落中 15px (字體大小)後面。修改後如下:

Variable name="body.font" description="Font" type="font"
default="normal normal 15px Arial, Tahoma, Helvetica, FreeSans, sans-serif" value="normal normal 15px Arial, '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei', 'sans-serif'


其中「’文泉驛正黑’」=「’WenQuanYi Zen Hei’」,中文與英文表示方式都使用,因電腦系統若是英文會無法使用「文泉驛正黑」。同時添加多種字型,會按照順位依序替補,若觀看網頁的電腦無法使用第一種則使用第二順位。「sans-serif」則是通用字型.所有電腦都會有的。

字型若只有一個單字;如「Arial」;不需要加上單引號「’ ’」。兩個單字以上就須加上單引號;如:「’WenQuanYi Zen Hei’」「’文泉驛正黑’」。單引號在編輯 HTML 儲存後則顯示「& # 3 9 ;」字串。(如下圖)


這篇主要紀錄編輯 HTML 增加中文字型所學的,以備將來恢復記憶使用。若文章中有說明不清楚或是想瞭解更多,請參考下列文章。

參考文章:
修改各處 CSS(文章標題+內文+其他),以字型大小顏色舉例
網頁中英文字型(font-family)跨平台設定最佳化
打造部落格(一):讓版面更容易閱讀的幾個調整方案