{ DriverManagement - Driver Initialization & Management Interface. @author(Kieron Morris ) } unit drivermanagement; interface uses console, util, strings, lmemorymanager, terminal, tracer; const idANY = $FFFFFFFF; type PDevEx = ^TDevEx; TDevEx = record idN : uInt32; ex : PDevEx; end; TBusIdentifier = (biUnknown, biPCI, biUSB, bii2c, biPCIe, biANY); PDeviceIdentifier = ^TDeviceIdentifier; TDeviceIdentifier = record Bus : TBusIdentifier; id0 : uInt32; id1 : uInt32; id2 : uInt32; id3 : uint32; id4 : uint32; ex : PDevEx; end; TDriverLoadCallback = function(ptr : void) : boolean; PDriverRegistration = ^TDriverRegistration; TDriverRegistration = record Driver_Name : PChar; Identifier : PDeviceIdentifier; Driver_Load : TDriverLoadCallback; Loaded : Boolean; Next : PDriverRegistration; end; PDeviceRegistration = ^TDeviceRegistration; TDeviceRegistration = record Device_Name : PChar; Identifier : PDeviceIdentifier; Driver_Loaded : Boolean; Driver : PDriverRegistration; Next : PDeviceRegistration; end; procedure init; procedure register_driver(Driver_Name : PChar; DeviceID : PDeviceIdentifier; Load_Callback : TDriverLoadCallback); procedure register_driver_ex(Driver_Name : PChar; DeviceID : PDeviceIdentifier; Load_Callback : TDriverLoadCallback; force_load : boolean); procedure register_device(Device_Name : PChar; DeviceID : PDeviceIdentifier; ptr : void); var Root : PDriverRegistration = nil; Dev : PDeviceRegistration = nil; implementation procedure writeBusType(Bus : TBusIdentifier; WND : HWND); begin case Bus of biUnknown : console.writestringWND('Unknown', WND); biANY : console.writestringWND('ANY', WND); bii2c : console.writestringWND('i2c', WND); biPCI : console.writestringWND('PCI', WND); biPCIe : console.writestringWND('PCIe', WND); biUSB : console.writestringWND('USB', WND); end; end; { Terminal Commands } procedure terminal_command_drivers(Params : PParamList); var Drv : PDriverRegistration; ex : PDevEx; i : uint32; begin push_trace('driver_management.terminal_command_drivers'); Drv:= Root; i:= 1; while Drv <> nil do begin if Drv^.Loaded then begin console.writeintWND(i, getTerminalHWND); console.writestringWND(') ', getTerminalHWND); console.writestringWND(Drv^.Driver_Name, getTerminalHWND); console.writestringWND(' - Bus: ', getTerminalHWND); writeBusType(Drv^.Identifier^.Bus, getTerminalHWND); console.writestringlnWND(' ', getTerminalHWND); console.writestringWND(' [', getTerminalHWND); console.writeHexWND(Drv^.Identifier^.id0, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Drv^.Identifier^.id1, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Drv^.Identifier^.id2, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Drv^.Identifier^.id3, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Drv^.Identifier^.id4, getTerminalHWND); ex:= Drv^.Identifier^.ex; while ex <> nil do begin console.writestringWND('-', getTerminalHWND); console.writeHexWND(ex^.idN, getTerminalHWND); ex:= ex^.ex; end; console.writestringlnWND(']', getTerminalHWND); i:= i + 1; end; Drv:= Drv^.Next; end; pop_trace; end; procedure terminal_command_driversex(Params : PParamList); var Drv : PDriverRegistration; ex : PDevEx; i : uint32; begin push_trace('driver_management.terminal_command_driversex'); Drv:= Root; i:= 1; while Drv <> nil do begin console.writeintWND(i, getTerminalHWND); console.writestringWND(') ', getTerminalHWND); console.writestringWND(Drv^.Driver_Name, getTerminalHWND); console.writestringWND(' - Bus: ', getTerminalHWND); writeBusType(Drv^.Identifier^.Bus, getTerminalHWND); console.writestringWND(' - Loaded: ', getTerminalHWND); if Drv^.Loaded then console.writestringlnWND('true', getTerminalHWND) else console.writestringlnWND('false', getTerminalHWND); console.writestringWND(' [', getTerminalHWND); console.writeHexWND(Drv^.Identifier^.id0, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Drv^.Identifier^.id1, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Drv^.Identifier^.id2, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Drv^.Identifier^.id3, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Drv^.Identifier^.id4, getTerminalHWND); ex:= Drv^.Identifier^.ex; while ex <> nil do begin console.writestringWND('-', getTerminalHWND); console.writeHexWND(ex^.idN, getTerminalHWND); ex:= ex^.ex; end; console.writestringlnWND(']', getTerminalHWND); i:= i + 1; Drv:= Drv^.Next; end; pop_trace; end; procedure terminal_command_devices(Params : PParamList); var Dv : PDeviceRegistration; ex : PDevEx; i : uint32; begin push_trace('driver_management.terminal_command_devices'); Dv:= Dev; i:= 1; while Dv <> nil do begin console.writeintWND(i, getTerminalHWND); console.writestringWND(') ', getTerminalHWND); console.writestringWND(Dv^.Device_Name, getTerminalHWND); console.writestringWND(' - Bus: ', getTerminalHWND); writeBusType(Dv^.Identifier^.Bus, getTerminalHWND); console.writestringlnWND(' ', getTerminalHWND); console.writestringWND(' [', getTerminalHWND); console.writeHexWND(Dv^.Identifier^.id0, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Dv^.Identifier^.id1, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Dv^.Identifier^.id2, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Dv^.Identifier^.id3, getTerminalHWND); console.writestringWND('-', getTerminalHWND); console.writeHexWND(Dv^.Identifier^.id4, getTerminalHWND); ex:= Dv^.Identifier^.ex; while ex <> nil do begin console.writestringWND('-', getTerminalHWND); console.writeHexWND(ex^.idN, getTerminalHWND); ex:= ex^.ex; end; console.writestringlnWND(']', getTerminalHWND); if Dv^.Driver_Loaded then begin console.writestringWND(' Driver Loaded: ', getTerminalHWND); if Dv^.Driver <> nil then begin console.writestringlnWND(Dv^.Driver^.Driver_Name, getTerminalHWND); end else begin console.writestringlnWND('Unknown', getTerminalHWND) end; end; i:= i + 1; Dv:= Dv^.Next; end; pop_trace; end; procedure terminal_command_dev(Params : PParamList); var p1 : pchar; begin if paramCount(Params) > 0 then begin p1:= getParam(0, Params); if StringEquals(p1, 'drivers') then begin terminal_command_drivers(Params); end; if StringEquals(p1, 'devices') then begin terminal_command_devices(Params); end; if StringEquals(p1, 'driverex') then begin terminal_command_driversex(Params); end; end else begin writeStringlnWND('Driver Management Interface', getTerminalHWND); writeStringlnWND(' ', getTerminalHWND); writeStringlnWND('An interface to the drivermanagement portion of the kernel.', getTerminalHWND); writeStringlnWND(' ', getTerminalHWND); writeStringlnWND('Usage: ', getTerminalHWND); writeStringlnWND(' dev drivers - Print a list of loaded drivers.', getTerminalHWND); writeStringlnWND(' dev devices - Print a list of registered devices.', getTerminalHWND); writeStringlnWND(' dev driverex - Print a list of all available drivers.', getTerminalHWND); writeStringlnWND(' ', getTerminalHWND) end; end; { Main Functions } function copy_identifier(DeviceID : PDeviceIdentifier) : PDeviceIdentifier; var New_DevID : PDeviceIdentifier; root_ex, param_ex, new_ex: PDevEx; begin push_trace('driver_management.copy_identifier'); New_DevID:= PDeviceIdentifier(kalloc(sizeof(TDeviceIdentifier))); New_DevID^.Bus:= DeviceID^.Bus; New_DevID^.id0:= DeviceID^.id0; New_DevID^.id1:= DeviceID^.id1; New_DevID^.id2:= DeviceID^.id2; New_DevID^.id3:= DeviceID^.id3; New_DevID^.id4:= DeviceID^.id4; root_ex:= nil; if DeviceID^.ex <> nil then begin root_ex:= PDevEx(kalloc(sizeof(TDevEx))); param_ex:= DeviceID^.ex; new_ex:= root_ex; new_ex^.idN:= param_ex^.idN; new_ex^.ex:= nil; param_ex:= param_ex^.ex; while param_ex <> nil do begin new_ex^.ex:= PDevEx(kalloc(sizeof(TDevEx))); new_ex:= new_ex^.ex; new_ex^.idN:= param_ex^.idN; param_ex:= param_ex^.ex; end; end; New_DevID^.ex:= root_ex; copy_identifier:= New_DevID; pop_trace; end; function identifiers_match(i1, i2 : PDeviceIdentifier) : boolean; var ll1, ll2 : PDevEx; b1, b2 : boolean; begin push_trace('driver_management.identifiers_match'); identifiers_match:= true; identifiers_match:= identifiers_match and ((i1^.Bus = i2^.Bus) OR (i1^.Bus = biANY) OR (i2^.Bus = biANY)); identifiers_match:= identifiers_match and ((i1^.id0 = i2^.id0) OR (i1^.id0 = $FFFFFFFF) OR (i2^.id0 = $FFFFFFFF)); identifiers_match:= identifiers_match and ((i1^.id1 = i2^.id1) OR (i1^.id1 = $FFFFFFFF) OR (i2^.id1 = $FFFFFFFF)); identifiers_match:= identifiers_match and ((i1^.id2 = i2^.id2) OR (i1^.id2 = $FFFFFFFF) OR (i2^.id2 = $FFFFFFFF)); identifiers_match:= identifiers_match and ((i1^.id3 = i2^.id3) OR (i1^.id3 = $FFFFFFFF) OR (i2^.id3 = $FFFFFFFF)); identifiers_match:= identifiers_match and ((i1^.id4 = i2^.id4) OR (i1^.id4 = $FFFFFFFF) OR (i2^.id4 = $FFFFFFFF)); ll1:= i1^.ex; ll2:= i2^.ex; while true do begin b1:= ll1 <> nil; b2:= ll2 <> nil; identifiers_match:= identifiers_match and (b1 = b2); if not (b1 and b2) then begin break; end; if b1 = b2 then begin identifiers_match:= identifiers_match and ((ll1^.idN = ll2^.idN) OR (ll1^.idN = $FFFFFFFF) OR (ll2^.idN = $FFFFFFFF)); end else begin identifiers_match:= false; break; end; ll1:= ll1^.ex; ll2:= ll2^.ex; end; pop_trace; end; procedure init; begin push_trace('driver_management.init'); terminal.registerCommand('DEV', @terminal_command_dev, 'Driver Management Interface.'); //terminal.registerCommand('DRIVERSEX', @terminal_command_driversex, 'List all available drivers.'); //terminal.registerCommand('DRIVERS', @terminal_command_drivers, 'List loaded drivers.'); //terminal.registerCommand('DEVICES', @terminal_command_devices, 'List devices.'); pop_trace; end; procedure register_driver(Driver_Name : PChar; DeviceID : PDeviceIdentifier; Load_Callback : TDriverLoadCallback); begin push_trace('driver_management.register_driver'); register_driver_ex(Driver_Name, DeviceID, Load_Callback, false); pop_trace; end; procedure register_driver_ex(Driver_Name : PChar; DeviceID : PDeviceIdentifier; Load_Callback : TDriverLoadCallback; force_load : boolean); var NewReg : PDriverRegistration; RegList : PDriverRegistration; begin push_trace('driver_management.register_driver_ex'); if DeviceID <> nil then begin; NewReg:= PDriverRegistration(kalloc(sizeof(TDriverRegistration))); NewReg^.Driver_Name:= stringCopy(Driver_Name); NewReg^.Identifier:= copy_identifier(DeviceID); NewReg^.Loaded:= false; NewReg^.Driver_Load:= Load_Callback; NewReg^.Next:= nil; if Root = nil then begin Root:= NewReg; end else begin RegList:= Root; While RegList^.Next <> nil do begin RegList:= RegList^.Next; end; RegList^.Next:= NewReg; end; console.output('Driver Management', 'New Driver Registered: '); console.writestringln(NewReg^.Driver_Name); if force_load then begin console.output('Driver Management', 'Driver ('); console.writestring(NewReg^.Driver_Name); console.writestringln(') forced to load.'); NewReg^.Loaded:= True; NewReg^.Driver_Load(nil); end; end; pop_trace; end; procedure register_device(Device_Name : PChar; DeviceID : PDeviceIdentifier; ptr : void); var drv : PDriverRegistration; new_dev : PDeviceRegistration; dev_list : PDeviceRegistration; begin push_trace('driver_management.register_device'); drv:= Root; new_dev:= PDeviceRegistration(kalloc(sizeof(TDeviceRegistration))); new_dev^.Device_Name:= stringCopy(Device_Name); new_dev^.Identifier:= copy_identifier(DeviceID); new_dev^.Driver_Loaded:= false; new_dev^.Driver:= nil; new_dev^.next:= nil; if Dev = nil then begin Dev:= new_dev; end else begin dev_list:= Dev; While dev_list^.Next <> nil do begin dev_list:= dev_list^.Next; end; dev_list^.Next:= new_dev; end; console.output('Driver Management', 'New Device Registered: '); console.writestringln(new_dev^.Device_Name); while drv <> nil do begin if identifiers_match(drv^.Identifier, DeviceID) then begin console.output('Driver Management', 'Device/Driver Match: '); console.writestring(new_dev^.Device_Name); console.writestring('->'); console.writestringln(drv^.Driver_Name); if drv^.Driver_Load(ptr) then begin console.output('Driver Management', 'Driver ('); console.writestring(drv^.Driver_Name); console.writestringln(') successfully loaded.'); drv^.Loaded:= true; new_dev^.Driver_Loaded:= true; new_dev^.Driver:= drv; break; end; end; drv:= drv^.Next; end; pop_trace; end; end.