/* -*- 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 #include #include #include #include #include #include #include #include #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; icEntryName)) 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, ®_entry->cEntryName, 64); memcpy(pvrcore_registry[number_registry_entries].cKeyName, ®_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 $ */