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

📄 pmacpci.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#ifndef CONFIG_PCI#  error "This driver needs PCI support to be available"#endif#include "pmacpci.h"#include<linux/pci.h>#include<linux/module.h>#include <linux/moduleparam.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 pmac pci /////////////////////////////////////#define PMAC_VENDOR 0x1172#define PMAC_ID 0x0001/////////////////////////#defines for immutable pmac properties//////////////////////#define PMAC_HOST_BASE(x)(pmac_dev[x].host)#define PMAC_HOST_RANGE(x) (pmac_dev[x].range)	/**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(1, 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)///////////////////////////////GLOBAL VARIABLES///////////////////////////////////////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");MODULE_AUTHOR("chiefleo, sjtu");MODULE_LICENSE("Dual BSD/GPL");static unsigned int major = 0;           /* major device number, can be specified or used 0 for dynamic allocation*/                                          /*MODULE_PARM(major, "i");*/module_param(major, int, S_IRUGO);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 PCI";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++;			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;	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, nchr=0;	unsigned int temp;	write_char_port(minor, CTRL_X);	while(i++<pmac_timeout_cnt && nchr<5){		if(!PMAC_RDY_TO_SEND(minor)){			udelay(delay_per_try);			continue;		}else			nchr++;		temp = inb_p(PMAC_DATA(minor));		if(temp == CTRL_X)			break;		else if(temp == 0xFF)			return -ENODEV;	}	return 0;}   /*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;	}	//DPR_CLR_WRITE_READY(minor);	//DPR_CLR_READ_READY(minor);	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);

⌨️ 快捷键说明

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