📄 de2_switches.c
字号:
/* Copyright (C) 2007 Philipp Lutz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/////////////////////////////////////////////////////////////////////////////////////////////////////*Description:------------This device driver is capable of reading out the values of the switches found on the DE2 board.It uses the major number SWITCHES_MAJOR to be able to create a corresponding device file to read from.In uClinux for NIOS2 the automatic creation of device files is found in the script located at "vendors/Altera/nios2nommu/romfs_list".In uClinux it works with the following command:mknod /dev/switches 666 c 242 0*///////////////////////////////////////////////////////////////////////////////////////////////////////// Debug defines:// --------------//// uncomment following line to use the kernelmodule without// io (inb / outb) functions, needed for debug purposses on host machine.//#define TEST// enables debug-kernel-messages (viewed via "dmesg" command)//#define DEBUG///////////////////////////////////////////////////////////////////////////////////////////////////#include "de2_includes.h"// major numbers for identifying the device files#define SWITCHES_MAJOR 242// base-adress mapping to device names according to linux-2.6.x/include/nios2_system.h#define SWITCHES_BASE na_Switch// define buffers for the strings sended to userchar switches_string[STRING_LEN] = "0\0";char* switches_ptr = switches_string;// device files open?int switches_is_open = 0;/////////////////////////////////////////////////////////////////////////// Open handler/////////////////////////////////////////////////////////////////////////static int switches_open(struct inode *inode, struct file *file){#ifdef DEBUG printk("switches_open called\n");#endif unsigned long int value = 0; np_pio *pio_switches = (np_pio *)(SWITCHES_BASE); if (switches_is_open++) { printk("device busy...\n"); return -EBUSY; } // get new information from register#ifndef TEST value = inl(&pio_switches->np_piodata);#endif ltoa(switches_string,value);#ifdef DEBUG printk("read value: %i\n",value);#endif switches_ptr = switches_string; try_module_get(THIS_MODULE); return 0;}/////////////////////////////////////////////////////////////////////////// Release/Close handler/////////////////////////////////////////////////////////////////////////static int switches_release(struct inode *inode, struct file *file){#ifdef DEBUG printk("switches_release called\n");#endif --switches_is_open; module_put(THIS_MODULE); return 0;}/////////////////////////////////////////////////////////////////////////// Read handler/////////////////////////////////////////////////////////////////////////static ssize_t switches_read(struct file *filp, char *buffer, size_t length, loff_t * offset){ // Number of bytes actually written to the buffer int bytes_read = 0;#ifdef DEBUG printk("switches_read called\n");#endif // If we're at the end of the message, return 0 signifying end of file if (*switches_ptr == 0) return 0; while (length-- && *switches_ptr) { /* The buffer is in the user data segment, not the kernel segment so "*" assignment won't work. We have to use put_user which copies data from the kernel data segment to the user data segment. */ put_user(*(switches_ptr++), buffer++); bytes_read++; }#ifdef DEBUG printk("bytes read: %i\n",bytes_read);#endif // return count of bytes, sent to user return bytes_read;}// definitions, which functions are called for /dev/switchesstatic struct file_operations fops_switches = { .read = switches_read, .open = switches_open, .release = switches_release};/////////////////////////////////////////////////////////////////////////// Init funktion/////////////////////////////////////////////////////////////////////////static int __init mod_init(void){ np_pio *pio_switches = (np_pio *)(SWITCHES_BASE); // reserving memory regions for the I/O port if(!request_mem_region((unsigned long)SWITCHES_BASE, sizeof(np_pio), "de2_switches")) return -1; // registering PIO port as character device to the kernel if(register_chrdev(SWITCHES_MAJOR, "de2_switches", &fops_switches)) { printk("register_chrdev of de2_switches failed!\n"); release_mem_region((unsigned long)SWITCHES_BASE, sizeof(np_pio)); return -EIO; } #ifdef DEBUG printk("de2_switches registered successfully!\n");#ifdef TEST print("TEST mode active, so no I/O interaction is possible!\n");#endif#endif // set PIO port as input#ifndef TEST outl(0, &pio_switches->np_piodirection);#endif return 0;}/////////////////////////////////////////////////////////////////////////// Exit function (will be spared if build-in device driver selected)/////////////////////////////////////////////////////////////////////////static void __exit mod_exit(void){ // unregistering character device unregister_chrdev(SWITCHES_MAJOR,"de2_switches"); // releasing memory region release_mem_region((unsigned long)SWITCHES_BASE, sizeof(np_pio));}// declaring the init/exit functions of the modulemodule_init( mod_init );module_exit( mod_exit );MODULE_LICENSE("GPL");MODULE_AUTHOR("Philipp Lutz");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -