Plan 9 from Bell Labs’s /sys/src/pub/doc/beagle/igepv2/powervr/module.c

Copyright © 2021 Plan 9 Foundation
Distributed under the MIT License.
Download the Plan 9 distribution.


/* -*- Mode: C; tab-width: 4; indent-tabs-mode: 't; c-basic-offset: 4 -*-
 *
 * Name         : $RCSfile: module.c $
 *
 * Copyright    : 2000,2001,2002 by Imagination Technologies Limited. 
 *                  All rights reserved.
 *                  No part of this software, either material or conceptual 
 *                  may be copied or distributed, transmitted, transcribed,
 *                  stored in a retrieval system or translated into any 
 *                  human or computer language in any form by any means,
 *                  electronic, mechanical, manual or other-wise, or 
 *                  disclosed to third parties without the express written
 *                  permission of:
 *                             Imagination Technologies Limited, 
 *                             HomePark Industrial Estate, 
 *                             Kings Langley, 
 *                             Hertfordshire,
 *                             WD4 8LZ, 
 *                             UK
 *
 * Description  : module init/deinit/ioctl for pvr core drivers
 *
 * Version	 	: $Revision: 1.40 $
 *
 **************************************************************************/

#include <linux/errno.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/kdev_t.h>
#include <linux/pci.h>
#include <linux/list.h>
#include <linux/init.h>
#include "mmap.h"
#include "virtmem.h"
#include "kernmem.h"

#include "debug.h"

/* ResMan */
void ResManProcessConnect(int dwProcID);
void ResManProcessDisconnect(void);

void RecoverPrimarySurface(void);
#define RESMAN_PROCESSID_FIND                   0xffffffff

/****************************************************/
/* FILE OPERATIONS                                  */
/****************************************************/

int pmxcore_driver_init = 0;

/* Registry */
int number_registry_entries = 0; 
REGISTRY_ENTRY pvrcore_registry[MAX_REGISTRY_ENTRIES];

int send_registry_info(void *); /* send to the kernel */
int get_registry_info(void *, void *); /* get from the kernel */


LIST_HEAD(pvrProcList);
extern PKV_OFFSET_LOCKED_STRUCT psKVOffsetStruct;

void ReleaseDpf(char *format, ...)
{
	asm("pop %%ebp\njmp *%0\n" : : "r" (&printk));
}

int pmxcore_open(void)
{
	int Ret = 0;

	struct list_head *ptr = 0;
	struct pvrProcRecord *entry = 0;
	unsigned found = 0;
	MOD_INC_USE_COUNT;

	if(pmxcore_driver_init)
	{
		pmxcore_driver_init += 1;

		ResManProcessConnect(RESMAN_PROCESSID_FIND);

		/* process open ref count for KVOT lock */
		for (ptr = pvrProcList.next; ptr != &pvrProcList; ptr = ptr->next)
		{
			entry = list_entry(ptr, struct pvrProcRecord, list);
			if (entry->pid == current->pid)
			{
				entry->count++;
				found = 1;
				break;
			}
		}
		if (!found)
		{
			entry = kmalloc(sizeof(struct pvrProcRecord), GFP_KERNEL);
			entry->pid = current->pid;
			INIT_LIST_HEAD(&entry->mmapList);
			entry->count = 1;
			entry->drmMMAP = 0;
			list_add_tail(&entry->list, &pvrProcList);
		}
	}

	DPF("pmxcore_open ok");

	return Ret;
}

int pvr_switch_to_pvr(struct inode *inode, struct file *file,
					  unsigned int cmd, unsigned long arg)
{
	struct list_head *ptr = 0;
	struct pvrProcRecord *entry = 0;

	for (ptr = pvrProcList.next; ptr != &pvrProcList; ptr = ptr->next)
	{
		entry = list_entry(ptr, struct pvrProcRecord, list);
		if (entry->pid == current->pid)
			entry->drmMMAP = 0;
	}
	return 0;
}

int pvr_switch_to_drm(struct inode *inode, struct file *file,
					  unsigned int cmd, unsigned long arg)
{
	struct list_head *ptr = 0;
	struct pvrProcRecord *entry = 0;

	for (ptr = pvrProcList.next; ptr != &pvrProcList; ptr = ptr->next)
	{
		entry = list_entry(ptr, struct pvrProcRecord, list);
		if (entry->pid == current->pid)
			entry->drmMMAP = 1;
	}
	return 0;
}

int pvrUsingDRMMMAP(void)
{
	struct list_head *ptr = 0;
	struct pvrProcRecord *entry = 0;

	for (ptr = pvrProcList.next; ptr != &pvrProcList; ptr = ptr->next)
	{
		entry = list_entry(ptr, struct pvrProcRecord, list);
		if (entry->pid == current->pid)
			return entry->drmMMAP;
	}
	return 0;
}

