Asuro/src/drivermanagement.pas
2018-10-12 20:49:03 +00:00

414 lines
15 KiB
ObjectPascal

{
DriverManagement - Driver Initialization & Management Interface.
@author(Kieron Morris <kjm@kieronmorris.me>)
}
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.