schedule_int_transfer 第 6 形参原为 toggle_ptr: uint8*,却直接转发给 _td_set_token 的值形参 toggle: uint8,命中指针隐式转整数禁令(uhci.vp:160 CastError)。改为 toggle: uint8 值传递,四个调用点去掉取地址,buf 仍以 & 传。同时纳入工作区既有的指针语法迁移:t.CPtr 改 X*、c.Addr 改 &、c.Set(c.Deref(...)) 改 *p = v。
94 lines
3.4 KiB
Plaintext
94 lines
3.4 KiB
Plaintext
import t, c
|
|
import asm
|
|
|
|
|
|
define PCI_CONFIG_ADDR = 0xCF8
|
|
define PCI_CONFIG_DATA = 0xCFC
|
|
|
|
define PCI_CLASS_SERIAL_USB = 0x0C03
|
|
define PCI_CLASS_SERIAL_UHCI = 0x0C0300
|
|
define PCI_CLASS_SERIAL_OHCI = 0x0C0310
|
|
define PCI_CLASS_SERIAL_EHCI = 0x0C0320
|
|
define PCI_CLASS_SERIAL_XHCI = 0x0C0330
|
|
|
|
define PCI_CMD_IO_SPACE = 0x0001
|
|
define PCI_CMD_BUS_MASTER = 0x0004
|
|
|
|
class pci_device:
|
|
bus: uint8
|
|
dev: uint8
|
|
func: uint8
|
|
vendor_id: uint16
|
|
device_id: uint16
|
|
class_code: uint32
|
|
irq: uint8
|
|
bar: [6]uint32
|
|
|
|
def pci_read32(bus: uint8, dev: uint8, func: uint8, offset: uint8) -> uint32:
|
|
addr: uint32 = 0x80000000 | (uint32(bus) << 16) | (uint32(dev) << 11) | (uint32(func) << 8) | (uint32(offset) & 0xFC)
|
|
asm.outl(PCI_CONFIG_ADDR, addr)
|
|
return asm.inl(PCI_CONFIG_DATA)
|
|
|
|
def pci_write32(bus: uint8, dev: uint8, func: uint8, offset: uint8, value: uint32):
|
|
addr: uint32 = 0x80000000 | (uint32(bus) << 16) | (uint32(dev) << 11) | (uint32(func) << 8) | (uint32(offset) & 0xFC)
|
|
asm.outl(PCI_CONFIG_ADDR, addr)
|
|
asm.outl(PCI_CONFIG_DATA, value)
|
|
|
|
def pci_read16(bus: uint8, dev: uint8, func: uint8, offset: uint8) -> uint16:
|
|
val: uint32 = pci_read32(bus, dev, func, offset)
|
|
shift: uint32 = (uint32(offset) & 0x02) * 8
|
|
return uint16((val >> shift) & 0xFFFF)
|
|
|
|
def pci_read8(bus: uint8, dev: uint8, func: uint8, offset: uint8) -> uint8:
|
|
val: uint32 = pci_read32(bus, dev, func, offset)
|
|
shift: uint32 = (uint32(offset) & 0x03) * 8
|
|
return uint8((val >> shift) & 0xFF)
|
|
|
|
def pci_get_class(bus: uint8, dev: uint8, func: uint8) -> uint32:
|
|
cls: uint8 = pci_read8(bus, dev, func, 0x0B)
|
|
sub: uint8 = pci_read8(bus, dev, func, 0x0A)
|
|
proto: uint8 = pci_read8(bus, dev, func, 0x09)
|
|
return (uint32(cls) << 16) | (uint32(sub) << 8) | uint32(proto)
|
|
|
|
def pci_get_bar(bus: uint8, dev: uint8, func: uint8, bar_idx: uint8) -> uint32:
|
|
return pci_read32(bus, dev, func, 0x10 + bar_idx * 4)
|
|
|
|
def pci_enable_device(dev: pci_device*):
|
|
cmd: uint16 = pci_read16(dev.bus, dev.dev, dev.func, 0x04)
|
|
cmd = cmd | PCI_CMD_IO_SPACE | PCI_CMD_BUS_MASTER
|
|
pci_write32(dev.bus, dev.dev, dev.func, 0x04, uint32(cmd))
|
|
|
|
def pci_fill_device(bus: uint8, dev_n: uint8, func: uint8, out: pci_device*):
|
|
out.bus = bus
|
|
out.dev = dev_n
|
|
out.func = func
|
|
out.vendor_id = pci_read16(bus, dev_n, func, 0x00)
|
|
out.device_id = pci_read16(bus, dev_n, func, 0x02)
|
|
out.class_code = pci_get_class(bus, dev_n, func)
|
|
out.irq = pci_read8(bus, dev_n, func, 0x3C)
|
|
for i in range(6):
|
|
out.bar[i] = pci_get_bar(bus, dev_n, func, uint8(i))
|
|
|
|
_uhci_dev: pci_device
|
|
_uhci_found: int = 0
|
|
|
|
def find_uhci() -> uint16:
|
|
global _uhci_dev, _uhci_found
|
|
bus: uint8
|
|
dev_n: uint8
|
|
func: uint8
|
|
for bus in range(1):
|
|
for dev_n in range(32):
|
|
for func in range(8):
|
|
vendor: uint16 = pci_read16(bus, dev_n, func, 0x00)
|
|
if vendor == 0xFFFF: continue
|
|
cls: uint32 = pci_get_class(bus, dev_n, func)
|
|
if cls == PCI_CLASS_SERIAL_UHCI:
|
|
pci_fill_device(bus, dev_n, func, &_uhci_dev)
|
|
pci_enable_device(&_uhci_dev)
|
|
_uhci_found = 1
|
|
bar: uint32 = _uhci_dev.bar[4]
|
|
io_base: uint16 = uint16(bar & 0xFFFE)
|
|
return io_base
|
|
return 0
|