historical/m0-applesillicon.git/xnu-qemu-arm64-5.1.0/roms/QemuMacDrivers/shared/MacDriverUtils.c
2024-01-16 11:20:27 -06:00

1 line
No EOL
4.1 KiB
C

/*
* Various utilities for writing a MacOS "ndrv" driver, such as device-tree
* helpers. These replace the various Apple sample codes whose licences
* are dubious and probably not suitable for GPL code
*/
//#include "VideoDriverPrivate.h"
//#include "VideoDriverPrototypes.h"
#include "logger.h"
#include "MacDriverUtils.h"
/* Simplified DT properties accessors */
void *DTGetProp(RegEntryIDPtr dtNode,
RegPropertyNamePtr name,
RegPropertyValueSize *outSize)
{
OSStatus err;
RegPropertyValue *v;
if (!outSize)
return NULL;
/* Grab size so we can allocate some memory */
err = RegistryPropertyGetSize(dtNode, name, outSize);
if (err)
return NULL;
/* Allocate */
v = PoolAllocateResident(*outSize, FALSE);
if (!v)
return NULL;
err = RegistryPropertyGet(dtNode, name, v, outSize);
if (err)
return NULL;
return v;
}
void DTFreeProp(void *v)
{
if (v)
PoolDeallocate(v);
}
/* Find a BAR logical address and size */
LogicalAddress GetDeviceBARAddress(RegEntryIDPtr dtNode,
PCIRegisterNumber barOffset,
ByteCount *size,
Boolean *isIO)
{
RegPropertyValueSize aasize, lasize;
LogicalAddress *las = NULL;
PCIAssignedAddress *aas = NULL;
LogicalAddress result = 0;
UInt32 i;
/* First grab assigned-addresses to find the BAR */
aas = DTGetProp(dtNode, kPCIAssignedAddressProperty, &aasize);
if (!aas)
return NULL;
aasize /= sizeof(*aas);
/* Then grab AAPL,addresses to get the corresponding logical addresses */
las = DTGetProp(dtNode, kAAPLDeviceLogicalAddress, &lasize);
if (!las)
goto bail;
lasize /= sizeof(LogicalAddress);
/* Lookup BAR */
for (i = 0; i < aasize; i++) {
struct PCIAssignedAddress *aa = aas + i;
/* Skip config space */
if (GetPCIAddressSpaceType(aa) == kPCIConfigSpace)
continue;
/* Check BAR offset */
if (GetPCIRegisterNumber(aa) != barOffset)
continue;
/* Found it, check that it was assigned */
if (aa->size.hi == 0 && aa->size.lo == 0) {
lprintf("BAR %02x not assigned !\n");
goto bail;
}
/* Check we have a logical for it */
if (i >= lasize) {
lprintf("BAR %02x missing AAPL,address property !\n");
goto bail;
}
/* We don't do 64-bit, sorry... */
if (aa->size.hi) {
lprintf("BAR %02x too big !\n");
goto bail;
}
/* Gotcha ! */
if (size)
*size = aa->size.lo;
if (isIO)
*isIO = GetPCIAddressSpaceType(aa) == kPCIIOSpace;
result = las[i];
break;
}
bail:
DTFreeProp(aas);
DTFreeProp(las);
return result;
}
/* PCI "Command" config register address */
#define kPCIConfigCommandAddress 0x04
#define cwCommandEnableMemorySpace 0x0002
/* Enable access to PCI memory space */
OSStatus EnablePCIMemorySpace(RegEntryIDPtr dtNode)
{
OSStatus status;
UInt16 cmd;
lprintf("Reading cmd word...\n");
status = ExpMgrConfigReadWord(dtNode, (LogicalAddress)kPCIConfigCommandAddress, &cmd);
if( status )
return status;
lprintf("cmad word is: %04x, writing update...\n", cmd);
cmd |= cwCommandEnableMemorySpace;
return ExpMgrConfigWriteWord(dtNode, (LogicalAddress)kPCIConfigCommandAddress, cmd);
}
OSStatus SetupPCIInterrupt(RegEntryID *dtNode, IRQInfo *info,
InterruptHandler handler, void *refCon)
{
ISTProperty *ist;
RegPropertyValueSize istSize;
OSStatus err;
ist = DTGetProp(dtNode, kISTPropertyName, &istSize);
if (!ist) {
lprintf("SetupPCIInterrupt: No %s property\n", kISTPropertyName);
return paramErr;
}
info->interruptSetMember = (*ist)[kISTChipInterruptSource];
DTFreeProp(ist);
err = GetInterruptFunctions(info->interruptSetMember.setID,
info->interruptSetMember.member,
&info->refCon,
&info->handlerFunction,
&info->enableFunction,
&info->disableFunction);
if (err) {
lprintf("SetupPCIInterrupt: Error %d getting interrupt functions\n");
return err;
}
err = InstallInterruptFunctions(info->interruptSetMember.setID,
info->interruptSetMember.member,
refCon, handler, NULL, NULL);
if (err) {
lprintf("SetupPCIInterrupt: Error %d setting interrupt functions\n");
return err;
}
return noErr;
}