{ ************************************************ * Asuro * Unit: Driver_Management * Description: Manages Driver Loading ************************************************ * Author: K Morris * Contributors: ************************************************ } unit drivermanagement; interface uses console, util, strings, lmemorymanager, terminal; 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); begin case Bus of biUnknown : console.writestring('Unknown'); biANY : console.writestring('ANY'); bii2c : console.writestring('i2c'); biPCI : console.writestring('PCI'); biPCIe : console.writestring('PCIe'); biUSB : console.writestring('USB'); end; end; { Terminal Commands } procedure terminal_command_drivers(Params : PParamList); var Drv : PDriverRegistration; ex : PDevEx; i : uint32; begin Drv:= Root; i:= 1; while Drv <> nil do begin if Drv^.Loaded then begin console.writeint(i); console.writestring(') '); console.writestringln(Drv^.Driver_Name); console.writestring(' ['); writeBusType(Drv^.Identifier^.Bus); console.writestring(' - ID:'); console.writeHex(Drv^.Identifier^.id0); console.writestring('-'); console.writeHex(Drv^.Identifier^.id1); console.writestring('-'); console.writeHex(Drv^.Identifier^.id2); console.writestring('-'); console.writeHex(Drv^.Identifier^.id3); console.writestring('-'); console.writeHex(Drv^.Identifier^.id4); ex:= Drv^.Identifier^.ex; while ex <> nil do begin console.writestring('-'); console.writeHex(ex^.idN); ex:= ex^.ex; end; console.writestringln(']'); i:= i + 1; end; Drv:= Drv^.Next; end; end; procedure terminal_command_driversex(Params : PParamList); var Drv : PDriverRegistration; ex : PDevEx; i : uint32; begin Drv:= Root; i:= 1; while Drv <> nil do begin console.writeint(i); if Drv^.Loaded then console.writestring('L'); console.writestring(') '); console.writestringln(Drv^.Driver_Name); console.writestring(' ['); writeBusType(Drv^.Identifier^.Bus); console.writestring(' - ID:'); console.writeHex(Drv^.Identifier^.id0); console.writestring('-'); console.writeHex(Drv^.Identifier^.id1); console.writestring('-'); console.writeHex(Drv^.Identifier^.id2); console.writestring('-'); console.writeHex(Drv^.Identifier^.id3); console.writestring('-'); console.writeHex(Drv^.Identifier^.id4); ex:= Drv^.Identifier^.ex; while ex <> nil do begin console.writestring('-'); console.writeHex(ex^.idN); ex:= ex^.ex; end; console.writestringln(']'); i:= i + 1; Drv:= Drv^.Next; end; end; procedure terminal_command_devices(Params : PParamList); var Dv : PDeviceRegistration; ex : PDevEx; i : uint32; begin Dv:= Dev; i:= 1; while Dv <> nil do begin console.writeint(i); console.writestring(') '); console.writestringln(Dv^.Device_Name); console.writestring(' ['); writeBusType(Dv^.Identifier^.Bus); console.writestring(' - ID:'); console.writeHex(Dv^.Identifier^.id0); console.writestring('-'); console.writeHex(Dv^.Identifier^.id1); console.writestring('-'); console.writeHex(Dv^.Identifier^.id2); console.writestring('-'); console.writeHex(Dv^.Identifier^.id3); console.writestring('-'); console.writeHex(Dv^.Identifier^.id4); ex:= Dv^.Identifier^.ex; while ex <> nil do begin console.writestring('-'); console.writeHex(ex^.idN); ex:= ex^.ex; end; console.writestringln(']'); if Dv^.Driver_Loaded then begin console.writestring(' Driver Loaded: '); if Dv^.Driver <> nil then begin console.writestringln(Dv^.Driver^.Driver_Name); end else begin console.writestringln('Unknown') end; end; i:= i + 1; Dv:= Dv^.Next; end; end; { Main Functions } function copy_identifier(DeviceID : PDeviceIdentifier) : PDeviceIdentifier; var New_DevID : PDeviceIdentifier; root_ex, param_ex, new_ex: PDevEx; begin 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; end; function identifiers_match(i1, i2 : PDeviceIdentifier) : boolean; var ll1, ll2 : PDevEx; b1, b2 : boolean; begin 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 exit; 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; exit; end; ll1:= ll1^.ex; ll2:= ll2^.ex; end; end; procedure init; begin 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.'); end; procedure register_driver(Driver_Name : PChar; DeviceID : PDeviceIdentifier; Load_Callback : TDriverLoadCallback); begin register_driver_ex(Driver_Name, DeviceID, Load_Callback, false); end; procedure register_driver_ex(Driver_Name : PChar; DeviceID : PDeviceIdentifier; Load_Callback : TDriverLoadCallback; force_load : boolean); var NewReg : PDriverRegistration; RegList : PDriverRegistration; begin if DeviceID = nil then exit; 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; if force_load then begin NewReg^.Loaded:= True; NewReg^.Driver_Load(nil); end; end; procedure register_device(Device_Name : PChar; DeviceID : PDeviceIdentifier; ptr : void); var drv : PDriverRegistration; new_dev : PDeviceRegistration; dev_list : PDeviceRegistration; begin 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; while drv <> nil do begin if identifiers_match(drv^.Identifier, DeviceID) then begin if drv^.Driver_Load(ptr) then begin drv^.Loaded:= true; new_dev^.Driver_Loaded:= true; new_dev^.Driver:= drv; exit; end; end; drv:= drv^.Next; end; end; end.