From aee4947669b8313970af22c9b89c05fd47347d7c Mon Sep 17 00:00:00 2001 From: aaron <aaron@6dbc8c32-bb84-406f-8558-d1cf31a0ab0c> Date: Fri, 6 Apr 2018 12:36:27 +0000 Subject: [PATCH] git-svn-id: https://spexeah.com:8443/svn/Asuro@367 6dbc8c32-bb84-406f-8558-d1cf31a0ab0c --- src/driver/PCI.pas | 364 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 src/driver/PCI.pas diff --git a/src/driver/PCI.pas b/src/driver/PCI.pas new file mode 100644 index 00000000..ed91020c --- /dev/null +++ b/src/driver/PCI.pas @@ -0,0 +1,364 @@ +{ ************************************************ + * Asuro + * Unit: Drivers/PCI + * Description: PCI Driver + ************************************************ + * Author: Aaron Hance + * Contributors: + ************************************************ } + +unit PCI; + +interface + +uses + util, + console, + drivertypes, + lmemorymanager, + drivermanagement; + +type + + TPCI_Device_Bridge = bitpacked record + device_id : uint16; + vendor_id : uint16; + status : uint16; + command : uint16; + class_code : uint8; + subclass_class : uint8; + prog_if : uint8; + revision_id : uint8; + BIST : uint8; + header_type : uint8; + latency_timer : uint8; + cache_size : uint8; + address0 : uint32; + address1 : uint32; + latency_timer2 : uint8; + subordinate_bus : uint8; + secondery_bus : uint8; + primary_bus : uint8; + secondery_status : uint16; + io_limit : uint8; + io_base : uint8; + memory_limit : uint16; + memory_base : uint16; + pref_memory_limit : uint16; + pref_memory_base : uint16; + pref_base_upper : uint32; + pref_limit_upper : uint32; + io_limit_upper : uint16; + io_base_upper : uint16; + reserved : uint16; + reserved0 : uint8; + capability_pointer : uint8; + epx_rom_addr : uint32; + bridge_control : uint16; + interrupt_pin : uint8; + interrupt_line : uint8; + end; + +var + devices : array[0..1024] of TPCI_Device; + busses : array[0..256] of TPCI_Device_Bridge; + + device_count : uint16; + bus_count : uint8 = 1; + get_device_count : uint8; + +procedure init(); +procedure scanBus(bus : uint8); +function loadDeviceConfig(bus : uint8; slot : uint8; func : uint8) : boolean; +function getDeviceInfo(class_code : uint8; subclass_code : uint8; prog_if : uint8; var count : uint32) : TdeviceArray; //(Will in future)returns TPCI_DEVICE.vendor_id := 0xFFFF if no device found. + +implementation + +function load(ptr : void) : boolean; +var + current_bus : uint8; + +begin + console.writestringln('PCI: Scanning Bus: 0'); + scanBus(0); + //while unscanned busses scan busses + current_bus := 1; + while true do begin + if current_bus < bus_count then begin + console.writestringln('PCI: Scanning Bus: '); + console.writeint(bus_count); + scanBus(current_bus); + current_bus := current_bus + 1; + end else break; + end; + load:= true; +end; + +procedure init(); +var + DevID : TDeviceIdentifier; + +begin + console.writestringln('PCI: INIT BEGIN.'); + DevID.Bus:= biUnknown; + DevID.id0:= 0; + DevID.id1:= 0; + DevID.id2:= 0; + DevID.id3:= 0; + DevID.ex:= nil; + drivermanagement.register_driver_ex('PCI Driver', @DevID, @load, true); + console.writestringln('PCI: INIT END.'); +end; + +procedure scanBus(bus : uint8); +var + slot : uint16; + func : uint16; + result : boolean; + +begin + for slot := 0 to 31 do begin + result := loadDeviceConfig(bus, slot, 0); + if result = true then begin + if devices[device_count - 1].header_type and $40 = 40 then begin + for func := 1 to 8 do begin + loadDeviceConfig(bus, slot, func); + psleep(1000); + end; + end; + end; + end; +end; + +procedure requestConfig(bus : uint8; slot : uint8; func : uint8; row : uint8); +var + packet : uint32; + +begin + packet := ($1 shl 31); + packet := packet or (bus shl 16); + packet := packet or ((slot) shl 11); + packet := packet or ((func) shl 8); + packet := packet or ((row) shl 2); + + outl($CF8, uint32(packet)); +end; + +procedure loadBusConfig(bus : uint8; slot : uint8; func : uint8; device : TPCI_Device); +var + busT : TPCI_Device_Bridge; + data : uint32; + +begin + + busT.device_id := device.device_id; + busT.vendor_id := device.vendor_id; + busT.status := device.status; + busT.command := device.command; + busT.class_code := device.class_code; + busT.subclass_class := device.subclass_class; + busT.prog_if := device.prog_if; + busT.revision_id := device.revision_id; + busT.BIST := device.BIST; + busT.header_type := device.header_type; + busT.latency_timer := device.latency_timer; + busT.cache_size := device.cache_size; + + requestConfig(bus, slot, func, 4); + busT.address0 := inl($CFC); + requestConfig(bus, slot, func, 5); + busT.address1 := inl($CFC); + + requestConfig(bus, slot, func, 6); + data := inl($CFC); + busT.latency_timer2 := getbyte(data, 0); + busT.subordinate_bus := getbyte(data, 1); + busT.secondery_bus := getbyte(data, 2); + busT.primary_bus := getbyte(data, 3); + + requestConfig(bus, slot, func, 7); + data := inl($CFC); + busT.secondery_status := getword(data, false); + busT.io_limit := getbyte(data, 2); + busT.io_base := getbyte(data, 3); + + requestConfig(bus, slot, func, 8); + data := inl($CFC); + busT.memory_limit := getword(data, false); + busT.memory_base := getword(data, true); + + requestConfig(bus, slot, func, 9); + data := inl($CFC); + busT.pref_memory_limit := getword(data, false); + busT.pref_memory_base := getword(data, true); + + requestConfig(bus, slot, func, 10); + busT.pref_base_upper := inl($CFC); + requestConfig(bus, slot, func, 11); + busT.pref_limit_upper := inl($CFC); + + requestConfig(bus, slot, func, 11); + data := inl($CFC); + busT.io_limit_upper := getword(data, false); + busT.io_base_upper := getword(data, true); + + requestConfig(bus, slot, func, 12); + data := inl($CFC); + busT.reserved := getword(data, false); + busT.reserved0 := getbyte(data, 2); + busT.capability_pointer := getbyte(data, 3); + + requestConfig(bus, slot, func, 13); + busT.epx_rom_addr := inl($CFC); + + requestConfig(bus, slot, func, 14); + data := inl($CFC); + busT.bridge_control := getword(data, false); + busT.interrupt_pin := getbyte(data, 2); + busT.interrupt_line := getbyte(data, 3); + + busses[bus_count] := busT; + bus_count := bus_count + 1; + +end; + +function loadDeviceConfig(bus : uint8; slot : uint8; func : uint8) : boolean; +var + device : TPCI_Device; + data : uint32; + DevID : PDeviceIdentifier; + +begin + + loadDeviceConfig := false; + + requestConfig(bus, slot, func, 0); + data := inl($CFC); + device.device_id := getword(data, false); + device.vendor_id := getword(data, true); + + if device.vendor_id = $FFFF then exit; + + requestConfig(bus, slot, func, 1); + data := inl($CFC); + device.status := getword(data, false); + device.command := getword(data, true); + + requestConfig(bus, slot, func, 2); + data := inl($CFC); + device.class_code := getbyte(data, 3); + device.subclass_class := getbyte(data, 2); + device.prog_if := getbyte(data, 1); + device.revision_id := getbyte(data, 0); + + requestConfig(bus, slot, func, 3); + data := inl($CFC); + device.BIST := getbyte(data, 3); + device.header_type := getbyte(data, 2); + device.latency_timer := getbyte(data, 1); + device.cache_size := getbyte(data, 0); + + if device.header_type and $7 = 0 then begin + loadDeviceConfig := true; + end else begin + loadBusConfig(bus, slot, func, device); + exit(false); + end; + //TODO implement other types? + + requestConfig(bus, slot, func, 4); + device.address0 := inl($CFC); + requestConfig(bus, slot, func, 5); + device.address1 := inl($CFC); + requestConfig(bus, slot, func, 6); + device.address2 := inl($CFC); + requestConfig(bus, slot, func, 7); + device.address3 := inl($CFC); + requestConfig(bus, slot, func, 8); + device.address4 := inl($CFC); + requestConfig(bus, slot, func, 9); + device.address5 := inl($CFC); + + requestConfig(bus, slot, func, 10); + device.CIS_Pointer := inl($CFC); + + requestConfig(bus, slot, func, 11); + data := inl($CFC); + device.subsystem_id := getword(data, false); + device.subsystem_vid := getword(data, true); + + requestConfig(bus, slot, func, 12); + device.exp_rom_addr := inl($CFC); + + requestConfig(bus, slot, func, 13); + data := inl($CFC); + device.reserved0 := getword(data, false); + device.reserved1 := getbyte(data, 2); + device.capabilities := getbyte(data, 3); + + requestConfig(bus, slot, func, 14); + device.reserved2 := inl($CFC); + + requestConfig(bus, slot, func, 15); + data := inl($CFC); + device.max_latency := getbyte(data, 0); + device.min_grant := getbyte(data, 1); + device.interrupt_pin := getbyte(data, 2); + device.interrupt_line := getbyte(data, 3); + + DevID:= PDeviceIdentifier(kalloc(sizeof(TDeviceIdentifier))); + DevID^.Bus:= biPCI; + DevID^.id0:= device.device_id; + DevID^.id1:= device.class_code; + DevID^.id2:= device.subclass_class; + DevID^.id3:= device.prog_if; + DevID^.id4:= device.vendor_id; + DevID^.ex:= nil; + + console.writestring('PCI: Found Device: '); + console.writehex(device.header_type); + console.writestring(' '); + console.writehex(device.device_id); + console.writestring(' '); + console.writehex(device.class_code); + console.writestring(' '); + console.writehex(device.subclass_class); + console.writestring(' '); + console.writehexln(device.prog_if); + + devices[device_count] := device; + device_count := device_count + 1; + + drivermanagement.register_device('PCI Device', DevID, @device); + kfree(void(DevID)); + //if device.class_code = 1 then ata.init(device); +end; + +function getDeviceInfo(class_code : uint8; subclass_code : uint8; prog_if : uint8; var count : uint32) : TDeviceArray; +var + i : uint16; + devices_out : array[0..31] of TPCI_Device; + +begin + count := 0; + for i:=0 to device_count do begin + {writehex(devices[i].class_code); + writestring(' ?= '); + writehex(class_code); + writestring(' && '); + writehex(devices[i].subclass_class); + writestring(' ?= '); + writehex(subclass_code); + writestring(' && '); + writehex(devices[i].prog_if); + writestring(' ?= '); + writehex(prog_if);} + if (devices[i].class_code = class_code) and (devices[i].subclass_class = subclass_code) and ((devices[i].prog_if = prog_if) or (prog_if = $FF)) then begin + devices_out[count] := devices[i]; + count := count + 1; + end; + end; + getDeviceInfo := devices_out; +end; + +end. \ No newline at end of file