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

📄 pmacisa.c~

📁 linux 内核版本2.6.18下的pmac运动控制卡驱动源程序
💻 C~
📖 第 1 页 / 共 2 页
字号:
#ifndef __KERNEL__#  define __KERNEL__#endif#ifndef MODULE#  define MODULE#endif#include<linux/configfs.h>/*#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)#  define MODVERSIONS#endif#ifdef MODVERSIONS#  include<linux/modversions.h>#endif*/#include "pmacisa.h"#include<linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/proc_fs.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/mm.h>#include <linux/ioport.h>/////////////////////////#defines for immutable pmac properties//////////////////////#define PMAC_HOST_BASE(x)(pmac_dev[x].host)#define PMAC_HOST_RANGE 0x10		/**total 16 ports & can change*/#define PMAC_STATUS(x)(pmac_dev[x].host + 2)#define PMAC_LO_INIT(x)(pmac_dev[x].host + 5)#define PMAC_HI_INIT(x)(pmac_dev[x].host + 6)#define PMAC_DATA(x)(pmac_dev[x].host + 7)#define PMAC_DPR_BASE(x)(pmac_dev[x].dpr)#define PMAC_DPR_VADD(x)(pmac_dev[x].dpr_vadd)#define PMAC_DPR_SIZE(x)(pmac_dev[x].size)#define PMAC_DPR_LENGTH 0x4000		/**can change */#define PMAC_RDY_TO_RCV(x)((inb_p(PMAC_STATUS(x)) & 2) == 2)#define PMAC_RDY_TO_SEND(x)((inb_p(PMAC_STATUS(x)) & 1) == 1)#define DPR_READ_STATUS(x)(PMAC_DPR_VADD(x) + pmac_dev[x].reg_read_status)#define DPR_WRITE_STATUS(x)(PMAC_DPR_VADD(x) + pmac_dev[x].reg_write_status)#define DPR_REG_CTRL_CHAR(x)(PMAC_DPR_VADD(x) + pmac_dev[x].reg_ctrl_char)#define DRP_REG_NUM_CHAR(x)(PMAC_DPR_VADD(x) + pmac_dev[x].reg_num_char)#define DPR_REG_READ(x)(PMAC_DPR_VADD(x) + pmac_dev[x].reg_read)#define DPR_REG_WRITE(x)(PMAC_DPR_VADD(x) + pmac_dev[x].reg_write)#define DPR_NUM_CHARS(x)(readw(DRP_REG_NUM_CHAR(x)) - 1)#define DPR_READ_READY(x)(readw(DPR_READ_STATUS(x)) != 0)#define DPR_WRITE_READY(x)((readw(DPR_WRITE_STATUS(x)) & 0x0001) == 0)#define DPR_CLR_READ_READY(x)(writew(0, DPR_READ_STATUS(x)))#define DPR_CLR_WRITE_READY(x)(writew(0, DPR_WRITE_STATUS(x)))#define DPR_SET_WRITE_READY(x)(writew(1, DPR_WRITE_STATUS(x)))#define DPR_FLUSHED(x)((readw(DPR_READ_STATUS(x)) & 0x001F) == CTRL_X)#define DPR_ERROR(x)((readw(DPR_READ_STATUS(x)) & 0x8000) > 0)#define DPR_ERROR_CODE(x)(readw(DPR_READ_STATUS(x)) & 0x00FF)#define DPR_ACK(x)((readw(DPR_READ_STATUS(x)) & 0x000F) == ACK_CHR)#define DPR_CR(x)((readw(DPR_READ_STATUS(x)) & 0x000F) == CARRIAGE_RETURN)#define DPR_USER(x)((readw(DPR_READ_STATUS(x)) & 0x0300) != 0)MODULE_AUTHOR("chiefleo");MODULE_LICENSE("Dual BSD/GPL");///////////////////////////////GLOBAL VARIABLES/////////////////////////////////////static unsigned int major = 0;           /* major device number, can be specified or used 0 for dynamic allocation*/module_param(major, int, S_IRUGO);/*MODULE_PARM(major, "i");*/static unsigned int host[PMAC_NO]={0x210};                /* pmac host port address, default is 0x210 *//*MODULE_PARM(host, "0-7i");*/static unsigned long dpr[PMAC_NO]={0x0};    /* pmac Dual Port Ram base address, default is 0xD0000 *//*MODULE_PARM(dpr, "0-7i");*/static unsigned long pmac_timeout_cnt = 2000;  /* not implemented as desired...  */static unsigned int delay_per_try = 5;         /* micro seconds delay per try */static char driver_name[60]="Delta Tau Data Systems Inc. PMAC ISA";static int pmac_dev_no=0;            //total successfully initialized devicesstatic struct _Pmac_Device pmac_dev[PMAC_NO];static struct proc_dir_entry* proc_pmac_dir;/////////////////////////////////////PORT functions////////////////////////////////   /*write_char_port() writes a single character to data port and if not ready waits    *till time out. it returns the status of the communication    */int write_char_port(unsigned int minor, char outchar){	unsigned long timeout=0;	while(timeout++ < pmac_timeout_cnt){		if(PMAC_RDY_TO_RCV(minor)){			outb_p(outchar, PMAC_DATA(minor));			return COMM_OK;		}else		udelay(delay_per_try);	}	return COMM_TIMEOUT;}   /*write_line_port() writes a null terminated string of size 256 to data port,    *and writes the carriage return 0x0D(13) to end pmac command. it sets the    *status and returns the number of characters written to the port    */int write_line_port(unsigned int minor, char *buffer, int *status){	unsigned int nc=0;	int result=COMM_OK;	while(buffer[nc]!=NULL_CHR && nc<255 && result==COMM_OK)		result=write_char_port(minor, buffer[nc++]);	if(result==COMM_OK)		result=write_char_port(minor, CARRIAGE_RETURN);	*status=result;	return nc;}   /*read_line_port() reads data from data port. it does not send the ACK character back.    *it checks for watchdog or junk, terminates the buffer with null and sets the status    *accordingly and returns the number of character read    */int read_line_port(unsigned int minor, char *buffer, int *status){	unsigned long timeout=0;	int nc=0;	while(timeout<pmac_timeout_cnt && nc<256)        {		if(!PMAC_RDY_TO_SEND(minor))		{			udelay(delay_per_try);			timeout++;			continue;		}		buffer[nc] = inb_p(PMAC_DATA(minor));		timeout=0;		if(buffer[nc] == ACK_CHR)		{			*status = COMM_EOT;			break;		}		else if(buffer[nc] == CARRIAGE_RETURN)		{			nc++;			*status=COMM_OK;			break;		}		else if(buffer[nc] > 0x7E)		{			*status=COMM_ERROR;			break;		}		else if(buffer[nc] == CTRL_G)			*status=COMM_ERROR;		else			nc++;		if(*status==COMM_ERROR && !PMAC_RDY_TO_SEND(minor))			break;	}	if (timeout>=pmac_timeout_cnt)		*status=COMM_TIMEOUT;	buffer[nc] = NULL_CHR;//	printk (KERN_NOTICE "pmac isa: Card sent following string %s at port 0x%X\n", buffer, PMAC_HOST_BASE(minor));	return nc;}   /*flush_port() clears out any garbage in pmac command buffer by writing Ctrl-X and    *then reads few characters back to clear out data buffer    */int flush_port(unsigned int minor){	int i=0;	unsigned int temp;	write_char_port(minor, CTRL_X);	while(i++<pmac_timeout_cnt)	{	    if(!PMAC_RDY_TO_SEND(minor))	    {		udelay(delay_per_try);		continue;	    }	    temp = inb_p(PMAC_DATA(minor));	    if(temp == CTRL_X)	    {//		printk (KERN_NOTICE "pmac isa: flush_port successful 0x%X at port 0x%X\n", temp, PMAC_HOST_BASE(minor));		return 0;	    }	    else if(temp == 0xFF)	    {    	    	printk (KERN_NOTICE "pmac isa: flush_port returned 0x%X at port 0x%X\n", temp, PMAC_HOST_BASE(minor));		    return -ENODEV;	    }	    else	    {	    	printk (KERN_NOTICE "pmac isa: flush_port returned garbage 0x%X at port 0x%X\n", temp, PMAC_HOST_BASE(minor));		    return -ENODEV;	    }	        }    printk (KERN_NOTICE "pmac isa: flush_port command timed out with %d tries at port 0x%X\n", i, PMAC_HOST_BASE(minor));    return -ENODEV;}   /*get_ctrl_resp() sends requested ctrl character between 1-26 to pmac. if request is known    *not to return any characters it sets the EOT status bit then exits. if request is know to    *return 1 line of data then function grabs the data and sets EOT. if n lines are returned    *function does not grab data and nor does set EOT    */int get_ctrl_resp(unsigned int minor, char *buffer, int *status){	int result=0;	*status=COMM_OK;	if(!buffer[0]==CTRL_I)		flush_port(minor);	write_char_port(minor, buffer[0]);	switch(buffer[0]){		case CTRL_B: case CTRL_C: case CTRL_F: case CTRL_G: case CTRL_P: case CTRL_T: case CTRL_V: case CTRL_Y: case CTRL_X:			result=read_line_port(minor, buffer, status);			break;		case CTRL_E: case CTRL_I:			buffer[0]=NULL_CHR;			break;		default:			buffer[0]=NULL_CHR;			*status=COMM_EOT;	}	return result;}/////////////////////////////////////DPRAM functions//////////////////////////////////int write_char_mem(unsigned int minor, char outchar){	unsigned long timeout=0;	if(!pmac_dev[minor].has_memory)		return -EPERM;	while(timeout++ < pmac_timeout_cnt){		if(DPR_WRITE_READY(minor)){			if(CTRL_A <= outchar && outchar <= CTRL_Z){				writeb(outchar, DPR_REG_CTRL_CHAR(minor));				DPR_SET_WRITE_READY(minor);			}else{				writeb(outchar, DPR_REG_WRITE(minor));				writeb(NULL_CHR, DPR_REG_WRITE(minor) + 1);				DPR_SET_WRITE_READY(minor);			}			return COMM_OK;		}else		udelay(delay_per_try);	}	return COMM_TIMEOUT;}int flush_mem(unsigned int minor){	int i=0, status;	if(!pmac_dev[minor].has_memory)		return -EPERM;	write_char_mem(minor, CTRL_X);	while(i++<pmac_timeout_cnt){		if(DPR_READ_READY(minor)){			if(DPR_FLUSHED(minor))				status = COMM_OK;			else				status = COMM_ERROR;			DPR_CLR_READ_READY(minor);		}else			udelay(delay_per_try);	}	status = COMM_TIMEOUT;	return status;}   /*write_line_mem() write string to dpram ascii port, returns no of characters written to dpram    *or a -ve no if there is no DPRAM    */int write_line_mem(unsigned int minor, char *buffer, int *status){	int nc=0;	unsigned long timeout=0;	if(!pmac_dev[minor].has_memory)		return -EPERM;	while(buffer[nc] != NULL_CHR)		nc++;	if(nc > MAX_DPR_BUFFER){		*status = COMM_ERROR;		return -EPERM;	}	while(timeout++ < pmac_timeout_cnt){		if(DPR_WRITE_READY(minor)){			memcpy_toio(DPR_REG_WRITE(minor), buffer, nc + 1);			DPR_SET_WRITE_READY(minor);			*status = COMM_OK;			return nc;		}else			udelay(delay_per_try);	}	*status = COMM_TIMEOUT;	return 0;}  /*read_line_mem() reads a string from DPR ascii port   */int read_line_mem(unsigned int minor, char *buffer, int *status){	unsigned long timeout = 0;	unsigned int retval=0;	if(!pmac_dev[minor].has_memory)		return -EPERM;	while(timeout++ < pmac_timeout_cnt){		if(DPR_READ_READY(minor)){			if(DPR_ERROR(minor)){				retval = DPR_ERROR_CODE(minor);				*status = COMM_ERROR;				DPR_CLR_READ_READY(minor);				return retval;			}			retval = DPR_NUM_CHARS(minor);			if(retval > 0){				if(!(retval < MAX_COMM_BUFFER))					retval = MAX_COMM_BUFFER - 1;				memcpy_fromio(buffer, DPR_REG_READ(minor), retval);			}			if(DPR_CR(minor)){				buffer[retval] = CARRIAGE_RETURN;				retval++;			}else if(DPR_ACK(minor)){				*status = COMM_EOT;			}else if(DPR_USER(minor))				*status = COMM_UNSOLICITED;			DPR_CLR_READ_READY(minor);			buffer[retval] = NULL_CHR;			return retval;		}else			udelay(delay_per_try);	}	*status = COMM_TIMEOUT;	return 0;}  /*set_mem() writes a string to any offset on dpram   */int set_mem(unsigned int minor, char *buffer, int *status, unsigned long offset, unsigned int count){	if(!pmac_dev[minor].has_memory)		return -EPERM;	if(count > 0 && count < PMAC_DPR_SIZE(minor))		if((PMAC_DPR_VADD(minor) + offset + (unsigned long)count) > (PMAC_DPR_VADD(minor) + PMAC_DPR_SIZE(minor))){			*status = COMM_ERROR;			return -ENXIO;		}	memcpy_toio(PMAC_DPR_VADD(minor) + offset, buffer, count);	*status = COMM_OK;	return count;}  /*get_mem() reads a string from any offset on dpram   */int get_mem(unsigned int minor, char *buffer, int *status, unsigned long offset, unsigned int count){	if(!pmac_dev[minor].has_memory)		return -EPERM;	if(count > 0 && count < PMAC_DPR_SIZE(minor))		if((PMAC_DPR_VADD(minor) + offset + (unsigned long)count) > (PMAC_DPR_VADD(minor) + PMAC_DPR_SIZE(minor))){			*status = COMM_ERROR;			return -ENXIO;		}	memcpy_fromio(buffer, PMAC_DPR_VADD(minor) + offset, count);	*status = COMM_OK;	return count;}  /*get_ctrl_resp_mem() sends requested control character to PMAC...   */int get_ctrl_resp_mem(unsigned int minor, char *buffer, int *status){	int result=0;	*status = COMM_OK;	if(!pmac_dev[minor].has_memory)		return -EPERM;	if(!buffer[0]==CTRL_I)		result = flush_mem(minor);	if(buffer[0]==CTRL_X)    /** already flushed in last statement*/		return result;	write_char_mem(minor, buffer[0]);	switch(buffer[0]){		case CTRL_B: case CTRL_C: case CTRL_F: case CTRL_G: case CTRL_P: case CTRL_T: case CTRL_V: case CTRL_Y:			result=read_line_mem(minor, buffer, status);			if(*status == COMM_OK)				*status = COMM_EOT;			break;		case CTRL_E: case CTRL_I:			buffer[0]=NULL_CHR;			*status = COMM_OK;			break;		default:			buffer[0]=NULL_CHR;			*status=COMM_EOT;	}	return result;}/////////////////////////////////////General functions////////////////////////////////   /*get_dpr_base() sets the base address of the PMAC's dpram    */unsigned long get_dpr_base(unsigned int minor){	//...will implement later...	return 0;}   /*set_dpr_base() sets the base address of the PMAC's dpram, will imporve in future...    */int set_dpr_base(unsigned int minor){	unsigned int d1, d2;	char str[256];	int status;	unsigned long base = PMAC_DPR_BASE(minor);	struct _Pmac_Device *device = &pmac_dev[minor];	d1 = (base & 0xF0000) >> 16;	d2 = ((base & 0x0F000) >> 8) + 0x5;	if(device->type > PT_PMAC){

⌨️ 快捷键说明

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