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

📄 pmacisa.c~

📁 linux 内核版本2.6.18下的pmac运动控制卡驱动源程序
💻 C~
📖 第 1 页 / 共 2 页
字号:
		sprintf(str, "wx$70009,$%X,$%X",d1,d2);		write_line_port(minor, str, &status);		read_line_port(minor, str, &status);		sprintf(str, "I93=$%X I94=$%X",d1,d2);		write_line_port(minor, str, &status);		read_line_port(minor, str, &status);	}else{		sprintf(str, "wx$E009,$%X,$%X",d1,d2);		write_line_port(minor, str, &status);		read_line_port(minor, str, &status);		sprintf(str, "wx$786,$%X,$%X",d1,d2);		write_line_port(minor, str, &status);		read_line_port(minor, str, &status);	}	return 0;}   /*dpr_initialize() intializes the dpr register variables in _Pmac_Device structure    *depending on the pmac device type   */int dpr_initialize(unsigned int minor){	struct _Pmac_Device *device = &pmac_dev[minor];	if(device->type > PT_PMAC){	/** Is it Turbo! */		device->reg_write_status = 0x0E9C;		device->reg_read_status = 0x0F40;		device->reg_ctrl_char = 0x0E9E;		device->reg_num_char = 0x0F42;		device->reg_write = 0x0EA0;		device->reg_read = 0xF44;	}else{		device->reg_write_status = 0x062C;		device->reg_read_status = 0x06D0;		device->reg_ctrl_char = 0x062E;		device->reg_num_char = 0x06D2;		device->reg_write = 0x0630;		device->reg_read = 0x06D4;	}	return 0;}   /*get_pmac_param() is used only in pmac_read_procmem to fill proc entries    *and in pmac_intialize() to find the type of the pmac   */int get_pmac_param(unsigned int minor, char *buffer, char *pmac_cmd){	int status, len=0;	int result = 0;	char cdummy[256];	flush_port(minor);	write_line_port(minor, pmac_cmd, &status);	if (status == COMM_OK)	{		len=read_line_port(minor, buffer, &status);		if (status == COMM_EOT)		{		    buffer[--len]=NULL_CHR;		    result = 1; 		}		else if(status == COMM_OK) // get the ACK as well		{		    read_line_port(minor, cdummy, &status);		    if(status == COMM_EOT)			result = 1;		}		result = 0;	}	return result;}   /*pmac_initialize() initializes the pmac at the very first communication    */int pmac_initialize(unsigned int minor){	int nt = 0, result = -1;	char type[20];	outb_p(0, PMAC_LO_INIT(minor));	outb_p(0, PMAC_HI_INIT(minor));	while(nt++ < pmac_timeout_cnt)	{	    udelay(delay_per_try);	}	result=flush_port(minor);	result=flush_port(minor);	if (result < 0) 	{		printk (KERN_NOTICE "pmac isa: pmac_initialize failure at port 0x%X with result %d\n", PMAC_HOST_BASE(minor),result);		return result; // failure	}	pmac_dev[minor].type = PT_UNKNOWN;		get_pmac_param(minor, type, "type\0");	if(strstr(type, "PMAC1"))	    pmac_dev[minor].type = PT_PMAC1;	else if(strstr(type, "PMAC2"))	    pmac_dev[minor].type = PT_PMAC2;	else if(strstr(type, "PMACU"))	    pmac_dev[minor].type = PT_PMACUL;	else if(strstr(type, "TURBO1"))	    pmac_dev[minor].type = PT_PMAC1T;	else if(strstr(type, "TURBO2"))	    pmac_dev[minor].type = PT_PMAC2T;	else if(strstr(type, "TURBOU"))	    pmac_dev[minor].type = PT_PMACUT;	printk (KERN_NOTICE "pmac isa: pmac_initialize gets pamctype %d at port 0x%X\n", pmac_dev[minor].type, PMAC_HOST_BASE(minor));		if(pmac_dev[minor].type == PT_UNKNOWN)	    return 0;	else  // success	    return 1;}   /*pmac_find_hardware() checks if card is in slot. if not the response will   *be an infinite array of 0xFF   */int pmac_find_hardware (unsigned int minor){    int nt = 0, result = -1;        outb_p(0,PMAC_LO_INIT(minor));    outb_p(0,PMAC_HI_INIT(minor));    outb_p(0,PMAC_STATUS(minor));	    while(nt++ < pmac_timeout_cnt)    {	udelay(delay_per_try);    }    result = flush_port(minor);    result = flush_port(minor);    if (result < 0)     {	printk (KERN_NOTICE "pmac isa: pmac_find_hardware failure at port 0x%X with result %d\n", PMAC_HOST_BASE(minor),result);	return result;    }    return 0;}   /*pmac_read_procmem() fills up the proc entry /proc/pmacisa   */int pmac_read_procmem(char *buff, char **start, off_t offset, int count, int *eof, void *data){	unsigned int device, len=0;	char type[20], version[15], date[15];	len += sprintf(buff+len, "%s\n", driver_name);	len += sprintf(buff+len, "Total ISA Devices %d\n", pmac_dev_no);	device=0;	for(device=0; device<pmac_dev_no; device++){		len += sprintf(buff+len, "Device %d\n", device);		len += sprintf(buff+len, "\tPort 0x%X, DPR Base 0x%lX\n", pmac_dev[device].host, pmac_dev[device].dpr);		get_pmac_param(device, type, "type\0");		get_pmac_param(device, version, "version\0");		get_pmac_param(device, date, "date\0");		len += sprintf(buff+len, "\tType %s, Version %s, Date %s:\n", type, version, date);	}	return len;}///////////////////////////system call implementation for pmac////////////////////////////////int pmac_open (struct inode *inode, struct file *filp){	unsigned int minor = MINOR(inode->i_rdev);	if(minor >= pmac_dev_no)		return -ENODEV;	if(!(pmac_dev[minor].has_region))		return -ENODEV;	/*MOD_INC_USE_COUNT;*/	return 0;}int pmac_release (struct inode *inode, struct file *filp){	/*MOD_DEC_USE_COUNT;*/	return 0;}int pmac_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){	int err = 0, result = 0;	struct _Device_Ext *pdx, *parg;	unsigned int minor = MINOR(inode->i_rdev);	if (_IOC_TYPE(cmd) != IOCTL_MOTION_BASE) return -ENOTTY; // extract the type and number bitfields, and don't decode wrong cmds	if (_IOC_NR(cmd) > IOCTL_MAXNR) return -ENOTTY;	if (_IOC_DIR(cmd) & _IOC_READ)     //The concept of "read" and "write" is reversed in following		err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));	else if (_IOC_DIR(cmd) & _IOC_WRITE)		err =  !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));	if (err) return -EFAULT;	parg = (struct _Device_Ext *) arg;	pdx = &pmac_dev[minor].ext;	switch(cmd){		case IOCTL_MOTION_INIT:			outb_p(0, PMAC_LO_INIT(minor));			outb_p(0, PMAC_HI_INIT(minor));			result = 0;			break;		case IOCTL_MOTION_FLUSH_PORT:			result = flush_port(minor);			break;		case IOCTL_MOTION_PORT_READREADY:     //return 0 if ready to read else return -ve value			if (!(PMAC_RDY_TO_SEND(minor)))				return -EBUSY;			result = 0;			break;		case IOCTL_MOTION_READLN_PORT:			result = read_line_port(minor, pdx->buffer, &pdx->status);			if(copy_to_user(parg, pdx, sizeof (struct _Device_Ext)))				return -EFAULT;			break;		case IOCTL_MOTION_WRITELN_PORT:			if (copy_from_user(pdx, parg, sizeof (struct _Device_Ext)))				return -EFAULT;			result = write_line_port(minor, pdx->buffer, &pdx->status);			break;		case IOCTL_MOTION_WRITECHAR_PORT:			if (copy_from_user(pdx, parg, sizeof (struct _Device_Ext)))				return -EFAULT;			result = write_char_port(minor, pdx->buffer[0]);     //character to be written to port is at buffer[0]			break;		case IOCTL_WRITECHAR_PORT:			if (copy_from_user(pdx, parg, sizeof (struct _Device_Ext)))				return -EFAULT;			outb_p(PMAC_HOST_BASE(minor) + pdx->buffer[0], pdx->buffer[1]);  //offset is at buffer[0] and character at buffer[1]			result = 0;			break;		case IOCTL_READCHAR_PORT:			if (copy_from_user(pdx, parg, sizeof (struct _Device_Ext)))				return -EFAULT;			pdx->buffer[1]=inb_p(PMAC_HOST_BASE(minor) + pdx->buffer[0]);   //data read from offset buffer[0] is stored in buffer[1]			if(copy_to_user(parg, pdx, sizeof (struct _Device_Ext)))				return -EFAULT;			result = 0;			break;		case IOCTL_MOTION_CTRLRESP_PORT:			if (copy_from_user(pdx, parg, sizeof (struct _Device_Ext)))				return -EFAULT;			result = get_ctrl_resp(minor, pdx->buffer, &pdx->status);			if(copy_to_user(parg, pdx, sizeof (struct _Device_Ext)))				return -EFAULT;			break;		case IOCTL_MOTION_FLUSH_MEM:			result = flush_mem(minor);			break;		case IOCTL_MOTION_MEM_READREADY:			if (!(DPR_READ_READY(minor)))				return -EBUSY;			result = 0;			break;		case IOCTL_MOTION_READLN_MEM:			result = read_line_mem(minor, pdx->buffer, &pdx->status);			if(pdx->status == COMM_ERROR){				pdx->err_code = result;				result=0;			}			if(copy_to_user(parg, pdx, sizeof (struct _Device_Ext)))				return -EFAULT;			break;		case IOCTL_MOTION_WRITELN_MEM:			if (copy_from_user(pdx, parg, sizeof (struct _Device_Ext)))				return -EFAULT;			result = write_line_mem(minor, pdx->buffer, &pdx->status);			break;		case IOCTL_MOTION_WRITECHAR_MEM:			if (copy_from_user(pdx, parg, sizeof (struct _Device_Ext)))				return -EFAULT;			result = write_char_mem(minor, pdx->buffer[0]);     //character to be written to port is at buffer[0]			break;		case IOCTL_MOTION_WRITECTRL_MEM:			if (copy_from_user(pdx, parg, sizeof (struct _Device_Ext)))				return -EFAULT;			result = write_char_mem(minor, pdx->buffer[0]);     //character to be written to port is at buffer[0]			break;		case IOCTL_MOTION_GET_MEM:			result = get_mem(minor, pdx->buffer, &pdx->status, pdx->dpr_offset, pdx->dpr_count);			if(copy_to_user(parg, pdx, sizeof (struct _Device_Ext)))				return -EFAULT;			break;		case IOCTL_MOTION_SET_MEM:			if (copy_from_user(pdx, parg, sizeof (struct _Device_Ext)))				return -EFAULT;			result = set_mem(minor, pdx->buffer, &pdx->status, pdx->dpr_offset, pdx->dpr_count);			break;		case IOCTL_MOTION_CTRLRESP_MEM:			if (copy_from_user(pdx, parg, sizeof (struct _Device_Ext)))				return -EFAULT;			result = get_ctrl_resp_mem(minor, pdx->buffer, &pdx->status);			if(copy_to_user(parg, pdx, sizeof (struct _Device_Ext)))				return -EFAULT;			break;		case IOCTL_MOTION_DPRAM:			result = pmac_dev[minor].has_memory;			break;	}	return result;}/**ssize_t pmac_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos) {	unsigned char *kbuf=kmalloc(count, GFP_KERNEL);	unsigned int minor = MINOR(filp->f_dentry->d_inode->i_rdev);	if(!pmac_dev[minor].has_memory)		return -EPERM;	if (!kbuf) return -ENOMEM;	if(count > 0 && count < PMAC_DPR_SIZE(minor))		if((*f_pos + (unsigned long)count) > (PMAC_DPR_VADD(minor) + PMAC_DPR_SIZE(minor))){			return -ENXIO;		}	if (copy_from_user(kbuf, buf, count))		return -EFAULT;	memcpy_toio(f_pos, kbuf, count);	kfree(kbuf);	return count;}ssize_t pmac_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) {	unsigned char *kbuf=kmalloc(count, GFP_KERNEL);	unsigned int minor = MINOR(filp->f_dentry->d_inode->i_rdev);	if (!kbuf) return -ENOMEM;	if(!pmac_dev[minor].has_memory)		return -EPERM;	if(count > 0 && count < PMAC_DPR_SIZE(minor))		if((*f_pos + (unsigned long)count) > (PMAC_DPR_VADD(minor) + PMAC_DPR_SIZE(minor))){			return -ENXIO;		}	memcpy_fromio(kbuf, f_pos, count);	if ( (count > 0) && copy_to_user(buf, kbuf, count))		retval = -EFAULT;	kfree(kbuf);	return count;}**/////////////////////////////////Declaration of File Operations///////////////////////////////struct file_operations pmac_fops = {        .owner = THIS_MODULE,//	read:		pmac_read,//	write:	pmac_write,	.ioctl = pmac_ioctl,	.open = pmac_open,	.release = pmac_release,};////////////////////////module init and clean up/////////////////////////////////////////////	/*Release IO Region, Memory Region and major node number	 */void pmac_cleanup_module(void){	unsigned int minor;	for(minor=0; minor<PMAC_NO; minor++){		if(host[minor]==0) break;		if(pmac_dev[minor].has_region){			release_region (PMAC_HOST_BASE(minor), PMAC_HOST_RANGE);		}		if(pmac_dev[minor].has_region && pmac_dev[minor].has_memory){			release_mem_region(PMAC_DPR_BASE(minor), PMAC_DPR_SIZE(minor));			iounmap(pmac_dev[minor].dpr_vadd);		}	}	if(proc_pmac_dir)		remove_proc_entry("pmacisa", proc_pmac_dir);	unregister_chrdev (major, "pmacisa");	printk (KERN_NOTICE "pmac isa: Driver Unloaded successfully\n");}	/*all intializing stuff...	*/int pmac_init_module (void) {	int result;	unsigned int minor;	struct proc_dir_entry* temp;	/*EXPORT_NO_SYMBOLS;*/	if ((result=register_chrdev (major, "pmacisa", &pmac_fops)) < 0) {    // Attempt to register the major node number of the PMAC.		printk (KERN_WARNING "pmac isa: Can't get major number %d\n", major);		return result;	}	if(major==0)		major=result;	for(temp=proc_root_driver->subdir; temp; temp=temp->next)		if (strstr(temp->name, "pmac"))			proc_pmac_dir = temp;	if(!proc_pmac_dir)		proc_pmac_dir = proc_mkdir("pmac", proc_root_driver);	if(proc_pmac_dir)		create_proc_read_entry("pmacisa", 0, proc_pmac_dir, pmac_read_procmem, NULL);	for(minor=0; minor<PMAC_NO; minor++){		if(host[minor]==0) break;		pmac_dev[minor].host = host[minor];		pmac_dev[minor].range = PMAC_HOST_RANGE;		pmac_dev[minor].dpr = dpr[minor];		pmac_dev[minor].size = PMAC_DPR_LENGTH;		if (pmac_find_hardware(minor)<0)		{		    printk(KERN_WARNING "pmac isa: pmac_find_hardware failure at port 0x%X\n", PMAC_HOST_BASE(minor));		    continue;		}		if(check_region(PMAC_HOST_BASE(minor), PMAC_HOST_RANGE)<0){  // Check IO Region for PMAC communication.			printk(KERN_WARNING "pmac isa: Can't allocate port 0x%X\n", PMAC_HOST_BASE(minor));			pmac_dev[minor].has_region=0;			continue;		}else{			request_region (PMAC_HOST_BASE(minor), PMAC_HOST_RANGE, driver_name);  //Request io and memory region			pmac_dev[minor].has_region=1;		}		if(pmac_initialize (minor) > 0)		{			pmac_dev_no++;			printk(KERN_WARNING "pmac isa: pmac_initialize Device number %d successful at port 0x%X\n", pmac_dev_no, PMAC_HOST_BASE(minor));					}		if(pmac_dev[minor].dpr!=0 && pmac_dev[minor].has_region){			if (check_mem_region(PMAC_DPR_BASE(minor), PMAC_DPR_SIZE(minor))<0){  // Check IO Memory for PMAC Dual Port Ram Communication.				printk(KERN_WARNING "pmac isa: Can't allocate memory for dual port ram at 0x%lX\n", PMAC_DPR_BASE(minor));				pmac_dev[minor].has_memory=0;				continue;			}else{				set_dpr_base(minor);  // set pmac dpr registers to required address				request_mem_region(PMAC_DPR_BASE(minor), PMAC_DPR_SIZE(minor), driver_name);				pmac_dev[minor].dpr_vadd = ioremap(PMAC_DPR_BASE(minor), PMAC_DPR_SIZE(minor));				pmac_dev[minor].has_memory=1;				dpr_initialize(minor);  // initialize the dpr register variables in pmac_dev			}		}else{			pmac_dev[minor].has_memory=0;			pmac_dev[minor].size=0;		//set size to zero if no dpr		}	}	printk(KERN_NOTICE "pmac isa: Driver successfully loaded, Total Devices: %d\n", pmac_dev_no);	return 0;}module_init(pmac_init_module);module_exit(pmac_cleanup_module);

⌨️ 快捷键说明

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