source: svn/zas_dstar/hal/os/src/module/dst_module.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

File size: 16.4 KB
Line 
1/******************************************************************************
2 *.Copyright (c) 1999-2006 DST Technologies Inc.  All rights reserved.
3 *
4 *   MODULE:
5 *     dst_module.c
6 *
7 *   DESCRIPTION:
8 *     Linux kernel loadable module for low level DST hardware access
9 ******************************************************************************/
10#ifndef __KERNEL__
11#define __KERNEL__
12#endif
13
14#define CONFIG_DEVFS_FS 1
15
16#ifndef MODULE
17#define MODULE
18#endif
19
20/*========================
21 * Includes
22 *=======================*/
23#include "lld_os.h"
24#include "lld_local.h"
25#include "dst_kernel.h"
26#include "dstmodule.h"
27
28#if KERNEL_2_4_0
29//#include <linux/devfs_fs_kernel.h>
30#endif
31
32/*========================
33 * Local defines
34 *=======================*/
35#define DEVICE_NAME         DST_DEV_NAME
36#define DST_DEV_PERM        0666
37
38#define KSEG0_START         0x80000000
39
40#define GET_DS_U8_0(x)  (unsigned int)((x>>24)&0xFF)
41#define GET_DS_U8_1(x)  (unsigned int)((x>>16)&0xFF)
42#define GET_DS_U8_2(x)  (unsigned int)((x>>8)&0xFF)
43#define GET_DS_U8_3(x)  (unsigned int)((x)&0xFF)
44
45/*========================
46 * Local Prototypes
47 *=======================*/
48static DS_U32 lld_dlevel    (DS_U32 level);
49static int device_open      (struct inode *inode, struct file *file);
50static int device_close     (struct inode *inode, struct file *file);
51static int device_ioctl     (struct inode *inode, struct file *file,
52                         unsigned int ioctl_num, unsigned long ioctl_param);
53static __s64 dst_do_gettimeofday(void);
54
55/*========================
56 * Global variables
57 *=======================*/
58
59/*========================
60 * Local variables
61 *=======================*/
62static int lld_debug = 0;
63
64MODULE_AUTHOR ("DS Technology Inc.");
65MODULE_DESCRIPTION ("DS Kernel Module for Linux Platform");
66//MODULE_PARM (debug, "i");
67
68DST_DEVICE_INFO dst_device[MAX_DEVICES];
69DS_U32 current_filp=KERNEL_PID;
70
71struct file_operations dst_fops = 
72{
73#if KERNEL_2_4_0
74    owner: THIS_MODULE,
75#endif
76    ioctl: device_ioctl, 
77    mmap: NULL, 
78    open: device_open, 
79    release: device_close,
80};
81
82static int dsthwacc_major_num = 0;
83
84/******************************************************************************
85 * Interrupt setup for kernel
86 *
87 *
88 *
89 *****************************************************************************^^*/
90static int DevOpenForKernel (DST_DEVICE_INFO *pdevice)
91{
92    struct file KFileH;
93
94    KFileH.private_data = pdevice;
95    return (0);
96}
97
98/******************************************************************************
99 * Interrupt cleanup for kernel
100 *
101 *
102 *
103 *****************************************************************************^^*/
104static int DevCloseForKernel (DST_DEVICE_INFO *pdevice)
105{
106    struct file KFileH;
107
108    KFileH.private_data = pdevice;
109    return (0);
110}
111
112/******************************************************************************
113 * DS_U32 lld_GetVersion (void);
114 *
115 *  Purpose:    Return the version for this module
116 *
117 *  Inputs:     None
118 *
119 *  Outputs:    Version number
120 *
121 *****************************************************************************^^*/
122DS_U32 lld_GetVersion (void)
123{
124    return (DSTMOD_VERSION_NUMBER);
125}
126
127static int lld_get_info (char *page, char **start, off_t offset, int count, int *eof, void *data)
128{
129    int len = 0;
130    int limit = count - 80; /* don't print more than this */
131    static int ref_count=0;
132    unsigned int i;
133    DST_DEVICE_INFO *pdevice = (DST_DEVICE_INFO *) data;
134
135    ref_count++;
136   
137    for (i = 0; i < MAX_DEVICES; i++)
138    {
139        if ( limit > len )
140                len += sprintf(page+len, "dstmod[%d]: refcount = %i\n", i, ref_count);
141    }
142
143    *eof = 1;
144    pdevice = pdevice;
145   
146    return (len);
147}
148
149/*^^***************************************************************************
150 * static DS_U32 lld_dlevel (DS_U32 level)
151 *
152 * Description:
153 *          Set debug level in LLD and HKD
154 *
155 * Entry :  level = new debug level
156 *
157 * Return:  Old debug level
158 *
159 **************************************************************************^^*/
160static DS_U32 lld_dlevel (DS_U32 level)
161{
162    DS_U32 old_level;
163
164    old_level = lld_debug;
165    lld_debug = level;
166
167    return old_level;
168}
169
170/******************************************************************************
171 *  init_module (void)
172 *
173 *  Purpose: Initializes the module, registers the device
174 *   Inputs: NONE
175 *  Outputs: int - 0 on success, non zero on failure
176 ******************************************************************************/
177int init_module (void)
178{
179        printk( DEVICE_NAME ": " DSTMOD_VERSION_STRING ", Copyright (c) 2005-2006, Digital Stream Technology.\n");
180    printk( DEVICE_NAME ": generated on " __DATE__ " at " __TIME__ " \n");
181
182    memset (dst_device, 0, sizeof (dst_device));
183
184#if (KERNEL_2_4_0) && defined (CONFIG_DEVFS_FS)
185    dsthwacc_major_num = devfs_register_chrdev (DST_MAJOR_DEV_NUM, DEVICE_NAME, &dst_fops);
186#else
187    dsthwacc_major_num = register_chrdev (DST_MAJOR_DEV_NUM, DEVICE_NAME, &dst_fops);
188#endif
189
190    if (dsthwacc_major_num < 0) {
191        printk(DEVICE_NAME ": Error registering device: %d\n", dsthwacc_major_num);
192        return (dsthwacc_major_num);
193    }
194
195    printk( KERN_DEBUG DEVICE_NAME ": Major device number is %d.\n", dsthwacc_major_num);
196
197#if (KERNEL_2_4_0) && defined (CONFIG_DEVFS_FS)
198    devfs_register_series (NULL, DEVICE_NAME"%u", MAX_DEVICES, 
199                           DEVFS_FL_DEFAULT, dsthwacc_major_num, 0, 
200                           S_IFCHR | S_IRUSR | S_IWUSR | DST_DEV_PERM,
201                           &dst_fops, NULL);
202#endif
203
204    /*============================
205     * Init sem and event libs
206     *===========================*/
207    SemInit();
208    EventInit();
209
210    DevOpenForKernel(&dst_device[0]);
211    create_proc_read_entry (DST_DEV_NAME, 0, NULL, lld_get_info, (void *) dst_device);
212
213    return (0);
214}
215
216/******************************************************************************
217 *  cleanup_module (void)
218 *
219 *  Purpose: unregisters the device, frees memory and I/O ranges
220 *           used by the device.
221 *   Inputs: NONE
222 *  Outputs: NONE
223 ******************************************************************************/
224void cleanup_module (void)
225{
226    int retval;
227#if (KERNEL_2_4_0) && defined (CONFIG_DEVFS_FS)
228        int i;
229    char dst_dev[16];
230    devfs_handle_t de;
231#endif
232   
233    printk( DEVICE_NAME ": Shutting down module.\n");
234
235    DevCloseForKernel(&dst_device[0]);
236
237#if (KERNEL_2_4_0) && defined (CONFIG_DEVFS_FS)
238    retval = devfs_unregister_chrdev (dsthwacc_major_num, DEVICE_NAME);
239#else
240    retval = unregister_chrdev (dsthwacc_major_num, DEVICE_NAME);
241#endif
242
243    if (retval < 0)
244    {
245        printk( DEVICE_NAME ": Error in unregister_chrdev: %d\n", retval);
246    }
247
248#if (KERNEL_2_4_0) && defined (CONFIG_DEVFS_FS)
249    for (i = 0; i <= MAX_DEVICES; i++) 
250    {
251      sprintf(dst_dev, DEVICE_NAME"%u", i);
252      de = devfs_find_handle (NULL, dst_dev, 0, 0,
253                  DEVFS_SPECIAL_CHR, 0);
254      devfs_unregister(de);
255    }
256#endif
257    SemCleanup();
258    EventCleanup();
259    remove_proc_entry (DST_DEV_NAME, NULL);
260    memset (dst_device, 0, sizeof (dst_device));
261}
262
263/******************************************************************************
264 *.open_device (struct inode *inode, struct file *filp)
265 *  Function: Opens the device, increments the module count
266 *    Inputs: struct inode *inode
267 *            struct file *filp
268 *   Outputs: int - returns 0 on success, the defined error otherwise
269 ******************************************************************************/
270static int open_device (struct inode *inode, struct file *filp)
271{
272    unsigned int device_minor;
273    DST_DEVICE_INFO *pdevice;
274
275    /* Ensure that the requested minor device number exists and is valid */
276
277    device_minor = MINOR (inode->i_rdev);
278    pdevice = &dst_device[device_minor];
279   
280    printk( KERN_DEBUG DEVICE_NAME ": %s open for pid %d\n", pdevice->name, mCurrentTid);
281
282    filp->private_data = pdevice;
283
284    pdevice->refcount += 1; /* Increment counter */
285    //MOD_INC_USE_COUNT;
286    return (0);
287}
288
289/******************************************************************************
290 *.close_device (struct inode *inode, struct file *filp)
291 *  Function: Closes the device, decrements the module count
292 *    Inputs: struct inode *inode
293 *            struct file *filp
294 *   Outputs: NONE
295 ******************************************************************************/
296static int close_device (struct inode *inode, struct file *filp)
297{
298    DST_DEVICE_INFO *pdevice = filp->private_data;
299
300    printk( KERN_DEBUG DEVICE_NAME ": %s close for pid %d - refcount = %d\n", pdevice->name, mCurrentTid, (int)(pdevice->refcount));
301
302    SemProcessExit();
303    EventProcessExit();
304
305    /*===============================
306     * decrement reference counter
307     *==============================*/
308    if (pdevice->refcount > 0)
309    {
310        pdevice->refcount -= 1;
311    }
312    if (pdevice->refcount == 0)
313    {
314        filp->private_data = NULL;
315    }
316    //MOD_DEC_USE_COUNT;
317    return (0);
318}
319
320/******************************************************************************
321 *.device_open (struct inode *inode, struct file *filp)
322 *  Function: Opens the device, increments the module count
323 *    Inputs: struct inode *inode
324 *            struct file *filp
325 *   Outputs: int - returns 0 on success, the defined error otherwise
326 ******************************************************************************/
327static int device_open (struct inode *inode, struct file *filp)
328{
329    int i;
330    DS_U32 org_filp;
331
332    org_filp = current_filp;
333    current_filp = (DS_U32)filp;
334    i = open_device (inode, filp);
335    current_filp = org_filp;
336    return (i);
337}
338
339/******************************************************************************
340 *.device_close (struct inode *inode, struct file *filp);
341 *  Function: Closes the device, decrements the module count
342 *    Inputs: struct inode *inode
343 *            struct file *filp
344 *   Outputs: NONE
345 ******************************************************************************/
346static int device_close (struct inode *inode, struct file *filp)
347{
348    int i;
349    DS_U32 org_filp;
350
351    org_filp = current_filp;
352    current_filp = (DS_U32)filp;
353    i = close_device (inode, filp);
354    current_filp = org_filp;
355    return (i);
356}
357
358/*******************************************************************************
359 *.ioctl_device (struct inode *inode, struct file *filp,
360 *               unsigned int ioctl_num, unsigned long ioctl_param)
361 *  Function: Entry point for the programs calling the specific
362 *            IOCTLs.
363 *    Inputs: struct inode *inode
364 *            struct file *filp
365 *            unsigned int ioctl_num - the number of the IOCTL being called
366 *            unsigned int ioctl_param - the 'extra' data being sent
367 *   Outputs: int
368 ******************************************************************************/
369//extern char LoaderVer[];
370static int ioctl_device (struct inode *inode, struct file *filp,
371                         unsigned int ioctl_num, unsigned long ioctl_param)
372{
373    DS_U32 i;
374    DST_DEVICE_INFO *pdevice = filp->private_data;
375    __s64 time_stamp;
376    OBJ_OPER ObjOper;
377    DS_U32 flags;
378    DS_U8 *pbAddr;
379    DS_U16 *pwAddr;
380    DS_U32 *pdwAddr;
381        DS_U8 bTemp = 0;
382       
383    switch (ioctl_num)
384    {
385        case DSTHWIOC_SEM_OP:
386            copy_from_user (&ObjOper, (char *) ioctl_param, sizeof(OBJ_OPER));
387            i = SemOperation (&ObjOper);
388            copy_to_user ((char *)ioctl_param, &ObjOper, sizeof(OBJ_OPER));
389            return (i);
390            break;
391
392        case DSTHWIOC_EVENT_OP:
393            copy_from_user (&ObjOper, (char *) ioctl_param, sizeof(OBJ_OPER));
394            i = EventOperation (&ObjOper);
395            copy_to_user ((char *)ioctl_param, &ObjOper, sizeof(OBJ_OPER));
396            return (i);
397            break;
398
399        case DSTHWIOC_GET_VERSION:
400            copy_from_user (&i, (char *)ioctl_param, sizeof(DS_U32));
401            i = lld_GetVersion();
402            copy_to_user ((char *)ioctl_param, &i, sizeof (DS_U32));
403            break;
404       
405        case DSTHWIOC_GET_LOADER_VER:
406                        //printk("\nLoader Version %s\n",LoaderVer);
407                        //i = *(int *)LoaderVer;
408                        i=0;
409                        i = ((GET_DS_U8_0(i) - 48) << 24 ) | ((GET_DS_U8_1(i) - 48) << 16 ) | ((GET_DS_U8_2(i) - 48) << 8 ) | ((GET_DS_U8_3(i) - 48) );
410                        return i;
411                        break;
412
413        case DSTHWIOC_TIME_STAMP:
414            time_stamp = dst_do_gettimeofday();
415            copy_to_user((char *)ioctl_param, &time_stamp, sizeof(__s64));
416            return(-1);
417
418        case DSTHWIOC_SET_DBG_LEVEL:
419        {
420            DST_SET_DBG_LEVEL_MESSAGE_PARAMS params;
421
422            copy_from_user ((char *) &params, (char *) ioctl_param, sizeof (params));
423            lld_dlevel (params.level);
424            break;
425        }
426
427        case DSTHWIOC_IRQ_DISABLE:
428            flags = lld_os_disable_ints();      // disable interrupts
429
430            copy_to_user ((char*)ioctl_param, (char*)&flags, sizeof(DS_U32));
431
432            break;
433                       
434        case DSTHWIOC_IRQ_ENABLE:
435            lld_os_enable_ints();               // enable interrupts
436
437            break;
438                       
439        case DSTHWIOC_IRQ_RESTORE:
440            copy_from_user ((char*)&flags, (char*)ioctl_param, sizeof(DS_U32));
441
442            lld_os_restore_ints(flags);         // restore interrupt status
443
444            break;
445
446                case DSTHWIOC_ATOMIC_REG_ACCESS:
447            copy_from_user (&ObjOper, (char *) ioctl_param, sizeof(OBJ_OPER));
448                       
449                if ( ObjOper.Opcode == OBJ_OPCODE_READ ) {
450                        switch( ObjOper.Prm2 ) {
451                                case 1:
452                                        if ( ObjOper.Prm1 >= 0xB5021300 && ObjOper.Prm1 <= 0xB50213FF) {
453                                                bTemp = *((DS_U8 *)0xB50213DF);
454                                                *((DS_U8 *)0xB50213DF) = 0;
455                                        }
456                                       
457                                        pbAddr = (DS_U8 *)ObjOper.Prm1;
458                                        ObjOper.Prm2 = *pbAddr;
459                                       
460                                                if ( ObjOper.Prm1 >= 0xB5021300 && ObjOper.Prm1 <= 0xB50213FF) {
461                                                *((DS_U8 *)0xB50213DF) |= bTemp & 1;
462                                        }
463                                        break;
464                                       
465                                case 2:
466                                        pwAddr = (DS_U16 *)ObjOper.Prm1;
467                                        ObjOper.Prm2 = *pwAddr;
468                                        break;
469
470                                case 4:
471                                default:
472                                        pdwAddr = (DS_U32 *)ObjOper.Prm1;
473                                        ObjOper.Prm2 = *pdwAddr;
474                                }
475                } else {
476                        switch( ObjOper.RetCode ) {
477                                case 1:
478                                        if ( ObjOper.Prm1 >= 0xB5021300 && ObjOper.Prm1 <= 0xB50213FF) {
479                                                bTemp = *((DS_U8 *)0xB50213DF);
480                                                *((DS_U8 *)0xB50213DF) = 0;
481                                        }
482                                       
483                                        pbAddr = (DS_U8 *)ObjOper.Prm1;
484                                        *pbAddr = ObjOper.Prm2;
485                                               
486                                                if ( ObjOper.Prm1 >= 0xB5021300 && ObjOper.Prm1 <= 0xB50213FF) {
487                                                *((DS_U8 *)0xB50213DF) |= bTemp & 1;
488                                        }
489
490                                        break;
491                                       
492                                case 2:
493                                        pwAddr = (DS_U16 *)ObjOper.Prm1;
494                                        *pwAddr = ObjOper.Prm2;
495                                        break;
496
497                                case 4:
498                                default:
499                                        pdwAddr = (DS_U32 *)ObjOper.Prm1;
500                                        *pdwAddr = ObjOper.Prm2;
501                                }
502                }
503               
504                ObjOper.RetCode = OBJ_OK;
505
506            copy_to_user ((char *)ioctl_param, &ObjOper, sizeof(OBJ_OPER));
507            return (0);
508                        break;
509                       
510        default:
511            break;
512    }
513   
514    pdevice = pdevice;
515    return (0);
516}
517
518/******************************************************************************
519 *.device_ioctl (struct inode *inode, struct file *filp,
520 *               unsigned int ioctl_num, unsigned long ioctl_param)
521 *  Function: Entry point for the programs calling the specific
522 *            IOCTLs.
523 *    Inputs: struct inode *inode
524 *            struct file *filp
525 *            unsigned int ioctl_num - the number of the IOCTL being called
526 *            unsigned int ioctl_param - the 'extra' data being sent
527 *   Outputs: int
528 ******************************************************************************/
529static int device_ioctl (struct inode *inode, struct file *filp,
530                         unsigned int ioctl_num, unsigned long ioctl_param)
531{
532    int i;
533    DS_U32 org_filp;
534
535    org_filp = current_filp;
536    current_filp = (DS_U32)filp;
537    i = ioctl_device (inode, filp, ioctl_num, ioctl_param);
538    current_filp = org_filp;
539    return (i);
540}
541
542/******************************************************************************
543 *.dst_do_gettimeofday()
544 *  Function: Get the time of day
545 *    Inputs: NONE
546 *   Outputs: __s64
547 ******************************************************************************/
548static __s64 dst_do_gettimeofday(void)
549{
550    struct timeval  t;
551    __s64 stamp;
552    do_gettimeofday(&t);
553    stamp = (__s64)t.tv_sec * 1000000 + t.tv_usec;
554    stamp *= 1000;
555    return stamp;
556}
557
Note: See TracBrowser for help on using the repository browser.