Note: Use an xHCI debug port for Kernel debugging on Windows/Linux

xHCI 在Intel 平台已經是標準內建的功能,Intel 早期在EHCI 就有加入一個Debug Port 功能,但是基於 EHCI 的Host<->Client半雙工模式設計,它必須透過外部一個USB Device 去做Host/Target的資料交換,又EHCI Controller 上只有 Port 0 可以提供這個功能,變成硬體設計與使用設定上都相對複雜,所以只有相對少數的工程師會去使用這個功能,通常是開發Windows Kernel Driver 的才會需要。

而Intel 在發展XHCI 時,因為USB3 已經是TX/RX分離,所以這次規格變成可以直接兩個Host Port 對接, 一條USB 3 的Debug Cable 實際上就是把 USB 2.0 的 D+/D- 跟Power(VBUS) 斷掉, 然後把USB 3的SS TX/SS RX 交換而已
enter image description here

所以現在開發UEFI/Windows/Linux Kernel mode driver 都支援透過xHCI 的這個內建功能去做,不過有些外接的xHCI Host Controller 並沒有實作這個 DbC (Debug Capability Class)

Microsoft 關於Kernel Debug 的設定
Intel 關於Linux 的Kernel mode 設定 — 這已經併入Vanilla Kernel stream 的文件目錄了,可以看到Linux 下就是把它當tty用

廣告

Note: Vendor ACPI Driver on Windows

之前寫了一些 ACPI Driver 相關的紀錄, 最近看到USB Type C connector for Windows 10 如果不做PD State Machine,下面也需要ACPI Driver 去協調 MCU/EC 所以整理一下手上有的資料 順便重新整理一下網路上很多消失的檔案

ACPIDriver Vista — 這個是Microsoft 最早提供的文件,不過根據實際經驗應該Windows XP 就支援這些功能
ACPI in Vista — 這是早期 WinHEC 2006 的 Presatations
BIOS implement of UCSI — Intel 這是Intel 講如何實作USB Type C Connector System Interface

older WDM/DDK Sample from Windows 2000

這邊提供實際原始碼的實作內容

Older WDM driver implement – 實作了Customer GPIO Button/Indicator LED, 應該是 Intel 用來Demo MID (Mobile Internal Device)做的
Current WDF Driver implement for UCSI - 這就是Microsoft 實作UCSI 的參考Driver了 可以搭配Intel 文件跟 Microsoft 網站資料一起看

下面是想更了解UCSI可以參考的資料
https://www.usb.org/developers/presentations/  — 2017 USB Developer Days  in Taipei

Update:
Linux 下的實作也有 Intel 提交的標準
https://github.com/torvalds/linux/tree/master/drivers/usb/typec/ucsi
所以盡可能透過在使用ACPI/ASL implement 去做這個功能,這樣Windows/Linux 下都有inbox driver 不用另外提供特殊的 customization driver
不過要透過標準UCSI 有一個地方考慮的是成本, 標準UCSI 界面是由 ACPI + EC + PD Controller 構成的,需要付出比較多的成本,目前已經有一個新的方式透過提供軟體的TCPM 取代PD Controller 如下圖 這個架構仍然需要一個MCU 去控制Type C 的界面行為, 系統透過I2C之類的下PD Policy 的行為給MCU

TCPCx

ref. https://www.mail-archive.com/linux-usb@vger.kernel.org/msg92179.html

Note: CE for x86, SYSINTR_FIRMWARE, SYSINTR

SYSINTR_FIRMWARE 目前在WINCE 定義 在 $(WINCEROOT)\public\common\oak\inc\nkintr.h 內,
可以看到下面兩行, 所以實際的值等於 (0x10)

// SYSINTR_DEVICES is the base for any non-OAL system interrupts
#define SYSINTR_DEVICES 8

// SYSINTR_FIRMWARE is the base for any interrupts defined in the OAL
#define SYSINTR_FIRMWARE (SYSINTR_DEVICES+8)

