summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'sgx_km/eurasia_km/services4/srvkm/env/linux/proc.c')
-rw-r--r--sgx_km/eurasia_km/services4/srvkm/env/linux/proc.c1059
1 files changed, 1059 insertions, 0 deletions
diff --git a/sgx_km/eurasia_km/services4/srvkm/env/linux/proc.c b/sgx_km/eurasia_km/services4/srvkm/env/linux/proc.c
new file mode 100644
index 0000000..0f954c1
--- /dev/null
+++ b/sgx_km/eurasia_km/services4/srvkm/env/linux/proc.c
@@ -0,0 +1,1059 @@
1/*************************************************************************/ /*!
2@Title Proc files implementation.
3@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
4@Description Functions for creating and reading proc filesystem entries.
5 Proc filesystem support must be built into the kernel for
6 these functions to be any use.
7@License Dual MIT/GPLv2
8
9The contents of this file are subject to the MIT license as set out below.
10
11Permission is hereby granted, free of charge, to any person obtaining a copy
12of this software and associated documentation files (the "Software"), to deal
13in the Software without restriction, including without limitation the rights
14to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15copies of the Software, and to permit persons to whom the Software is
16furnished to do so, subject to the following conditions:
17
18The above copyright notice and this permission notice shall be included in
19all copies or substantial portions of the Software.
20
21Alternatively, the contents of this file may be used under the terms of
22the GNU General Public License Version 2 ("GPL") in which case the provisions
23of GPL are applicable instead of those above.
24
25If you wish to allow use of your version of this file only under the terms of
26GPL, and not to allow others to use your version of this file under the terms
27of the MIT license, indicate your decision by deleting the provisions above
28and replace them with the notice and other provisions required by GPL as set
29out in the file called "GPL-COPYING" included in this distribution. If you do
30not delete the provisions above, a recipient may use your version of this file
31under the terms of either the MIT license or GPL.
32
33This License is also included in this distribution in the file called
34"MIT-COPYING".
35
36EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
37PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
40COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
41IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
42CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43*/ /**************************************************************************/
44
45#include <linux/version.h>
46
47#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
48#ifndef AUTOCONF_INCLUDED
49#include <linux/config.h>
50#endif
51#endif
52
53#include <linux/init.h>
54#include <linux/module.h>
55#include <linux/fs.h>
56#include <linux/proc_fs.h>
57#include <linux/seq_file.h>
58
59#include "services_headers.h"
60
61#include "queue.h"
62#include "resman.h"
63#include "pvrmmap.h"
64#include "pvr_debug.h"
65#include "pvrversion.h"
66#include "proc.h"
67#include "perproc.h"
68#include "env_perproc.h"
69#include "linkage.h"
70
71#include "lists.h"
72
73struct pvr_proc_dir_entry {
74 struct proc_dir_entry *pde;
75
76 pvr_next_proc_seq_t *next;
77 pvr_show_proc_seq_t *show;
78 pvr_off2element_proc_seq_t *off2element;
79 pvr_startstop_proc_seq_t *startstop;
80
81 pvr_proc_write_t *write;
82
83 IMG_VOID *data;
84};
85
86// The proc entry for our /proc/pvr directory
87static struct proc_dir_entry * dir;
88
89static const IMG_CHAR PVRProcDirRoot[] = "pvr";
90
91static IMG_INT pvr_proc_open(struct inode *inode,struct file *file);
92static ssize_t pvr_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
93
94static struct file_operations pvr_proc_operations =
95{
96 .open = pvr_proc_open,
97 .read = seq_read,
98 .write = pvr_proc_write,
99 .llseek = seq_lseek,
100 .release = seq_release,
101};
102
103static void *pvr_proc_seq_start (struct seq_file *m, loff_t *pos);
104static void *pvr_proc_seq_next (struct seq_file *m, void *v, loff_t *pos);
105static void pvr_proc_seq_stop (struct seq_file *m, void *v);
106static int pvr_proc_seq_show (struct seq_file *m, void *v);
107
108static struct seq_operations pvr_proc_seq_operations =
109{
110 .start = pvr_proc_seq_start,
111 .next = pvr_proc_seq_next,
112 .stop = pvr_proc_seq_stop,
113 .show = pvr_proc_seq_show,
114};
115
116#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
117static struct pvr_proc_dir_entry* g_pProcQueue;
118#endif
119static struct pvr_proc_dir_entry* g_pProcVersion;
120static struct pvr_proc_dir_entry* g_pProcSysNodes;
121
122#ifdef DEBUG
123static struct pvr_proc_dir_entry* g_pProcDebugLevel;
124#endif
125
126#ifdef PVR_MANUAL_POWER_CONTROL
127static struct pvr_proc_dir_entry* g_pProcPowerLevel;
128#endif
129
130
131static void ProcSeqShowVersion(struct seq_file *sfile,void* el);
132
133static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
134static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
135
136
137#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
138#define PDE_DATA(x) PDE(x)->data;
139#endif
140
141#ifdef DEBUG
142
143/*!
144******************************************************************************
145
146 @Function : ProcSeq1ElementOff2Element
147
148 @Description
149
150 Heleper Offset -> Element function for /proc files with only one entry
151 without header.
152
153 @Input sfile : seq_file object related to /proc/ file
154
155 @Input off : the offset into the buffer (id of object)
156
157 @Return : Pointer to element to be shown.
158
159*****************************************************************************/
160static void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
161{
162 PVR_UNREFERENCED_PARAMETER(sfile);
163 // Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL
164 if(!off)
165 return (void*)2;
166 return NULL;
167}
168
169#endif
170
171/*!
172******************************************************************************
173
174 @Function : ProcSeq1ElementHeaderOff2Element
175
176 @Description
177
178 Heleper Offset -> Element function for /proc files with only one entry
179 with header.
180
181 @Input sfile : seq_file object related to /proc/ file
182
183 @Input off : the offset into the buffer (id of object)
184
185 @Return : Pointer to element to be shown.
186
187*****************************************************************************/
188static void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
189{
190 PVR_UNREFERENCED_PARAMETER(sfile);
191
192 if(!off)
193 {
194 return PVR_PROC_SEQ_START_TOKEN;
195 }
196
197 // Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL
198 if(off == 1)
199 return (void*)2;
200
201 return NULL;
202}
203
204
205/*!
206******************************************************************************
207
208 @Function : pvr_proc_open
209
210 @Description
211 File opening function passed to proc_dir_entry->proc_fops for /proc entries
212 created by CreateProcReadEntrySeq.
213
214 @Input inode : inode entry of opened /proc file
215
216 @Input file : file entry of opened /proc file
217
218 @Return : 0 if no errors
219
220*****************************************************************************/
221static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
222{
223 IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
224
225 struct seq_file *seq = (struct seq_file*)file->private_data;
226 struct pvr_proc_dir_entry* ppde = PDE_DATA(inode);
227
228 /* Add pointer to handlers to seq_file structure */
229 seq->private = ppde;
230 return ret;
231}
232
233/*!
234******************************************************************************
235
236 @Function : pvr_proc_write
237
238 @Description
239 File writing function passed to proc_dir_entry->proc_fops for /proc files.
240 It's exacly the same function that is used as default one (->fs/proc/generic.c),
241 it calls proc_dir_entry->write_proc for writing procedure.
242
243*****************************************************************************/
244static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
245 size_t count, loff_t *ppos)
246{
247 struct inode *inode = file->f_path.dentry->d_inode;
248 struct pvr_proc_dir_entry * ppde;
249
250 PVR_UNREFERENCED_PARAMETER(ppos);
251 ppde = PDE_DATA(inode);
252
253 if (!ppde->write)
254 return -EIO;
255
256 return ppde->write(file, buffer, count, ppde->data);
257}
258
259
260/*!
261******************************************************************************
262
263 @Function : pvr_proc_seq_start
264
265 @Description
266 Seq_file start function. Detailed description of seq_file workflow can
267 be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
268 This function ises off2element handler.
269
270 @Input proc_seq_file : sequence file entry
271
272 @Input pos : offset within file (id of entry)
273
274 @Return : Pointer to element from we start enumeration (0 ends it)
275
276*****************************************************************************/
277static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
278{
279 struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
280 if(ppde->startstop != NULL)
281 ppde->startstop(proc_seq_file, IMG_TRUE);
282 return ppde->off2element(proc_seq_file, *pos);
283}
284
285/*!
286******************************************************************************
287
288 @Function : pvr_proc_seq_stop
289
290 @Description
291 Seq_file stop function. Detailed description of seq_file workflow can
292 be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
293
294 @Input proc_seq_file : sequence file entry
295
296 @Input v : current element pointer
297
298*****************************************************************************/
299static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
300{
301 struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
302 PVR_UNREFERENCED_PARAMETER(v);
303
304 if(ppde->startstop != NULL)
305 ppde->startstop(proc_seq_file, IMG_FALSE);
306}
307
308/*!
309******************************************************************************
310
311 @Function : pvr_proc_seq_next
312
313 @Description
314 Seq_file next element function. Detailed description of seq_file workflow can
315 be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
316 It uses supplied 'next' handler for fetching next element (or 0 if there is no one)
317
318 @Input proc_seq_file : sequence file entry
319
320 @Input pos : offset within file (id of entry)
321
322 @Input v : current element pointer
323
324 @Return : next element pointer (or 0 if end)
325
326*****************************************************************************/
327static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
328{
329 struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
330 (*pos)++;
331 if(ppde->next != NULL)
332 return ppde->next( proc_seq_file, v, *pos );
333 return ppde->off2element(proc_seq_file, *pos);
334}
335
336/*!
337******************************************************************************
338
339 @Function : pvr_proc_seq_show
340
341 @Description
342 Seq_file show element function. Detailed description of seq_file workflow can
343 be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
344 It call proper 'show' handler to show (dump) current element using seq_* functions
345
346 @Input proc_seq_file : sequence file entry
347
348 @Input v : current element pointer
349
350 @Return : 0 if everything is OK
351
352*****************************************************************************/
353static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
354{
355 struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
356 ppde->show( proc_seq_file,v );
357 return 0;
358}
359
360
361
362/*!
363******************************************************************************
364
365 @Function : CreateProcEntryInDirSeq
366
367 @Description
368
369 Create a file under the given directory. These dynamic files can be used at
370 runtime to get or set information about the device. Whis version uses seq_file
371 interface
372
373 @Input pdir : parent directory
374
375 @Input name : the name of the file to create
376
377 @Input data : aditional data that will be passed to handlers
378
379 @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
380 supplied, then off2element function is used instead
381
382 @Input show_handler : the function to call to show element
383
384 @Input off2element_handler : the function to call when it is needed to translate offest to element
385
386 @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
387
388 @Input whandler : the function to interpret writes from the user
389
390 @Return Ptr to proc entry , 0 for failure
391
392
393*****************************************************************************/
394static struct pvr_proc_dir_entry* CreateProcEntryInDirSeq(struct proc_dir_entry *pdir,
395 const IMG_CHAR * name,
396 IMG_VOID* data,
397 pvr_next_proc_seq_t next_handler,
398 pvr_show_proc_seq_t show_handler,
399 pvr_off2element_proc_seq_t off2element_handler,
400 pvr_startstop_proc_seq_t startstop_handler,
401 pvr_proc_write_t whandler)
402{
403
404 struct pvr_proc_dir_entry * ppde;
405 mode_t mode;
406
407 if (!dir)
408 {
409 PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
410 return NULL;
411 }
412
413 mode = S_IFREG;
414
415 if (show_handler)
416 {
417 mode |= S_IRUGO;
418 }
419
420 if (whandler)
421 {
422 mode |= S_IWUSR;
423 }
424
425 ppde = kmalloc(sizeof(struct pvr_proc_dir_entry), GFP_KERNEL);
426 if (!ppde)
427 {
428 PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
429 return NULL;
430 }
431
432 ppde->next = next_handler;
433 ppde->show = show_handler;
434 ppde->off2element = off2element_handler;
435 ppde->startstop = startstop_handler;
436 ppde->write = whandler;
437 ppde->data = data;
438
439 ppde->pde=proc_create_data(name, mode, pdir, &pvr_proc_operations, ppde);
440
441 if (!ppde->pde)
442 {
443 PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: proc_create_data failed", PVRProcDirRoot, name));
444 kfree(ppde);
445 return NULL;
446 }
447 return ppde;
448}
449
450
451/*!
452******************************************************************************
453
454 @Function : CreateProcReadEntrySeq
455
456 @Description
457
458 Create a file under /proc/pvr. These dynamic files can be used at runtime
459 to get information about the device. Creation WILL fail if proc support is
460 not compiled into the kernel. That said, the Linux kernel is not even happy
461 to build without /proc support these days. This version uses seq_file structure
462 for handling content generation.
463
464 @Input name : the name of the file to create
465
466 @Input data : aditional data that will be passed to handlers
467
468 @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
469 supplied, then off2element function is used instead
470
471 @Input show_handler : the function to call to show element
472
473 @Input off2element_handler : the function to call when it is needed to translate offest to element
474
475 @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
476
477 @Return Ptr to proc entry , 0 for failure
478
479*****************************************************************************/
480struct pvr_proc_dir_entry* CreateProcReadEntrySeq (const IMG_CHAR * name,
481 IMG_VOID* data,
482 pvr_next_proc_seq_t next_handler,
483 pvr_show_proc_seq_t show_handler,
484 pvr_off2element_proc_seq_t off2element_handler,
485 pvr_startstop_proc_seq_t startstop_handler)
486{
487 return CreateProcEntrySeq(name,
488 data,
489 next_handler,
490 show_handler,
491 off2element_handler,
492 startstop_handler,
493 NULL);
494}
495
496/*!
497******************************************************************************
498
499 @Function : CreateProcEntrySeq
500
501 @Description
502
503 @Description
504
505 Create a file under /proc/pvr. These dynamic files can be used at runtime
506 to get information about the device. Creation WILL fail if proc support is
507 not compiled into the kernel. That said, the Linux kernel is not even happy
508 to build without /proc support these days. This version uses seq_file structure
509 for handling content generation and is fuller than CreateProcReadEntrySeq (it
510 supports write access);
511
512 @Input name : the name of the file to create
513
514 @Input data : aditional data that will be passed to handlers
515
516 @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
517 supplied, then off2element function is used instead
518
519 @Input show_handler : the function to call to show element
520
521 @Input off2element_handler : the function to call when it is needed to translate offest to element
522
523 @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
524
525 @Input whandler : the function to interpret writes from the user
526
527 @Return Ptr to proc entry , 0 for failure
528
529*****************************************************************************/
530struct pvr_proc_dir_entry* CreateProcEntrySeq (const IMG_CHAR * name,
531 IMG_VOID* data,
532 pvr_next_proc_seq_t next_handler,
533 pvr_show_proc_seq_t show_handler,
534 pvr_off2element_proc_seq_t off2element_handler,
535 pvr_startstop_proc_seq_t startstop_handler,
536 pvr_proc_write_t whandler)
537{
538 return CreateProcEntryInDirSeq(dir,
539 name,
540 data,
541 next_handler,
542 show_handler,
543 off2element_handler,
544 startstop_handler,
545 whandler);
546}
547
548
549
550/*!
551******************************************************************************
552
553 @Function : CreatePerProcessProcEntrySeq
554
555 @Description
556
557 Create a file under /proc/pvr/<current process ID>. Apart from the
558 directory where the file is created, this works the same way as
559 CreateProcEntry. It's seq_file version.
560
561
562
563 @Input name : the name of the file to create
564
565 @Input data : aditional data that will be passed to handlers
566
567 @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
568 supplied, then off2element function is used instead
569
570 @Input show_handler : the function to call to show element
571
572 @Input off2element_handler : the function to call when it is needed to translate offest to element
573
574 @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
575
576 @Input whandler : the function to interpret writes from the user
577
578 @Return Ptr to proc entry , 0 for failure
579
580*****************************************************************************/
581struct pvr_proc_dir_entry* CreatePerProcessProcEntrySeq (const IMG_CHAR * name,
582 IMG_VOID* data,
583 pvr_next_proc_seq_t next_handler,
584 pvr_show_proc_seq_t show_handler,
585 pvr_off2element_proc_seq_t off2element_handler,
586 pvr_startstop_proc_seq_t startstop_handler,
587 pvr_proc_write_t whandler)
588{
589 PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
590 IMG_UINT32 ui32PID;
591
592 if (!dir)
593 {
594 PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: /proc/%s doesn't exist", PVRProcDirRoot));
595 return NULL;
596 }
597
598 ui32PID = OSGetCurrentProcessIDKM();
599
600 psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
601 if (!psPerProc)
602 {
603 PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: no per process data"));
604 return NULL;
605 }
606
607 if (!psPerProc->psProcDir)
608 {
609 IMG_CHAR dirname[16];
610 IMG_INT ret;
611
612 ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
613
614 if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
615 {
616 PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
617 return NULL;
618 }
619 else
620 {
621 psPerProc->psProcDir = proc_mkdir(dirname, dir);
622 if (!psPerProc->psProcDir)
623 {
624 PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u",
625 PVRProcDirRoot, ui32PID));
626 return NULL;
627 }
628 }
629 }
630
631 return CreateProcEntryInDirSeq(psPerProc->psProcDir, name, data, next_handler,
632 show_handler,off2element_handler,startstop_handler,whandler);
633}
634
635
636/*!
637******************************************************************************
638
639 @Function : CreateProcEntries
640
641 @Description
642
643 Create a directory /proc/pvr and the necessary entries within it. These
644 dynamic files can be used at runtime to get information about the device.
645 Creation might fail if proc support is not compiled into the kernel or if
646 there is no memory
647
648 @Input none
649
650 @Return nothing
651
652*****************************************************************************/
653IMG_INT CreateProcEntries(IMG_VOID)
654{
655 dir = proc_mkdir (PVRProcDirRoot, NULL);
656
657 if (!dir)
658 {
659 PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: cannot make /proc/%s directory", PVRProcDirRoot));
660
661 return -ENOMEM;
662 }
663
664#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
665 g_pProcQueue = CreateProcReadEntrySeq("queue", NULL, NULL, ProcSeqShowQueue, ProcSeqOff2ElementQueue, NULL);
666#endif
667 g_pProcVersion = CreateProcReadEntrySeq("version", NULL, NULL, ProcSeqShowVersion, ProcSeq1ElementHeaderOff2Element, NULL);
668 g_pProcSysNodes = CreateProcReadEntrySeq("nodes", NULL, NULL, ProcSeqShowSysNodes, ProcSeqOff2ElementSysNodes, NULL);
669
670 if(!g_pProcVersion || !g_pProcSysNodes
671#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
672 || !g_pProcQueue
673#endif
674 )
675 {
676 PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s files", PVRProcDirRoot));
677
678 return -ENOMEM;
679 }
680
681
682#ifdef DEBUG
683
684 g_pProcDebugLevel = CreateProcEntrySeq("debug_level", NULL, NULL,
685 ProcSeqShowDebugLevel,
686 ProcSeq1ElementOff2Element, NULL,
687 (IMG_VOID*)PVRDebugProcSetLevel);
688 if(!g_pProcDebugLevel)
689 {
690 PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/debug_level", PVRProcDirRoot));
691
692 return -ENOMEM;
693 }
694
695#ifdef PVR_MANUAL_POWER_CONTROL
696 g_pProcPowerLevel = CreateProcEntrySeq("power_control", NULL, NULL,
697 ProcSeqShowPowerLevel,
698 ProcSeq1ElementOff2Element, NULL,
699 PVRProcSetPowerLevel);
700 if(!g_pProcPowerLevel)
701 {
702 PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/power_control", PVRProcDirRoot));
703
704 return -ENOMEM;
705 }
706#endif
707#endif
708
709 return 0;
710}
711
712
713/*!
714******************************************************************************
715
716 @Function : RemoveProcEntrySeq
717
718 @Description
719
720 Remove a single node (created using *Seq function) under /proc/pvr.
721
722 @Input proc_entry : structure returned by Create function.
723
724 @Return nothing
725
726*****************************************************************************/
727IMG_VOID RemoveProcEntrySeq(struct pvr_proc_dir_entry* ppde)
728{
729#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
730 remove_proc_entry(ppde->pde->name, dir);
731#else
732 proc_remove(ppde->pde);
733#endif
734 kfree(ppde);
735}
736
737
738/*!
739******************************************************************************
740
741 @Function : RemovePerProcessProcEntrySeq
742
743 @Description
744
745 Remove a single node under the per process proc directory (created by *Seq function).
746
747 Remove a single node (created using *Seq function) under /proc/pvr.
748
749 @Input proc_entry : structure returned by Create function.
750
751 @Return nothing
752
753*****************************************************************************/
754IMG_VOID RemovePerProcessProcEntrySeq(struct pvr_proc_dir_entry* ppde)
755{
756 PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
757
758 psPerProc = LinuxTerminatingProcessPrivateData();
759 if (!psPerProc)
760 {
761 psPerProc = PVRSRVFindPerProcessPrivateData();
762 if (!psPerProc)
763 {
764 PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't remove proc entry, no per process data"));
765 return;
766 }
767 }
768
769 if (psPerProc->psProcDir)
770 {
771 PVR_DPF((PVR_DBG_MESSAGE, "Removing per-process proc entry"));
772#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
773 remove_proc_entry(ppde->pde->name, psPerProc->psProcDir);
774#else
775 proc_remove(ppde->pde);
776#endif
777 kfree(ppde);
778 }
779}
780
781#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
782/*!
783******************************************************************************
784
785 @Function : RemoveProcEntry
786
787 @Description
788
789 Remove a single node under /proc/pvr.
790
791 @Input name : the name of the node to remove
792
793 @Return nothing
794
795*****************************************************************************/
796static IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
797{
798 if (dir)
799 {
800 remove_proc_entry(name, dir);
801 PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, name));
802 }
803}
804
805
806/*!
807******************************************************************************
808
809 @Function : RemovePerProcessProcDir
810
811 @Description
812
813 Remove the per process directorty under /proc/pvr.
814
815 @Input psPerProc : environment specific per process data
816
817 @Return nothing
818
819*****************************************************************************/
820IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
821{
822 if (psPerProc->psProcDir)
823 {
824 while (psPerProc->psProcDir->subdir)
825 {
826 PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s/%s", PVRProcDirRoot, psPerProc->psProcDir->name, psPerProc->psProcDir->subdir->name));
827
828 RemoveProcEntry(psPerProc->psProcDir->subdir->name);
829 }
830 RemoveProcEntry(psPerProc->psProcDir->name);
831 }
832}
833#else
834IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
835{
836 proc_remove(psPerProc->psProcDir);
837}
838#endif
839/*!
840******************************************************************************
841
842 @Function : RemoveProcEntries
843
844 Description
845
846 Proc filesystem entry deletion - Remove all proc filesystem entries for
847 the driver.
848
849 @Input none
850
851 @Return nothing
852
853*****************************************************************************/
854IMG_VOID RemoveProcEntries(IMG_VOID)
855{
856#ifdef DEBUG
857 RemoveProcEntrySeq( g_pProcDebugLevel );
858#ifdef PVR_MANUAL_POWER_CONTROL
859 RemoveProcEntrySeq( g_pProcPowerLevel );
860#endif /* PVR_MANUAL_POWER_CONTROL */
861#endif
862
863#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
864 RemoveProcEntrySeq(g_pProcQueue);
865#endif
866 RemoveProcEntrySeq(g_pProcVersion);
867 RemoveProcEntrySeq(g_pProcSysNodes);
868
869#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
870 while (dir->subdir)
871 {
872 PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s", PVRProcDirRoot, dir->subdir->name));
873
874 RemoveProcEntry(dir->subdir->name);
875 }
876 remove_proc_entry(PVRProcDirRoot, NULL);
877#else
878 proc_remove(dir);
879#endif
880
881}
882
883/*************************************************************************/ /*!
884@Function PVRProcGetData
885@Description Extract data from PVR proc object.
886@Input pointer to pvr_proc_dir_entr object
887@Return pointer to data object passed in to Proc create function.
888*/ /**************************************************************************/
889void *PVRProcGetData(struct pvr_proc_dir_entry *ppde)
890{
891 return ppde->data;
892}
893
894/*****************************************************************************
895 FUNCTION : ProcSeqShowVersion
896
897 PURPOSE : Print the content of version to /proc file
898
899 PARAMETERS : sfile - /proc seq_file
900 el - Element to print
901*****************************************************************************/
902static void ProcSeqShowVersion(struct seq_file *sfile, void* el)
903{
904 SYS_DATA *psSysData;
905 IMG_CHAR *pszSystemVersionString = "None";
906
907 if(el == PVR_PROC_SEQ_START_TOKEN)
908 {
909 seq_printf(sfile,
910 "Version %s (%s) %s\n",
911 PVRVERSION_STRING,
912 PVR_BUILD_TYPE, PVR_BUILD_DIR);
913 return;
914 }
915
916 psSysData = SysAcquireDataNoCheck();
917#if defined(SUPPORT_TI_VERSION_STRING)
918 if(psSysData != IMG_NULL && psSysData->szTIVersion != IMG_NULL)
919 {
920 seq_printf( sfile, "UM Services Version: %s\n",
921 psSysData->szTIVersion);
922 }
923#endif
924 if(psSysData != IMG_NULL && psSysData->pszVersionString != IMG_NULL)
925 {
926 pszSystemVersionString = psSysData->pszVersionString;
927 }
928
929 seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
930}
931
932static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
933{
934 switch (deviceType)
935 {
936 default:
937 {
938 static IMG_CHAR text[10];
939
940 sprintf(text, "?%x", (IMG_UINT)deviceType);
941
942 return text;
943 }
944 }
945}
946
947
948static const IMG_CHAR *deviceClassToString(PVRSRV_DEVICE_CLASS deviceClass)
949{
950 switch (deviceClass)
951 {
952 case PVRSRV_DEVICE_CLASS_3D:
953 {
954 return "3D";
955 }
956 case PVRSRV_DEVICE_CLASS_DISPLAY:
957 {
958 return "display";
959 }
960 case PVRSRV_DEVICE_CLASS_BUFFER:
961 {
962 return "buffer";
963 }
964 default:
965 {
966 static IMG_CHAR text[10];
967
968 sprintf(text, "?%x", (IMG_UINT)deviceClass);
969 return text;
970 }
971 }
972}
973
974static IMG_VOID* DecOffPsDev_AnyVaCb(PVRSRV_DEVICE_NODE *psNode, va_list va)
975{
976 off_t *pOff = va_arg(va, off_t*);
977 if (--(*pOff))
978 {
979 return IMG_NULL;
980 }
981 else
982 {
983 return psNode;
984 }
985}
986
987/*****************************************************************************
988 FUNCTION : ProcSeqShowSysNodes
989
990 PURPOSE : Print the content of version to /proc file
991
992 PARAMETERS : sfile - /proc seq_file
993 el - Element to print
994*****************************************************************************/
995static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
996{
997 PVRSRV_DEVICE_NODE *psDevNode;
998
999 if(el == PVR_PROC_SEQ_START_TOKEN)
1000 {
1001 seq_printf( sfile,
1002 "Registered nodes\n"
1003 "Addr Type Class Index Ref pvDev Size Res\n");
1004 return;
1005 }
1006
1007 psDevNode = (PVRSRV_DEVICE_NODE*)el;
1008
1009 seq_printf( sfile,
1010 "%p %-8s %-8s %4d %2u %p %3u %p\n",
1011 psDevNode,
1012 deviceTypeToString(psDevNode->sDevId.eDeviceType),
1013 deviceClassToString(psDevNode->sDevId.eDeviceClass),
1014 psDevNode->sDevId.eDeviceClass,
1015 psDevNode->ui32RefCount,
1016 psDevNode->pvDevice,
1017 psDevNode->ui32pvDeviceSize,
1018 psDevNode->hResManContext);
1019}
1020
1021/*****************************************************************************
1022 FUNCTION : ProcSeqOff2ElementSysNodes
1023
1024 PURPOSE : Transale offset to element (/proc stuff)
1025
1026 PARAMETERS : sfile - /proc seq_file
1027 off - the offset into the buffer
1028
1029 RETURNS : element to print
1030*****************************************************************************/
1031static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
1032{
1033 SYS_DATA *psSysData;
1034 PVRSRV_DEVICE_NODE*psDevNode = IMG_NULL;
1035
1036 PVR_UNREFERENCED_PARAMETER(sfile);
1037
1038 if(!off)
1039 {
1040 return PVR_PROC_SEQ_START_TOKEN;
1041 }
1042
1043 psSysData = SysAcquireDataNoCheck();
1044 if (psSysData != IMG_NULL)
1045 {
1046 /* Find Dev Node */
1047 psDevNode = (PVRSRV_DEVICE_NODE*)
1048 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
1049 DecOffPsDev_AnyVaCb,
1050 &off);
1051 }
1052
1053 /* Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL */
1054 return (void*)psDevNode;
1055}
1056
1057/*****************************************************************************
1058 End of file (proc.c)
1059*****************************************************************************/