阅读:1377回复:3
请教高手,本程序如何在kernel2.4下运行?可在2.2下运行
/**********************************************************
* Module Name: ql5232.c * Description: kernel driver for Linux * Notes: none * Author: sirroom * Date: 2001-6-27 13:37 * Reference: ***********************************************************/ /********************************************************** Modification history: ===================== Date: By: Reason: ===================== Date: By: Reason: ===================== Date: By: Reason: *********************************************************/ #ifndef __KERNEL__ #define __KERNEL__ #endif #define __NO_VERSION__ #include <linux/module.h> #include <linux/version.h> const char kernel_version[] = UTS_RELEASE; #include <linux/pci.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/time.h> #include <linux/ioctl.h> #include <linux/errno.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/param.h> #include <asm/current.h> #include <asm/ptrace.h> #include <asm/system.h> #include <asm/segment.h> /***************** 加上你自己的.h吧 #include \"xxx.h\" #include \"xxx.h\" #include \"xxx.h\" ******************/ /////////////////////////////////////////////////////////// //// GLOBAL(S) ////-------------------------------------------------------- //// global variables static unsigned int chips = 0; static int major_devnum = 0; static CHIP_INFO chip_info[MAX_CHIP]; static int init_flag = 0; //// interrupt variables static unsigned int ReadComplete; static unsigned int WriteComplete; static unsigned int StartRead; static unsigned int StartWrite; static unsigned char InterruptLine; static struct wait_queue * wait_intr = NULL; //// ioremap variables static unsigned int base_address[MAX_CHIP] = {0}; static unsigned int space_length[MAX_CHIP] = {0}; static unsigned int *remap_addr[MAX_CHIP]= {NULL}; //// dma transfer variables static unsigned int pmem_for_chip_inputdata; static unsigned int pmem_for_chip_outputdata; static char * vmem_for_usr_output; static char * vmem_for_usr_input; static ssize_t kf_read( struct file *sp_file, char *buff, size_t count, loff_t *offvalue); static ssize_t kf_write( struct file *sp_file, const char *buff, size_t count, loff_t *offvalue); static int kf_open( struct inode *inode, struct file *filp); static void kf_release( struct inode *inode, struct file *filp); static int kf_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned int arg); ////-------------------------------------------------------- //// export symbols (unregister_chrdev) struct file_operations file_ops = { NULL, (ssize_t(*)())kf_read, (ssize_t(*)())kf_write, NULL, NULL, (int(*)())kf_ioctl, NULL, (int(*)())kf_open, NULL, (int(*)())kf_release, NULL, NULL, NULL, NULL, NULL}; //////////////////////////////////////////////////////////// //// FUNCTION(S) ////-------------------------------------------------------- //// chip base functions //// calculate address static inline void address_reg(unsigned int chip_id) { unsigned int *base = 0; //++ remap physical address to virtual address !!! // function \"ioremap\" extern in /asm/io.h base = (unsigned int *)ioremap(base_address[chip_id], space_length[chip_id]); // save address maped for release remap_addr[chip_id] = base; //100h chip_info[chip_id].addr.dma_length= base+QL_DMA_COUNT_REG/sizeof(unsigned int); //104h chip_info[chip_id].addr.dma_write_address= base+QL_DMA_WRITE_ADDRESS_REG/sizeof(unsigned int); //108h chip_info[chip_id].addr.dma_read_address= base+QL_DMA_READ_ADDRESS_REG/sizeof(unsigned int); //10ch chip_info[chip_id].addr.dma_control_status_reg= base+QL_DMA_CONTROL_STATUS_REG/sizeof(unsigned int); //18ch chip_info[chip_id].addr.int_control_status_reg= base+QL_INT_CONTROL_STATUS_REG/sizeof(unsigned int); //800h chip_info[chip_id].addr.microcode= base+QL_CODE_ADDRESS/sizeof(unsigned int); } //1. reset QLogic chip static inline int reset_chip(unsigned int chip_id) { *chip_info[chip_id].addr.int_control_status_reg=QLOGIC_RESET; return 0; } //2. load micro code to 800h static inline void load_code( unsigned int chip_id, unsigned int *p_microcode) { copy_from_user( chip_info[chip_id].addr.microcode, p_microcode, 1152); } //3.Send DMA read and write parameter static inline void QL_SEND_DMA_PARA(unsigned int chip_id, unsigned short ReadLength, unsigned short WriteLength, unsigned int ReadAddress, unsigned int WriteAddress) { //据说有什么自动左移,偶先来个右移 unsigned short *p1,*p2; unsigned int ReadAddress_new,WriteAddress_new; ReadAddress_new=ReadAddress>>2; WriteAddress_new=WriteAddress>>2; p1=&ReadLength; p2=&WriteLength; //send DMA read Length memcpy(chip_info[chip_id].addr.dma_length, p1-1, 4); //send DMA write Length memcpy(chip_info[chip_id].addr.dma_length, p2, sizeof(unsigned short)); //send DMA read address memcpy(chip_info[chip_id].addr.dma_read_address, &ReadAddress_new, sizeof(unsigned int)); //send DMA write address memcpy(chip_info[chip_id].addr.dma_write_address, &WriteAddress_new, sizeof(unsigned int)); } //4. write c1000100 to 10ch,start DMA transfer static inline void start_dma_transfer(unsigned int chip_id) { //unsigned int cmd_status; unsigned int instruction; struct pci_dev *p_dev = NULL; WriteComplete = 0; ReadComplete = 0; StartWrite = 1; StartRead = 1; p_dev = pci_find_device( QL_5232_VENDORID, QL_5232_DEVICEID, p_dev); if(p_dev == NULL){ return; } //config master pci_write_config_word(p_dev, 0x4, 0x6); pci_write_config_dword( p_dev, 0x08, 0x0); pci_write_config_dword( p_dev, 0x0c, 0x4000); instruction = QL_start_dma;//0xc1000100 memcpy( chip_info[chip_id].addr.dma_control_status_reg, &instruction, sizeof(unsigned int)); } //5. test 0,8,9,24,25 bit in 10ch.All bit is 0 stands for DMA transfer completed static inline int wait_done(unsigned int chip_id) { unsigned int counter = 0; //printk(\"enter wait_done\\n\"); //10ch 0,8,9,24,25 is zero while(counter < MAX_LOOP){ if(!(test_bit(0, chip_info[chip_id].addr.dma_control_status_reg)) &&(!test_bit(8, chip_info[chip_id].addr.dma_control_status_reg)) &&(!test_bit(9, chip_info[chip_id].addr.dma_control_status_reg) ) &&(!test_bit(24, chip_info[chip_id].addr.dma_control_status_reg)) &&(!test_bit(25, chip_info[chip_id].addr.dma_control_status_reg))) { return 0; } counter ++; } printk(\"Wait_done time out!\\n\"); printk(\"chip_info[chip_id].addr.dma_control_status_reg is 0x%x\\n\", *chip_info[chip_id].addr.dma_control_status_reg); printk(\"leave wait_done\\n\"); return -1; } ////------------------------------------------------------------------------- ////Enable interrupt static inline void EnableQLogicInterrupt(unsigned int chip_id) { unsigned int ICSR; memcpy( &ICSR, chip_info[chip_id].addr.int_control_status_reg, 4); ICSR=ICSR|ENABLE_DMA_WRITE_INT|ENABLE_QLOGIC_INT; memcpy( chip_info[chip_id].addr.int_control_status_reg, &ICSR, 4); } ////------------------------------------------------------------------------- ////Disable interrupt static inline void DisableQLogicInterrupt(unsigned int chip_id) { memset(chip_info[chip_id].addr.int_control_status_reg, 0, 4); } ////---------------------------------------------------------------------- //// I/O control specified functions static inline void ioctl_initial(INIT_INFO *arg) { int index, pass; unsigned int ret; if(init_flag == 1){ ret = SJW17_SUCCESS; copy_to_user(arg->status, &ret, sizeof(unsigned int)); ret = chips; copy_to_user(arg->chips, &ret, sizeof(unsigned int)); return; } pass = 0; // try to initial all chips found for(index=0; index<chips; index++){ // reset the specified chip if(reset_chip(index) != 0){ printk(\"v2_drv: reset chip %d [FAIL]\\n\", index); continue; } //load micro code to instruction memory of the specified chip load_code(index, arg->p_microcode); // set ready flag of the specified chip chip_info[index].ready_flag = 1; pass = 1; } // no chip can work !!! if(pass == 0){ ret = SJW17_FAIL_CHIP_ALLFAIL; copy_to_user(arg->status, &ret, sizeof(unsigned int)); } else{ ret = SJW17_SUCCESS; copy_to_user(arg->status, &ret, sizeof(unsigned int)); init_flag = 1; } ret = chips; copy_to_user(arg->chips, &ret, sizeof(unsigned int)); } static inline void ioctl_reset(unsigned int chip_id) { // reset the specified chip if(reset_chip(chip_id) != 0){ printk(\"v2_drv: reset chip %X [FAIL]\\n\", chip_id); return; } } static inline int ioctl_activity( unsigned int chip_id, ACTION_INFO *arg) { unsigned int ret,interrupt_flags; // check if the specified chip is ready if(chip_info[chip_id].ready_flag != 1){ printk(\"v2_drv: no ready %X [FAIL]\\n\", chip_id); ret = SJW17_FAIL_CHIP_NOREADY; copy_to_user(arg->status, &ret, sizeof(unsigned int)); return -1; } DisableQLogicInterrupt(chip_id); /* printk(\"After Disable interrupt,int_reg is 0x%8x\\n\", *chip_info[chip_id].addr.int_control_status_reg); */ //++ step 1 if(arg->InputLength > MAX_CACHE_LENGTH){ printk(\"<1>error: SJW17_FAIL_CMD_INVALID_INPUTLENGTH\\n\"); return -1; } // Check required data length if(arg->OutputLength > MAX_CACHE_LENGTH){ printk(\"<1>error:SJW17_FAIL_CMD_INVALID_OUTPUTLENGTH\\n\"); return -1; } copy_from_user(vmem_for_usr_input, arg->pRbuf, (arg->InputLength*4)); QL_SEND_DMA_PARA(chip_id, arg->InputLength, arg->OutputLength, pmem_for_chip_inputdata, pmem_for_chip_outputdata); start_dma_transfer(chip_id); EnableQLogicInterrupt(chip_id); /* printk(\"After Enable Interrupt,int_reg is 0x%8x\\n\", *chip_info[chip_id].addr.int_control_status_reg); */ save_flags(interrupt_flags); cli(); if( !WriteComplete ){ interruptible_sleep_on_timeout(&wait_intr,2*HZ); } restore_flags(interrupt_flags); if( WriteComplete ){ DisableQLogicInterrupt(chip_id); copy_to_user( arg->pWbuf, vmem_for_usr_output, arg->OutputLength*4); ret = SJW17_SUCCESS; copy_to_user(arg->status, &ret, sizeof(unsigned int)); } else /*calculate again*/ { printk(\"v2_kernel:time out!!!\\n\"); return -1; } return 0; // wait the specified chip idle /* if(wait_done(chip_id) == -1){ printk(\"v2_drv: time out %X [FAIL]\\n\", chip_id); ret = SJW17_FAIL_CHIP_TIMEOUT; copy_to_user(arg->status, &ret, sizeof(unsigned int)); return -1; } //printk(\"copy output data to upper layer\\n\"); copy_to_user( arg->pWbuf, vmem_for_usr_output, arg->OutputLength*4); ret = SJW17_SUCCESS; copy_to_user(arg->status, &ret, sizeof(unsigned int)); */ //return 0; } static void v2_handler( //unsigned int chip_id, int qlogicx , void * dev_id, struct pt_regs * pqlogicx) //unsigned int chip_id) { unsigned int interrupt_flags; unsigned int InterruptStatus; unsigned int chip_id=0; //unsigned int ICSR; //printk(\"enter v2_handler\\n\"); save_flags(interrupt_flags); cli(); /* Read Interrupt Registers*/ InterruptStatus=*chip_info[chip_id].addr.int_control_status_reg; /* If QLOGIC_ASSERTED_INT is set, it\'s QLOGIC\'s interrupt */ if((InterruptStatus & QLOGIC_ASSERTED_INT) != 0){ //Class or Type Error if((InterruptStatus &CLASS_ERROR_INT) != 0){} //READ_TRANSFER_COMPLETE_INTERUPPT HANDLE if((InterruptStatus & READ_TC_INT) != 0){ InterruptStatus= InterruptStatus|QLOGIC_ASSERTED_INT|READ_TC_INT; *chip_info[chip_id].addr.int_control_status_reg= InterruptStatus; if( StartRead ){ ReadComplete = 1; StartRead = 0; } } //WRITE_TRANSFER_COMPLETE_INTERUPPT HANDLE if( ( InterruptStatus & WRITE_TC_INT ) != 0){ InterruptStatus= InterruptStatus|QLOGIC_ASSERTED_INT|WRITE_TC_INT; *chip_info[chip_id].addr.int_control_status_reg= InterruptStatus; if( StartWrite ) { WriteComplete = 1; StartWrite = 0; //Wakeup process wake_up_interruptible( &wait_intr ); } DisableQLogicInterrupt(chip_id); } } restore_flags(interrupt_flags); //printk(\"leave v2_handler\\n\"); } ////---------------------------------------------------------------------- //// interface functions int init_module(void) { //unsigned int my_print; int index, result; struct pci_dev *p_dev = NULL; int mask,interRet; //++ 1: initial globals mask = 0; chips = 0; major_devnum = 0; memset(base_address, 0, sizeof(unsigned int) * MAX_CHIP); memset(chip_info, 0, sizeof(CHIP_INFO) * MAX_CHIP); //++ 2: search for v2-800 and get base memory address if(!pci_present()){ printk(\"v2_drv: find PCI bus [FAIL]\\n\"); return -ENODEV; } //printk(\"base valus is 0x\\n\", for(index=0; index<MAX_CHIP; index++){ p_dev = pci_find_device( QL_5232_VENDORID, QL_5232_DEVICEID, p_dev); if(p_dev == NULL){ break; } //chips ++; pci_read_config_byte( p_dev, PCI_INTERRUPT_LINE, &InterruptLine); pci_read_config_dword( p_dev, PCI_BASE_ADDRESS_0, &base_address[index]); pci_write_config_dword( p_dev, PCI_BASE_ADDRESS_0, ~0); pci_read_config_dword( p_dev, PCI_BASE_ADDRESS_0, &mask); pci_write_config_dword( p_dev, PCI_BASE_ADDRESS_0, base_address[index]); space_length[index] = (~mask + 1); pci_write_config_word(p_dev, PCI_COMMAND, //QL_config_master); 0x162); //register interrupt handler interRet=request_irq( InterruptLine, v2_handler, SA_INTERRUPT|SA_SHIRQ, \"v2-800\", NULL); printk(\"chip_id is %d\\n\",chips); chips ++; } if(chips == 0){ printk(\"v2_drv: find v2-800 [FAIL]\\n\"); return -ENODEV; } //printk(\"v2_drv: find v2 800 * %X [ OK ]\\n\", chips); //++ calcualte address for 6500(s) for(index=0; index<chips; index++){ address_reg(index); } // Allocate 1 dma page if((pmem_for_chip_inputdata = __get_dma_pages(GFP_KERNEL,0))==0){ printk(\"__get_dma_pages() fail \\n\"); return -EFAULT; } if((pmem_for_chip_outputdata = __get_dma_pages(GFP_KERNEL,0))==0){ printk(\"__get_dma_pages() fail \\n\"); return -EFAULT; } //conver between virtual address and physical address vmem_for_usr_input = (char *)phys_to_virt(pmem_for_chip_inputdata); vmem_for_usr_output = (char *)(phys_to_virt(pmem_for_chip_outputdata)); pmem_for_chip_inputdata = virt_to_phys(vmem_for_usr_input); pmem_for_chip_outputdata = virt_to_phys(vmem_for_usr_output); //printk(\"pmem_for_chip_inputdata is 0x%x\\n\",pmem_for_chip_inputdata); //printk(\"pmem_for_chip_outputdata is 0x%x\\n\",pmem_for_chip_outputdata); //++ register character device (ask for a dynamic major) result = register_chrdev( major_devnum, DRIVER_NAME, &file_ops); if(result < 0){ printk(\"v2_drv: register driver [FAIL]\\n\"); return result; } if( major_devnum == 0 ){ major_devnum = result; } printk(\"v2_drv: module insert [ OK ]\\n\"); return 0; } void cleanup_module(void) { int index; //free mem allocate in init_module free_pages( (unsigned int )pmem_for_chip_inputdata, 0 ); free_pages( (unsigned int )pmem_for_chip_outputdata, 0 ); //++ unregister character device for(index=0; index<chips; index++){ iounmap(remap_addr[index]); free_irq(InterruptLine, NULL ); //vfree(remap_addr[index]); } unregister_chrdev(major_devnum, DRIVER_NAME); printk(\"v2_drv: module clean [ OK ]\\n\"); } static ssize_t kf_read( struct file *sp_file, char *buff, size_t count, loff_t *offvalue) { // printk(\"v2_drv: module read [ OK ]\\n\"); return 0; } static ssize_t kf_write( struct file *sp_file, const char *buff, size_t count, loff_t *offvalue) { // printk(\"v2_drv: module write [ OK ]\\n\"); return 0; } static int kf_open( struct inode *inode, struct file *filp) { // printk(\"v2_drv: module open [ OK ]\\n\"); return 0; } static void kf_release( struct inode *inode, struct file *filp) { // printk(\"v2_drv: module release [ OK ]\\n\"); } static int kf_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned int arg) { int err = 0; unsigned int dev_minor = MAX_CHIP + 1; //++ extract the type and number bitfields, and don\'t decode if(_IOC_TYPE(cmd) != IOCC_MAGIC_){ printk(\"v2_drv: control code [FAIL]\\n\"); return -EINVAL; } if(_IOC_NR(cmd) > IOCC_MAXNR_){ printk(\"v2_drv: control code [FAIL]\\n\"); return -EINVAL; } //++ verify memory address err = verify_area( VERIFY_READ, (void *)arg, sizeof(unsigned int) * 3); if(err != 0){ printk(\"v2_drv: verify area [FAIL]\\n\"); return err; } //++ decode minor device number (chip id) dev_minor = MINOR(inode->i_rdev); if((dev_minor < 0)||(dev_minor > chips - 1)){ printk(\"v2_drv: chip id : %X [FAIL]\\n\", dev_minor); return -EINVAL; } // printk(\"v2_drv: chip id : %d [ OK ]\\n\", dev_minor); //++ decode control code switch(cmd){ case IOCC_RESERVED: // printk(\"v2_drv: IOCC_RESERVED [ OK ]\\n\"); break; case IOCC_INITIAL: ioctl_initial((INIT_INFO *)arg); // printk(\"v2_drv: IOCC_INITIAL [ OK ]\\n\"); break; case IOCC_RESET: ioctl_reset(dev_minor); // printk(\"v2_drv: IOCC_RESET [ OK ]\\n\"); break; case IOCC_ACTIVITY: ioctl_activity(dev_minor, (ACTION_INFO *)arg); break; case IOCC_REINITIAL: // ioctl_reinitial(dev_minor); break; case IOCC_DEBUGONLY: // printk(\"v2_drv: IOCC_DEBUGONLY [ OK ]\\n\"); // ioctl_debugonly(dev_minor); break; default: printk(\"v2_drv: control code [FAIL]\\n\"); return -EINVAL; } return 0; } |
|
|
沙发#
发布于:2001-12-24 17:49
ft.格式都变了哦
|
|
|
板凳#
发布于:2002-02-05 14:39
当然不可以, 有很多的东西要改
|
|
地板#
发布于:2002-03-28 21:26
说一下三。
|
|
|