於是乎 x86 的 Serial port 的 registry 關於 COM2 的設定如下, 其中 “SysIntr"=dword:13 ; 就是這樣來的 0x10(SYSINTR_FIRMWARE) + 3 (IRQ) = 0x13

Subkey Value Description
“SysIntr" dword:13 Hardware-platform-dependent. SYSINTR_FIRMWARE plus the IRQ.
“IoBase" dword:02F8 Hardware-platform-dependent base address of port-mapped I/O.
“IoLen" dword:8 Hardware-platform-dependent I/O space mapping to a virtual address in a memory-mapped I/O system. Notifies the system how much larger the address window is.
“DeviceArrayIndex" dword:0 Serial port that the driver manages. This key specifies the serial adapter that the driver manages. It also specifies the object to use inside the driver DLL. It is only useful for multi-object drivers, such as serial drivers, built-in drivers, and so on. You cannot use this key for single object drivers.
“Prefix" “COM" Entry point prefix. The entry point is constructed from the Prefix value and the name of the entry point. If the driver exposes the stream interface with undecorated entry points, no Prefix value exists.
“Dll" “Serial.Dll" DLL loaded by the bus enumerator.
“Order" dword:0 Value between zero (0) and 255. The smallest Order value gets loaded first. If there is no Ordervalue, the driver loads after drivers with defined Orders.

不過關鍵原因應該是 x86 的 BOOL OALIntrInit (void) 把他寫死了

這個函式定義在 $(WINCEROOT)\platform\common\src\x86\common\intr\init.c
不過 Adeneo Embedded 的BSP 實際上有 overwrite 在 $(WINCEROOT)\platform\INTEL_CS\SRC\COMMON\PDQOAL\intr\init.c

// Serial Port Info
//
// The legacy COM port layout defines IRQ4 being shared by
// COM ports 1 and 3 and IRQ3 is shared COM ports 2 and 4.
// If the legacy IRQ layout is followed, only 1 COM port
// per IRQ should be enabled.
//
// COM1 – 0x3F8-0x3FF, IRQ4
// COM2 – 0x2F8-0x3FF, IRQ3
// COM3 – 0x3E8-0x3EF, IRQ4
// COM4 – 0x2E8-0x2EF, IRQ3
//
// IRQ3 – COM2 or COM4
OALIntrStaticTranslate(SYSINTR_FIRMWARE + 3, 3);

// IRQ4 – COM1 or COM3
OALIntrStaticTranslate(SYSINTR_FIRMWARE + 4, 4);


https://msdn.microsoft.com/en-us/library/ee484687(v=winembedded.70).aspx

Touch Driver Architecture change on Windows Embedded Compact 7

這幾天又開始轉弄WINCE OS 的porting, 這次的任務是在 CedarTrail 上要 跑 WEC7, BSP 還是使用 Adeneo Embedded 所提供的, 根據前兩年做過的經驗, 很快就 Booting 成功了, Azalia Audio codec 這次換成 ALC269, 也稍微改一下就正常工作了,

但本來不預期會出意外的Touch Controller 卻不會動, 經過一早努力才發現, 原來 WEC7 把Touch Driver 的結構修改過了, 從以前單純的 PDD/MDD 結構, 又更一步把介面抽象化, 分成了 Touch Proxy 與 Touch Driver, Touch Driver 現在改成標準的 Steram Driver(但是還維持PDD/MDD結構) 更上層與系統GWES介面的改成單純由 Touch Proxy Driver 負責. 詳細的內容請參考MSDN 上的 Touch Driver Architecture 因應這個修改 Registry 需相應修改

Work Note:Modify Resource in WinCE