int pmxcore_release(void)
{
	int Ret = 0;

	struct list_head *ptr = 0;
	struct pvrProcRecord *entry = 0;

	DPF("pmxcore_release");

	if(pmxcore_driver_init > 1)
	{
		ResManProcessDisconnect();
			
		/* Check if we need to break the KVOT lock */
		for (ptr = pvrProcList.next; ptr != &pvrProcList; ptr = ptr->next)
		{
			entry = list_entry(ptr, struct pvrProcRecord, list);
			if (entry->pid == current->pid)
			{
				if (--entry->count == 0) {
					if (psKVOffsetStruct && 
						(*psKVOffsetStruct->lockAddress == current->pid))
						*psKVOffsetStruct->lockAddress = 0;

					while (!list_empty(&entry->mmapList))
					{
						struct pvrMMAPRecord *mrecord;
						mrecord = list_entry(entry->mmapList.next,
											 struct pvrMMAPRecord,
											 list);
						list_del(&mrecord->list);
						kfree(mrecord);
					}

					list_del(&entry->list);
					kfree(entry);
				
					/* Put this back when turning */
					/* fullscreen flipping back on */	
					/* RecoverPrimarySurface(); */
				}
				break;
			}
		}
	}

	MOD_DEC_USE_COUNT;

	return Ret;
}


/****************************************************/
/* DRIVER INIT AND DEINIT                           */
/****************************************************/

#if defined(SUPPORT_AGP)
extern void InitializeAGP(void);
extern void ShutdownAGP(void);
#endif


void pvr_munmap_event(void *pvIn)
{
	MUNMAP_EVENT *munmap = (MUNMAP_EVENT *)pvIn;
	struct list_head *ptr = 0;
	struct pvrProcRecord *processEntry = 0;
	struct pvrMMAPRecord *mmapEntry = 0;

	for (ptr = pvrProcList.next; ptr != &pvrProcList; ptr = ptr->next)
	{
		processEntry = list_entry(ptr, struct pvrProcRecord, list);
		if (processEntry->pid == current->pid)
		{
			struct list_head *mptr;
			for (mptr = processEntry->mmapList.next; mptr != &processEntry->mmapList; mptr = mptr->next)
			{
				mmapEntry = list_entry(mptr, struct pvrMMAPRecord, list);
				if ((mmapEntry->userAddress == munmap->userAddress) && 
					(mmapEntry->length == munmap->length))
				{
					list_del(&mmapEntry->list);
					kfree(mmapEntry);
					break;
				}
			}
			break;
		}
	}
}

int send_registry_info(void *pvIn)
{
	REGISTRY_ENTRY *reg_entry;
	int i;

	reg_entry = (REGISTRY_ENTRY*)pvIn;

	/* first check if the current registry setting exists */
	for(i=0; i<number_registry_entries; i++)
	{
		if(!strcmp(pvrcore_registry[i].cEntryName, reg_entry->cEntryName))
			if(!strcmp(pvrcore_registry[i].cKeyName, reg_entry->cKeyName))
			{
				/* we have found the entry in the registry so just overwrite it */
				pvrcore_registry[i].dwData = reg_entry->dwData;
				if(reg_entry->cData[0])
					strcpy(pvrcore_registry[i].cData, reg_entry->cData);
				else
					pvrcore_registry->cData[0]='\0';
				return 0;
			}
	}

	if (number_registry_entries < MAX_REGISTRY_ENTRIES)
	{
		memcpy(pvrcore_registry[number_registry_entries].cEntryName, &reg_entry->cEntryName, 64);
		memcpy(pvrcore_registry[number_registry_entries].cKeyName, &reg_entry->cKeyName, 32);
		pvrcore_registry[number_registry_entries].dwData = reg_entry->dwData;
		if(reg_entry->cData[0])
			strcpy(pvrcore_registry[number_registry_entries].cData, reg_entry->cData);
		else
			pvrcore_registry[number_registry_entries].cData[0] = '\0';

		number_registry_entries += 1;
	}

	return 0;
}

int get_registry_info(void *pvIn, void *pvOut)
{
	int code;

	code = *((int*)(pvIn));
	

	if(!code)
	{
		/* the user asks how many registry entries are there */
		*((int*)(pvOut)) = number_registry_entries;
		return 0;
	}

	/* we return the whole registry */
	memcpy(pvOut, pvrcore_registry, sizeof(REGISTRY_ENTRY) * number_registry_entries);

	return 0;
}


/* end of $RCSfile: module.c $ */

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@plan9.bell-labs.com.