summaryrefslogtreecommitdiff
path: root/shared/MacDriverUtils.c
blob: 19d323a6664413cf963e4a9e3fe010e64a69d8d7 (plain)
1
/*
 * 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"

/* 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;

	status = ExpMgrConfigReadWord(dtNode, (LogicalAddress)kPCIConfigCommandAddress, &cmd);
	if( status )
		return status;

	cmd |= cwCommandEnableMemorySpace;

	return ExpMgrConfigWriteWord(dtNode, (LogicalAddress)kPCIConfigCommandAddress, cmd);
}