這篇一定要寫下來, 不然可能下次要搞又要弄好久 T_T

  1. 首先用 ResHacker, extract 需要改語系的 XXX.RES (英文除外, 因為該死的微軟已經提供了0409語系的 .RC) 到某個Folder, 假設他叫作 XXX.RC
  2. 編輯剛剛得到的 XXX.RC檔案, 首先加上 #include <windows.h>
  3. 打開build window, 切換到該目錄 打 rc.exe /i%_PUBLICROOT%\common\sdk\inc /n XXX.rc 看看有沒有問題, 如果有問題通常是 HOTKEY 那邊 VK_A, VK_B, VK_C, 直接改成 “A", “B", “C" 即可! (/n 是重點, 因為WinCE內的程式基本上假定Resource 本身是C string type)
  4. 看看是否需要合併多個以上的.RES 為一個 透過 res2res.exe XXX.res yyy.res /fo zzz.res, 這樣就可以得到最終 zzz.res
  5. 將所需的 zzz.res 擺到 %_TARGETPLATROOT%\FILES\<LANGID> 下面, 這樣當Build script 跑到 “Copy Files to Release directory" 時, 會正確的覆蓋WINCE prebuilt 的 zzz.res, 這樣當makeimg 時, 就會正確連結修改過的 .RES了

WorkNote: a Debug message dump, Intel N450 with WEC7 Platform

Keypoint:
1. ACPI provide RAM size to CE kernel.
2. Due to Original code just discover ‘zero’ codec, so the InitHDA() always return failed. And the DiscoverCodec() still have a little bug,  so you need to patch it! May be still need added your codec ID into CheckcodecFG().

Debug Serial Init

SysInit: GDTBase=82acb000 IDTBase=82acf700 KData=82a85800
Windows CE Kernel for i486
INFO:OALLogSetZones: dpCurSettings.ulZoneMask: 0xb
PCIInitConfigMechanism():ucConfigMechanism 0x1
InitKitlNIC: Searching for PCI Ethernet NIC (dwIrq = 0, dwIoBase = 0, dwDfltType = 0) …
Intel(R) Ethernet Gigabit KITL driver [Build: Apr  9 2012  14:34:00]
InitKitlNIC: skipping unknown PCI Ethernet NIC: (subclass=0, Vendor=10EC, Device=8168)
Intel(R) Ethernet Gigabit KITL driver [Build: Apr  9 2012  14:34:00]
InitKitlNIC: skipping unknown PCI Ethernet NIC: (subclass=0, Vendor=10EC, Device=8168)
Intel(R) Ethernet Gigabit KITL driver [Build: Apr  9 2012  14:34:00]
InitKitlNIC: skipping unknown PCI Ethernet NIC: (subclass=0, Vendor=10EC, Device=8168)
Intel(R) Ethernet Gigabit KITL driver [Build: Apr  9 2012  14:34:00]
InitKitlNIC: skipping unknown PCI Ethernet NIC: (subclass=0, Vendor=10EC, Device=8168)
 x86InitMemory(): dwAcpiPHYS = 0x3F5CD627
x86InitMemory(): dwRamEndPHYS = 0x20000000
x86InitMemory(): dwRamTop(1)= 0xc0000000
Using ACPI location to determine RAM size
ACPI Tables found at 0x3f5cd627
RAM reported to kernel 1013MB
x86InitMemory():g_pOemGlobal->dwMainMemoryEndAddress = 0xa0000000
Found ACPI but it was located above 512MB at 1013MBIDE deviceId = 0x2828

disLegacyUsbSupport LPC deviceId=0x2815 PMBase=0x1000
+ disLegacyUsbSupport for ICH8M
– disLegacyUsbSupport for ICH8M

PID:00400002 TID:00410002  Found ACPI but it was located above 512MB at 1013MBReserve KITL IRQ: No IRQ reserved, KITL polling mode was specified
PID:00400002 TID:00510002 WARNING: COM1: has been reserved exclusively for Debug Messages.VBridge:: VB_INITIALIZED returns [0]
PID:00400002 TID:00A40006 HDA::InitHardware: InitHDA() failed