mirror of https://github.com/red-prig/fpPS4.git
376 lines
7.6 KiB
Plaintext
376 lines
7.6 KiB
Plaintext
unit dev_dmem;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
{$CALLING SysV_ABI_CDecl}
|
|
|
|
interface
|
|
|
|
uses
|
|
sys_conf;
|
|
|
|
procedure dmemdev_init();
|
|
|
|
implementation
|
|
|
|
uses
|
|
errno,
|
|
vuio,
|
|
subr_uio,
|
|
vm,
|
|
vmparam,
|
|
dmem_map,
|
|
kern_dmem,
|
|
sys_vm_object,
|
|
vm_pager,
|
|
kern_authinfo,
|
|
kern_budget,
|
|
subr_backtrace;
|
|
|
|
type
|
|
PAvailableDirectMemorySize=^TAvailableDirectMemorySize;
|
|
TAvailableDirectMemorySize=packed record
|
|
start:QWORD; //in,out
|
|
__end:QWORD; //in
|
|
align:QWORD; //in
|
|
osize:QWORD; //out
|
|
end;
|
|
|
|
PAllocateDirectMemory=^TAllocateDirectMemory;
|
|
TAllocateDirectMemory=packed record
|
|
start:QWORD; //in,out
|
|
__end:QWORD; //in
|
|
len :QWORD; //in
|
|
align:QWORD; //in
|
|
mtype:DWORD;
|
|
_alig:DWORD;
|
|
end;
|
|
|
|
PReleaseDirectMemory=^TReleaseDirectMemory;
|
|
TReleaseDirectMemory=packed record
|
|
start:QWORD; //in
|
|
len :QWORD; //in
|
|
end;
|
|
|
|
PDirectMemoryQuery=^TDirectMemoryQuery;
|
|
TDirectMemoryQuery=packed record
|
|
d_pool_id:Integer;
|
|
flags :Integer;
|
|
id :Integer;
|
|
_align :Integer;
|
|
offset :QWORD;
|
|
info :Pointer;
|
|
size :QWORD;
|
|
end;
|
|
|
|
p_set_prt_aperture=^t_set_prt_aperture;
|
|
t_set_prt_aperture=packed record
|
|
addr :Pointer;
|
|
len :QWORD;
|
|
apertureId:Integer;
|
|
end;
|
|
|
|
function set_prt_aperture(data:p_set_prt_aperture):Integer;
|
|
var
|
|
addr:QWORD;
|
|
len :QWORD;
|
|
begin
|
|
Result:=0;
|
|
|
|
addr:=QWORD(data^.addr);
|
|
|
|
if ((addr and PAGE_MASK) <> 0) then
|
|
begin
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
len:=data^.len;
|
|
|
|
if ((QWORD($fc00000000) - addr) < len) then
|
|
begin
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
if (DWORD((addr - QWORD($1000000000)) shr 34) > 58) then
|
|
begin
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
if (Int64(len) < 0) then
|
|
begin
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
if (DWORD(data^.apertureId) > 2) then
|
|
begin
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
if ((len and PAGE_MASK) <> 0) then
|
|
begin
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
Writeln('TODO:set_prt_aperture(0x',HexStr(addr,10),',0x',HexStr(len,10),',',data^.apertureId,')');
|
|
end;
|
|
|
|
Function dmem_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer;
|
|
var
|
|
dmap:p_dmem_obj;
|
|
begin
|
|
Result:=0;
|
|
|
|
dmap:=dev^.si_drv1;
|
|
|
|
Writeln('dmem_ioctl("',dev^.si_name,'",0x',HexStr(cmd,8),',0x',HexStr(fflag,8),')');
|
|
|
|
case cmd of
|
|
$4008800A: //sceKernelGetDirectMemorySize
|
|
begin
|
|
PQWORD(data)^:=kern_budget.DMEM_LIMIT;
|
|
//PQWORD(data)^:=SCE_KERNEL_MAIN_DMEM_SIZE;
|
|
end;
|
|
|
|
$C0208016: //sceKernelAvailableDirectMemorySize
|
|
begin
|
|
with PAvailableDirectMemorySize(data)^ do
|
|
begin
|
|
Result:=dmem_map_query_available(dmap^.dmem,start,__end,align,start,osize);
|
|
end;
|
|
end;
|
|
|
|
$C0288001: //sceKernelAllocateDirectMemory
|
|
begin
|
|
with PAllocateDirectMemory(data)^ do
|
|
begin
|
|
Result:=dmem_map_alloc(dmap^.dmem,start,__end,len,align,mtype,start);
|
|
{
|
|
Writeln('dmem_map_alloc(0x',HexStr(start,11),
|
|
',0x',HexStr(__end,11),
|
|
',0x',HexStr(len,11),
|
|
',0x',HexStr(align,11),
|
|
',',mtype,'):',Result);
|
|
}
|
|
end;
|
|
end;
|
|
|
|
$C0288011: //sceKernelAllocateMainDirectMemory
|
|
begin
|
|
with PAllocateDirectMemory(data)^ do
|
|
begin
|
|
Result:=dmem_map_alloc(dmap^.dmem,0,kern_budget.DMEM_LIMIT,len,align,mtype,start);
|
|
end;
|
|
end;
|
|
|
|
$80108002: //sceKernelReleaseDirectMemory
|
|
begin
|
|
with PReleaseDirectMemory(data)^ do
|
|
begin
|
|
Result:=dmem_map_release(dmap^.dmem,start,len,False);
|
|
end;
|
|
end;
|
|
|
|
$80108015: //sceKernelCheckedReleaseDirectMemory
|
|
begin
|
|
with PReleaseDirectMemory(data)^ do
|
|
begin
|
|
Result:=dmem_map_release(dmap^.dmem,start,len,True);
|
|
end;
|
|
end;
|
|
|
|
$80288012: //sceKernelDirectMemoryQuery
|
|
begin
|
|
with PDirectMemoryQuery(data)^ do
|
|
begin
|
|
|
|
if (d_pool_id>2) then
|
|
begin
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
if (d_pool_id<>1) then
|
|
begin
|
|
//sceSblACMgrIsSystemUcred
|
|
Exit(EPERM);
|
|
end;
|
|
|
|
Result:=dmem_map_query(dmem_maps[d_pool_id].dmem,offset,flags,id,info,size);
|
|
end;
|
|
end;
|
|
|
|
$C0208004: //sceKernelGetDirectMemoryType
|
|
begin
|
|
Result:=dmem_map_get_memory_type(dmap^.dmem,data);
|
|
end;
|
|
|
|
$80188008: //sceKernelSetPrtAperture
|
|
begin
|
|
set_prt_aperture(data);
|
|
end;
|
|
|
|
else
|
|
begin
|
|
print_error_td('dmem_ioctl(0x'+HexStr(cmd,8)+')');
|
|
Assert(False);
|
|
Result:=EINVAL;
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
function OFF_TO_IDX(x:QWORD):QWORD; inline;
|
|
begin
|
|
Result:=QWORD(x) shr PAGE_SHIFT;
|
|
end;
|
|
|
|
Function dmem_mmap(dev:p_cdev;offset:vm_ooffset_t;paddr:p_vm_paddr_t;nprot:Integer;memattr:p_vm_memattr_t):Integer;
|
|
var
|
|
dmap:p_dmem_obj;
|
|
entry:p_dmem_map_entry;
|
|
r:Boolean;
|
|
begin
|
|
Result:=0;
|
|
|
|
if is_sce_prog_attr_40_800000(@g_authinfo) then
|
|
begin
|
|
Exit(EPERM);
|
|
end;
|
|
|
|
if is_sce_prog_attr_40_400000(@g_authinfo) then
|
|
begin
|
|
Exit(EPERM);
|
|
end;
|
|
|
|
Writeln('dmem_mmap("',dev^.si_name,'",0x',HexStr(offset,8),',0x',HexStr(paddr),',',nprot,')');
|
|
|
|
dmap:=dev^.si_drv1;
|
|
|
|
entry:=nil;
|
|
|
|
dmem_map_lock(dmap^.dmem);
|
|
|
|
r:=dmem_map_lookup_entry(dmap^.dmem,
|
|
OFF_TO_IDX(offset),
|
|
@entry);
|
|
|
|
dmem_map_unlock(dmap^.dmem);
|
|
|
|
if not r then
|
|
begin
|
|
Exit(-1);
|
|
end;
|
|
|
|
paddr^:=offset {+ };
|
|
memattr^:=0;
|
|
end;
|
|
|
|
Function dmem_mmap_single2(dev:p_cdev;offset:p_vm_ooffset_t;size:vm_size_t;obj:p_vm_object_t;nprot:Integer;maxprotp:p_vm_prot_t;flagsp:PInteger):Integer;
|
|
var
|
|
dmap:p_dmem_obj;
|
|
ofs:vm_ooffset_t;
|
|
flags:Integer;
|
|
begin
|
|
Result:=0;
|
|
|
|
if is_sce_prog_attr_40_800000(@g_authinfo) then
|
|
begin
|
|
Exit(EPERM);
|
|
end;
|
|
|
|
if is_sce_prog_attr_40_400000(@g_authinfo) then
|
|
begin
|
|
Exit(EPERM);
|
|
end;
|
|
|
|
Writeln('dmem_mmap_single2("',dev^.si_name,'",0x',HexStr(offset^,8),',0x',HexStr(size,8),',',nprot,')');
|
|
|
|
ofs:=offset^;
|
|
|
|
if (ofs > -1) and (size <= max_valid_dmem - ofs) then
|
|
begin
|
|
//
|
|
end else
|
|
begin
|
|
Exit(EACCES);
|
|
end;
|
|
|
|
dmap:=dev^.si_drv1;
|
|
|
|
flags:=flagsp^;
|
|
|
|
//with the value (mtype=-1) this is a test of memory continuousness
|
|
Result:=dmem_map_set_mtype(dmap^.dmem,
|
|
OFF_TO_IDX(ofs),
|
|
OFF_TO_IDX(ofs+size),
|
|
-1,
|
|
nprot,
|
|
flags);
|
|
|
|
if (Result<>0) then Exit;
|
|
|
|
maxprotp^:=maxprotp^ or VM_PROT_GPU_ALL;
|
|
|
|
obj^:=dmap^.vobj;
|
|
|
|
if ((maxprotp^ and nprot)=nprot) then
|
|
begin
|
|
Assert(obj^<>nil);
|
|
vm_object_reference(obj^);
|
|
end else
|
|
begin
|
|
Exit(EACCES);
|
|
end;
|
|
|
|
end;
|
|
|
|
Function dmem_open(dev:p_cdev;oflags,devtype:Integer):Integer;
|
|
begin
|
|
Result:=0;
|
|
|
|
if is_sce_prog_attr_40_800000(@g_authinfo) then
|
|
begin
|
|
Exit(EPERM);
|
|
end;
|
|
|
|
if is_sce_prog_attr_40_400000(@g_authinfo) then
|
|
begin
|
|
Exit(EPERM);
|
|
end;
|
|
end;
|
|
|
|
const
|
|
dmem_cdevsw:t_cdevsw=(
|
|
d_version :D_VERSION;
|
|
d_flags :0;
|
|
d_name :'dmem';
|
|
d_open :@dmem_open;
|
|
d_ioctl :@dmem_ioctl;
|
|
d_mmap :@dmem_mmap;
|
|
d_mmap_single2:@dmem_mmap_single2;
|
|
);
|
|
|
|
procedure dmemdev_init();
|
|
var
|
|
dev:p_cdev;
|
|
obj:vm_object_t;
|
|
i:Integer;
|
|
begin
|
|
For i:=0 to 2 do
|
|
begin
|
|
dev:=make_dev(@dmem_cdevsw,i,0,0,&777,'dmem%d',[i]);
|
|
dev^.si_drv1:=@dmem_maps[i];
|
|
//
|
|
obj:=vm_pager_allocate(OBJT_DEVICE,dev,0,0,0);
|
|
obj^.size:=$1400000;
|
|
obj^.flags:=obj^.flags or OBJ_DMEM_EXT;
|
|
obj^.un_pager.map_base:=Pointer(VM_MIN_GPU_ADDRESS);
|
|
vm_object_reference(obj);
|
|
//
|
|
dmem_maps[i].dmem:=@kern_dmem.dmem;
|
|
dmem_maps[i].vobj:=obj;
|
|
end;
|
|
end;
|
|
|
|
|
|
end.
|
|
|