📄 tonedrv.c
字号:
/* Project Name : ToneSound * Project Date : 2003/12 * Version : 0.9 * Program Name : tonedrv.c * Description : ToneSound Driver * Author : Peter. * Compiler : arm-linux-gcc*/ #ifndef __KERNEL__#define __KERNEL__#endif#ifndef MODULE#define MODULE#endif#include <linux/fs.h>#include <linux/types.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/ioctl.h>#include <asm/system.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/hardware.h>//#include <asm/asm-s3c2410/s3c2410.h>#include "s3c2410.h"//#include <asm/mach-types.h>//#include <asm/mach-types.h>#define DRIVER_AUTHOR "Peter"#define DRIVER_DESC "Tone Driver"#define DRIVER_TYPE "Tone"#define DRIVER_NAME "Tone"#define TONE_SOUND 0x67A1#define TONE_VOL 0x67A2#define TONE_STOP 0x67A3#define TONE_MAJOR_NUM 0xFC/* Prototypes */// function used in file_operations int Tone_init(void);void Tone_cleanup(void);int Tone_open(struct inode *,struct file *);int Tone_release(struct inode *,struct file *);int Tone_ioctl(struct inode *,struct file *,unsigned int cmd,unsigned long arg);ssize_t Tone_read(struct file *,char *,size_t,loff_t *);ssize_t Tone_write(struct file *,const char *,size_t,loff_t *);/* Global Variables */static struct file_operations Tone_fops = { open: Tone_open, release: Tone_release, read: Tone_read, write: Tone_write, ioctl: Tone_ioctl};/* Methods */void Tone_Stop(){ rTCON = ( rTCON & 0xfffffff0 ); }// TCON : [22:0] => Timer0 : TCON[4:0]// TCON[0] : 0:Stop 1:Start// TCON[1] : 0:No Operation 1:Updat TCNTB0 & TCMPB0// TCON[2] : 0:Invert off 1: Invert on// TCON[3] : 0:One-Shot 1: Auto-Reload// TCFG0 : [31:0] => Prescalar0 : TCFG0[7:0] ( for Timer0 & Timer1) // TCFG1 : [31:0] => MUX0 : TCFG1[3:0] // 0000(1/2) 0001(1/4) 0010(1/8) 0011(1/16) // TCNTB0: [15:0]. TCMPB0: [15:0] void Tone_Sound(unsigned long freq){ unsigned int addr; rTCFG0 = ((rTCFG0 & ~0x0ff)|0xff); // Prescalar0 = 255 rTCFG1 = ((rTCFG1 & ~0x0f)| 0x03); // Divider = 1/16 rTCNTB0 = freq; // Between Max_Freq & Min_Freq rTCMPB0 = rTCNTB0 / 2; addr = (unsigned int)&rTCON; printk(KERN_ALERT "Tone_Sound:TCON addr=0x%x\n",addr); rTCON = ( rTCON & 0xfffffff0 ); rTCON = ( rTCON | 0x08 ); rTCON = ( rTCON & 0xfffffff8 ); rTCON = ( rTCON | 0x0a ); rTCON = ( rTCON & 0xfffffff8 ); rTCON = ( rTCON | 0x08 ); rTCON = ( rTCON & 0xfffffff8 ); rTCON = ( rTCON | 0x09 );}void Tone_Vol(unsigned long vol){ unsigned int addr; vol &= 0x07; rGPECON = (rGPECON & ~0x3f)| 0x15; // GPE0~GPE2 = 01(Output) rGPEDAT &= 0xfffffff8; addr = ( unsigned int) &rGPECON; printk(KERN_ALERT "Tone_Vol:GPECON=0x%x\n",addr); if ( vol == 1 ) rGPEDAT |= 0x04; else if ( vol == 2 ) rGPEDAT |= 0x02; else if ( vol == 3 ) rGPEDAT |= 0x01; else rGPEDAT &=0xfffffff8;}int Tone_open(struct inode *inode,struct file *flip){ MOD_INC_USE_COUNT; printk(KERN_ALERT "Tone_Drv:Tone_open\n"); return 0;}int Tone_release(struct inode *inode,struct file *flip){ MOD_DEC_USE_COUNT; printk(KERN_ALERT "Tone_Drv:Tone_release\n"); return 0;}ssize_t Tone_read(struct file *filp,char *buffer,size_t length,loff_t *offset){ printk(KERN_ALERT "Tone_Drv:Tone_read\n"); return -EINVAL;}ssize_t Tone_write(struct file *filp,const char *buffer,size_t length,loff_t *offset){ printk(KERN_ALERT "Tone_Drv:Tone_write\n"); return -EINVAL;}int Tone_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg){ printk(KERN_ALERT "Tone_Drv:Tone_ioctl=(%x,%u)\n",cmd,(unsigned int)arg); switch(cmd) { case TONE_SOUND: Tone_Sound(arg); printk(KERN_ALERT "Tone_Drv:ioctl-Sound\n"); return 0; case TONE_STOP: Tone_Stop(); printk(KERN_ALERT "Tone_Drv:ioctl-Stop\n"); return 0; case TONE_VOL: Tone_Vol(arg); printk(KERN_ALERT "Tone_Drv:ioctl-Volume\n"); return 0; default: return -EINVAL; }}/* Functions */int Tone_init(void){ int retval; printk(KERN_ALERT "Tone_Drv:Tone_init... \n"); // register the driver retval = register_chrdev(TONE_MAJOR_NUM,DRIVER_NAME,&Tone_fops); if(retval == -1) { printk(KERN_ALERT "Tone_Drv:Can't register the Tone Driver\n"); } else if(retval == 0) { printk(KERN_ALERT "Tone_Drv:Register the Tone Driver successfully\n"); } // Initialize the Tone Tone_Vol(0); printk(KERN_ALERT "Tone_Drv: GPBCON = 0x%x\n",(unsigned int)rGPBCON); rGPBCON &= 0xfffffffc; rGPBCON |= 0x02; printk(KERN_ALERT "Tone_Drv: GPBCON = 0x%x\n",(unsigned int)rGPBCON); return retval;}void Tone_cleanup(void){ int retval; printk(KERN_ALERT "Tone_Drv:Tone_cleanup- Unloading Tone Driver...\n"); // unregister the driver retval = unregister_chrdev(TONE_MAJOR_NUM,DRIVER_NAME); Tone_Stop(); if(retval < 0) { printk(KERN_ALERT "Tone_Drv:Can't unregister the Tone Driver\n"); } else if(retval == 0) { printk(KERN_ALERT "Tone_Drv:Unregister the Tone Driver successfully\n"); } //turn off the Tone Driver}module_init(Tone_init);module_exit(Tone_cleanup);MODULE_LICENSE("GPL");MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_SUPPORTED_DEVICE(DRIVER_TYPE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -