⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 HMS30C7202下的CAN驱动
💻 C
字号:
/** main.c * * Written by Sebastian Stolzenberg email:stolzi@sebastian-stolzenberg.de * Version 1.0  04 Feb 2003 */#ifndef __KERNEL__# define __KERNEL__#endif#ifndef MODULE# define MODULE#endif#define EXPORT_SYMTAB#include <linux/module.h>#include <linux/proc_fs.h>#include "../include/candrv.h"#include "../include/hms30c7202_can.h"#include "../include/c_can.h"//#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,8)MODULE_LICENSE("GPL");//#endif#define EXPORT_SYMTAB/* Module parameters, some must be supplied at module loading time */int major = CAN_MAJOR;MODULE_PARM(major,"i");int extended[ MAX_HW_CHIPS ] = { 0, 0 };MODULE_PARM(extended,"1-2i");int baudrate[ MAX_HW_CHIPS ] = { 125, 125 };MODULE_PARM(baudrate,"1-2i");char *hw[ MAX_HW_CHIPS ]={ NULL,NULL };MODULE_PARM(hw, "1-2s");int irq[ MAX_HW_CHIPS ]={ 0x12, 0x13 };MODULE_PARM(irq, "1-2i");unsigned long io[ MAX_HW_CHIPS ] = { 0x8002f000, 0x80030000 };MODULE_PARM(io, "1-2l");char time_triggered[ MAX_HW_CHIPS ] = { 0, 0 };MODULE_PARM(time_triggered, "1-2b");unsigned long time_trig_msec[ MAX_HW_CHIPS ] = { 10, 10 };MODULE_PARM(time_trig_msec, "1-2l");/* Global structure, used to hold information about   the installed hardware. */struct canhardware_t gcanhardware;struct canhardware_t *pghw = &gcanhardware;#define EXPORT_SYMTAB/* * Pointers to dynamically allocated memory are maintained in a linked list * to ease memory deallocation. */struct mem_addr *pgmem_head = NULL;struct file_operations can_fops={        owner:   THIS_MODULE,        read:    can_read,        write:   can_write,        poll:    can_poll,        ioctl:   can_ioctl,        open:    can_open,        release: can_close,};EXPORT_SYMBOL( can_fops );////////////////////////////////////////////////////////////////////////////////* * add_mem_to_list * * Adds a pointer to allocated memory area to the linked list. */int add_mem_to_list( void *paddress ){        struct mem_addr *pmem_new;#ifdef DEBUG_MEM        DEBUGMSG("add_mem_to_list %p, gmem_head=%p", paddress, gmem_head );#endif        pmem_new = ( struct mem_addr * )kmalloc( sizeof( struct mem_addr ),                                                 GFP_KERNEL );        if ( pmem_new == NULL ) {                CANMSG("Memory list error.");                return -ENOMEM;        }        pmem_new->next = pgmem_head;        pmem_new->address = paddress;        pgmem_head = pmem_new;        return 0;}////////////////////////////////////////////////////////////////////////////////* del_mem_from_list * * Removes pointer from linked list and releases memory area. */int del_mem_from_list( void *paddress ){        struct mem_addr *pmem_search = NULL;        struct mem_addr *pmem_delete = NULL;#ifdef DEBUG_MEM        DEBUGMSG("del_mem_from_list %p, gmem_head=%p", paddress, gmem_head );#endif        pmem_search = pgmem_head;        if  ( pgmem_head->address == paddress ) {                kfree( pgmem_head->address );                pgmem_head = pgmem_head->next;                kfree( pmem_search );        } else {                while (pmem_search->next->address != paddress ) {                        pmem_search = pmem_search->next;                }                kfree( pmem_search->next->address );                pmem_delete = pmem_search->next;                pmem_search->next = pmem_search->next->next;                kfree( pmem_delete );        }        return 0;}////////////////////////////////////////////////////////////////////////////////* * del_mem_list * * Removes all pointers from the list and clears the whole allocated memory. */int del_mem_list( void ){        struct mem_addr *mem_old;#ifdef DEBUG_MEM        DEBUGMSG("del_mem_list, gmem_head=%p", gmem_head);#endif        while ( pgmem_head->next != NULL ) {                mem_old = pgmem_head;                kfree( mem_old->address );                pgmem_head = mem_old->next;                kfree( mem_old );        }        return 0;}////////////////////////////////////////////////////////////////////////////////* * init_module * * Called through the insmod command. * Initializes the driver corresponding to the insmod parameters. */int init_module( void ){        /* Parse command line data; cards, io, irq's */        if ( parse_args( pghw )) {                return -EINVAL;        }        list_hw( pghw );        /* Register the character device */        if ( register_chrdev( major, DEVICE_NAME, &can_fops )) {                CANMSG("Error registering driver.");                return -ENODEV;        }        //  proc_register( &proc_root, &pcimod_proc_entry );        CANMSG("CAN driver successfully installed.");        return 0;/* error: ;        del_mem_list();        unregister_chrdev( major, DEVICE_NAME );        return -ENODEV;*/}////////////////////////////////////////////////////////////////////////////////* * cleanup_module * * Called by rmmod. */void cleanup_module( void ){        //  proc_unregister( &proc_root, pcimod_proc_entry.low_ino );        if ( del_mem_list() ) {                CANMSG("Error deallocating memory");        }        if ( unregister_chrdev( major, DEVICE_NAME )) {                CANMSG("Error unregistering CAN driver." );        }        CANMSG("CAN driver removed from the system." );        return;}////////////////////////////////////////////////////////////////////////////////* * parse_args * * Helper for init_module. Parses the insmod arguments and creates the * structures the driver works with. */int parse_args( struct canhardware_t *pghw ){        u16 cnt_hw = 0;              /* Counter for chips ( hardware ) */        u16 cnt_irq = 0;             /* counter for irq's */        u16 cnt_io = 0;              /* Counter for io addresses */        u16 cnt_minor = 0;           /* Counter for device id's */        if ( NULL == pghw ) {                return -EINVAL;        }        if ( ( hw[ 0 ] == NULL )) {                CANMSG("You must supply your type of hardware,                       interrupt numbers and io address.\n");                CANMSG("Example: # insmod can.o hw=hms30c7202_can irq=0x12 io=0x8002f000");                return -ENODEV;        }        /* Parse resources for all chips the user want us to work with */        while ( ( hw[ cnt_hw ] != NULL ) && ( cnt_hw < MAX_HW_CHIPS )) {                /* Another chip */                pghw->cnt_tot_chips++;                /* Allocate storage for the chip */                pghw->pchip[ cnt_hw ] =                        (struct chip_t *)kmalloc( sizeof(struct chip_t), GFP_KERNEL );                if ( pghw->pchip[ cnt_hw ] == NULL ) {                        return -ENOMEM;                } else {                        if ( add_mem_to_list( pghw->pchip[ cnt_hw ] ))                                return -ENOMEM;                }                /* Save baudrate */                pghw->pchip[ cnt_hw ]->baudrate = baudrate[ cnt_hw ];                /* Save time triggered mode settings */                pghw->pchip[ cnt_hw ]->time_triggered = time_triggered[ cnt_hw ];                pghw->pchip[ cnt_hw ]->time_trig_nanosec = 1000000 * (u64) time_trig_msec[ cnt_hw ];                /* Save message mode */                switch ( extended[ cnt_hw ] ) {                        case 1:                                pghw->pchip[ cnt_hw ]->init_msg_mode = 1; /* extended */                                break;                        //case 2:                        //        pghw->pchip[ cnt_hw ]->init_msg_mode = 2; /* standard + extended */                        //        break;                        default:                                pghw->pchip[ cnt_hw ]->init_msg_mode = 0; /* standard ( default ) */                                break;                }                if ( ( hw[ 0 ] != NULL ) &&  !strcmp( hw[ 0 ], "hms30c7202_can" )) {                        /****************************************************************                         *                * * * HMS30C7202 C-CAN device * * *                         *                         *                  1 io address and 1 irq is needed                         ***************************************************************/                        DEBUGMSG("Hardware: %s\n", hw[0] );                        if ( -1 == io[ cnt_io ] ) {                                CANMSG("hms30c7202_can: Missing needed io base address for chip");                                CANMSG("Example: # insmod can.o hw=hms30c7202_can irq=0x12 io=0x8002f000");                                return -EINVAL;                        }                        if ( -1 == irq[ cnt_irq ] ) {                                CANMSG("hms30c7202_can: Missing needed irq for chip");                                CANMSG("Example: # insmod can.o hw=hms30c7202_can irq=0x12 io=0x8002f000");                                return -EINVAL;                        }                        /* Initialize the device structures */                        if ( hms30c7202_init_hw_data( pghw->pchip[ cnt_hw ],                                                      cnt_hw,                                                      cnt_minor,                                                      (u32)io[ cnt_io ],                                                      (u8)irq[ cnt_irq ] )) {                                return -EINVAL;                        }                        cnt_io++;     /* Another io used */                        cnt_irq++;    /* Another irq used */                        cnt_minor += 32;  /* Another device */                } else {                        CANMSG( "Sorry, hardware \"%s\" is currently not supported.",                        hw[ cnt_hw ] );                        return -EINVAL;                }                cnt_hw++; /* next chip */        } /* while hw[] */        return 0;}////////////////////////////////////////////////////////////////////////////////* * list_hw * * list_hw is used when debugging is on to show the hardware layout */int list_hw( struct canhardware_t *pghw ){        int i,j;        CANMSG("Debug list of hardware resources" );        CANMSG("--------------------------------" );        CANMSG("Number of chips : %d", pghw->cnt_tot_chips);        for (i=0; i<pghw->cnt_tot_chips;i++) {                CANMSG("--------------------------------");                CANMSG("+Chip %d",i+1);                if (pghw->pchip[i]->ntype == CAN_CHIPTYPE_C_CAN)                        CANMSG("+Chiptype C-CAN");                else                        CANMSG("+Chiptype undefined");                CANMSG("+IRQ %d",pghw->pchip[i]->irq);                CANMSG("+Time trig mode %d",pghw->pchip[i]->time_triggered);                CANMSG("+Time trig cycle time %ld ms",                        (long)(pghw->pchip[i]->time_trig_nanosec / 1000000) );                CANMSG("+IO Base 0x%.8lx",(unsigned long)pghw->pchip[i]->base_addr);                CANMSG("+Virtual IO Base 0x%.8lx",(unsigned long)pghw->pchip[i]->vbase_addr);                CANMSG("+Number of message objects  : %d", pghw->pchip[i]->obj_cnt);                for (j=0;j<pghw->pchip[i]->obj_cnt;j++) {                        CANMSG("++Message Object %d -> Minor %d",j+1, pghw->pchip[i]->pmsgobj[j]->minor);                }                CANMSG("--------------------------------\n");        }        return 0;}////////////////////////////////////////////////////////////////////////////////* * can_poll * * Poll function through which the user can check if nonblocking read or write * access is possible. */unsigned int can_poll( struct file *filp, poll_table *wait ){        struct msgobj_t *pmsgobj;        unsigned int mask = 0;        int space;        if ( NULL == ( pmsgobj = filp->private_data ) ) {                CANMSG("Device is not correctly configured.");                CANMSG("Please reload the driver.");                return -1;        }        poll_wait( filp, &pmsgobj->fifo->readq, wait );        poll_wait( filp, &pmsgobj->fifo->writeq, wait );        if ( pmsgobj->fifo->rxrp != pmsgobj->fifo->rxwp )                mask |= POLLIN | POLLRDNORM; /* Readable */        space = ((int)pmsgobj->fifo->txwp < (int)pmsgobj->fifo->txrp ) ?                ((int)pmsgobj->fifo->txrp - (int)pmsgobj->fifo->txwp ) :                ((int)pmsgobj->fifo->txrp - (int)pmsgobj->fifo->txwp +                (int)pmsgobj->fifo->txsize);        if ( 0 != space )                mask |= POLLOUT | POLLWRNORM; /* Writable */        return mask;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -