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

📄 elektor_canpar.c

📁 canbus4linux,来自www.sourceforge.net
💻 C
字号:
/* * elektor_canpar.c * Copyright (c) 2001 J黵gen Eder <Juergen.Eder@gmx.de> * * The hardware driver for the Elektor CAN Card  * for the parallel port <http://www.elektor.de>. The circuit was * in magazine: June 2000 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. *  * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. *///#define EXPORT_SYMTAB#include <linux/version.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/parport.h>#include <linux/ioctl.h>#include <asm/uaccess.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,18)#include <linux/spinlock.h>#else#include <asm/spinlock.h>#endif#include <linux/delay.h>#include <linux/time.h>#include "trace.h"#include "canbus4linux.h"#include "elektor_canpar.h"#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endifstatic int minimum_num=-1;static int maximum_num=-1;static CANPARDEVICE candevice[PARPORT_MAX];static struct parport_driver ParportDriver;static void wr_can(PCANPARDEVICE lpDIOCParms, unsigned char adr,unsigned char wert);static unsigned char rd_can(PCANPARDEVICE lpDIOCParms, unsigned char adr);static void out2Data(PCANPARDEVICE lpDIOCParms, int data);static void out2Controlport(PCANPARDEVICE lpDIOCParms, int data);static unsigned char inControlport(PCANPARDEVICE lpDIOCParms);static unsigned char inData(PCANPARDEVICE lpDIOCParms);//static void MaskIRQ(PCANPARDEVICE lpDIOCParms);//static void UnmaskIRQ(PCANPARDEVICE lpDIOCParms);//static void out2ECPControlport(PCANPARDEVICE lpDIOCParms, int data);//static unsigned char inECPControlport(PCANPARDEVICE lpDIOCParms);//static unsigned char inStatusport(PCANPARDEVICE lpDIOCParms);/***************************************************************************************/static void wr_can(PCANPARDEVICE lpDIOCParms, unsigned char adr,unsigned char wert) // Wert in Register des 82C200 an Adresse adr schreiben{	out2Controlport(lpDIOCParms,lpDIOCParms->statusport & ~0x20);   // Datenport auf Ausgang schalten	out2Data(lpDIOCParms,adr);                                  // Adresse auf Datenport	out2Controlport(lpDIOCParms,lpDIOCParms->statusport | 0x08);      // ALE=0	out2Data(lpDIOCParms,wert);                                 // Wert auf Datenport	out2Controlport(lpDIOCParms,lpDIOCParms->statusport | 0x02);      // WR\=0	out2Controlport(lpDIOCParms,lpDIOCParms->statusport & ~0x02);     // WR\=1	out2Controlport(lpDIOCParms,lpDIOCParms->statusport & ~0x08);     // ALE=1	out2Controlport(lpDIOCParms,lpDIOCParms->statusport | 0x20);      // Datenport auf Eingang}/***************************************************************************************/static unsigned char rd_can(PCANPARDEVICE lpDIOCParms, unsigned char adr) // Wert aus Register des 82C200 auslesen{	unsigned char bw;	out2Controlport(lpDIOCParms,lpDIOCParms->statusport & ~0x20);    // Datenport auf Ausgang	out2Data(lpDIOCParms,adr);                                       // Adresse auf Datenport	out2Controlport(lpDIOCParms,lpDIOCParms->statusport | 0x08);     // ALE=0	out2Controlport(lpDIOCParms,lpDIOCParms->statusport | 0x20);     // Datenport auf Eingang	out2Controlport(lpDIOCParms,lpDIOCParms->statusport & ~0x04);    // RD\=0	bw=inData(lpDIOCParms);                                          // Datenport auslesen	out2Controlport(lpDIOCParms,lpDIOCParms->statusport | 0x04);     // RD\=1	out2Controlport(lpDIOCParms,lpDIOCParms->statusport & ~0x08);    // ALE=1;	return(bw);}/***************************************************************************************//*static unsigned char inStatusport(PCANPARDEVICE lpDIOCParms){                                                   return parport_read_status(lpDIOCParms->parport->port);}                                                       *//***************************************************************************************/static void out2Controlport(PCANPARDEVICE lpDIOCParms, int data){                                               #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)    parport_write_control(lpDIOCParms->parport->port,data & ~0x20);   	if(data & 0x20)    		parport_data_reverse(lpDIOCParms->parport->port);   	else    		parport_data_forward(lpDIOCParms->parport->port);#else    parport_write_control(lpDIOCParms->parport->port,data);#endif	lpDIOCParms->statusport = data;}                                                       /***************************************************************************************/static unsigned char inControlport(PCANPARDEVICE lpDIOCParms){                      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	return lpDIOCParms->statusport;#else    return parport_read_control(lpDIOCParms->parport->port);#endif}                                                       /***************************************************************************************/static void out2Data(PCANPARDEVICE lpDIOCParms, int data){                                                   parport_write_data(lpDIOCParms->parport->port,data);}                                                       /***************************************************************************************/static unsigned char inData(PCANPARDEVICE lpDIOCParms){                                                   return parport_read_data(lpDIOCParms->parport->port);}                                                       /***************************************************************************************/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)static void out2ECPControlport(PCANPARDEVICE lpDIOCParms, int data){                                                   parport_write_econtrol(lpDIOCParms->parport->port,data);}                                                       #endif/***************************************************************************************/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)static unsigned char inECPControlport(PCANPARDEVICE lpDIOCParms){                                                   return parport_read_econtrol(lpDIOCParms->parport->port);}     #endif                                                  /***************************************************************************************/static int can_preempt(void *handle){  return 1; // 1=don't release parport}/***************************************************************************************/static void can_irq(int irq, void *dev_id, struct pt_regs *regs){		PCANPARDEVICE parport=(PCANPARDEVICE)dev_id;		TRACE("can_irq()");		if(parport && parport->pIsr)		{			// Aufruf der SJA Routine				(*parport->pIsr)(parport,parport->pSja1000Par);		}}/***************************************************************************************/static int canpar_register_isr(PCANPARDEVICE lpDIOCParms, sja1000_isr pIsr, struct sja1000_admin *pSja1000Par){	TRACE("registering isr()");	if(lpDIOCParms)	{		lpDIOCParms->pIsr = pIsr;		lpDIOCParms->pSja1000Par = pSja1000Par;		return 0;	}	return -EINVAL;}/***************************************************************************************/static int canpar_unregister_isr(PCANPARDEVICE lpDIOCParms){	TRACE("unregistering isr()");	if(lpDIOCParms)	{		lpDIOCParms->pIsr = 0;		return 0;	}	return -EINVAL;}/***************************************************************************************/static int canpar_open_device(PCANPARDEVICE lpDIOCParms){	TRACE("open device");	if(lpDIOCParms)	{		if(parport_claim(lpDIOCParms->parport))		{			TRACE("no access to PARPORT device");			return -ENODEV;		}		lpDIOCParms->ecp = 0;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)		if(lpDIOCParms->parport->port->modes & (PARPORT_MODE_PCECP+PARPORT_MODE_PCECPEPP+PARPORT_MODE_PCECPPS2))		{			TRACE("using ECP mode");			lpDIOCParms->ecp = 1;		}		else		{			TRACE("using Standard mode (Bidirectional, EPP)");			lpDIOCParms->ecp = 0;		}#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)		out2Controlport(lpDIOCParms,0x04); // Schnittstelle initialisieren		parport_enable_irq(lpDIOCParms->parport->port);#else		if (lpDIOCParms->ecp == 1)  // ECP Modus umschalten			out2ECPControlport(lpDIOCParms,inECPControlport(lpDIOCParms)|0x20);		out2Controlport(lpDIOCParms,0x14); // Schnittstelle initialisieren/IRQ ein#endif		lpDIOCParms->open = 1;		return 0;	}	TRACE("Invalid data or no parport");	return -ENODEV;}/***************************************************************************************/static int canpar_close_device(PCANPARDEVICE lpDIOCParms){	TRACE("close device");	if(lpDIOCParms)	{#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)		out2Controlport(lpDIOCParms,inControlport(lpDIOCParms)&0xef); // Schnittstelle: IRQ aus		parport_disable_irq(lpDIOCParms->parport->port);#else		out2Controlport(lpDIOCParms,inControlport(lpDIOCParms)&0xef); // Schnittstelle: IRQ aus#endif		parport_release(lpDIOCParms->parport);		lpDIOCParms->open = 0;	}	return 0;}/***************************************************************************************/static void cb_canpar_attach(struct parport *port){	// Search a free entry	int num;  	for(num=0;num < PARPORT_MAX; num++)  	{  		if(candevice[num].parport == 0)  		{	  		candevice[num].open = 0;	  		candevice[num].pIsr = 0;	  		candevice[num].num = num;	    	candevice[num].parport = parport_register_device(port, "elektor_canpar", can_preempt, NULL, can_irq,0,&candevice[num]);	    	if (!candevice[num].parport)	    	{	      		TRACE("Can't register device no.: %d name: %s",num, port->name);	    	}	    	else	    	{				struct sja1000_access access;				char name[MAX_DEVICE_NAME_LENGTH];				TRACE("Register device no.: %d",num);				access.chipset_frequency = 16000000;				access.output_control_register = 0xc2;				access.pOpenCanDevice = (sja1000_openCanDevice)canpar_open_device;				access.pCloseCanDevice = (sja1000_closeCanDevice)canpar_close_device;				access.pWriteToRegister = (sja1000_writeToRegister)wr_can;				access.pReadFromRegister = (sja1000_readFromRegister)rd_can;				access.pRegisterIsr = (sja1000_registerIsr)canpar_register_isr;				access.pUnregisterIsr = (sja1000_unregisterIsr)canpar_unregister_isr;				access.bCanChipsetFlags=CANBUS_CFS_CAN_2_0_A+CANBUS_CFS_CAN_2_0_B+CANBUS_CFS_EXT_FRAME;				sprintf(name,"elektor parallelport card%d",num);				candevice[num].num = sja1000_register_device(name, CANBUS4LINUX_VERSION, &candevice[num], &access, minimum_num, maximum_num);				if(candevice[num].num < 0)					break; // not enough memory to register this device	    	}	    	break;    	}  	}}/***************************************************************************************/static void cb_canpar_detach(struct parport *port){	int num;  	for(num=0;num < PARPORT_MAX; num++)  	{  		if(candevice[num].parport && (candevice[num].parport->port == port))  		{	      	TRACE("cb_canpar_detach: %d name: %s",num, port->name);  			parport_unregister_device(candevice[num].parport);  			return;    	}  	}	INFO_TRACE("Can't detach parport: parport not found in candevice list %d: %s",num, port->name);}/***************************************************************************************/int init_module(void){	#ifdef EXPORT_NO_SYMBOLS	EXPORT_NO_SYMBOLS;#endif	TRACE("init_module()");	memset(candevice,0x00,PARPORT_MAX*sizeof(CANPARDEVICE));	memset(&ParportDriver,0x00,sizeof(struct parport_driver));	ParportDriver.name = "elektor_canpar";	ParportDriver.attach = cb_canpar_attach;	ParportDriver.detach = cb_canpar_detach;	if (0 != parport_register_driver(&ParportDriver))	{		INFO_TRACE("Error while calling parport_register_driver()");	}    	TRACE("Init module finished");  	return 0;}/***************************************************************************************/void cleanup_module(void){    int num;    	  	TRACE("cleanup"); 	for(num=0; num < PARPORT_MAX; num++)  	{  		if (candevice[num].parport)  		{			TRACE("Unregister device no.: %d",num);			if(candevice[num].open)				canpar_close_device(&candevice[num]);			candevice[num].num = sja1000_unregister_device(candevice[num].num);  		}  	}	parport_unregister_driver(&ParportDriver);	candevice[num].parport = 0;}/***************************************************************************************/MODULE_PARM(minimum_num,"1i");MODULE_PARM(maximum_num,"1i");MODULE_AUTHOR("Juergen Eder  <Juergen.Eder@gmx.de>");MODULE_DESCRIPTION("CAN driver for Elektor CAN Card 6/2000");

⌨️ 快捷键说明

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