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

📄 cpia_pp.c

📁 cpia usb摄像头的驱动程序源码。需要video4linux和i2c-core支持
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * cpia_pp CPiA Parallel Port driver * * Supports CPiA based parallel port Video Camera's. * * (C) Copyright 1999 Bas Huisman <bhuism@cs.utwente.nl> * (C) Copyright 1999-2000 Scott J. Bertin <sbertin@securenym.net>, * (C) Copyright 1999-2000 Peter Pregler <Peter_Pregler@email.com> * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. *//* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) *//* #define _CPIA_DEBUG_  1 */  #undef CPIA_PARPORT_DMA#define CPIA_PARPORT_DMA 1   /* comment this out to remove ECP DMA support */#include <linux/config.h>#include <linux/version.h>#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/parport.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/smp_lock.h>#include <linux/sched.h>#include <linux/pci.h>#include <asm/dma.h>#include <linux/parport_pc.h>#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3))#ifdef CONFIG_KMOD#include <linux/kmod.h>#endif#else#include <linux/kmod.h>#endif#include "cpia.h"static int cpia_pp_open(void *privdata, int alt);static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata),                                    void *cbdata);static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data);static int cpia_pp_streamStart(void *privdata);static int cpia_pp_streamStop(void *privdata);static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock);static int cpia_pp_close(void *privdata);static int cpia_pp_upload_mode(void *privdata);#define ABOUT "Parallel port driver for Vision CPiA based cameras"#define PACKET_LENGTH 8/* Magic numbers for defining port-device mappings */#define PPCPIA_PARPORT_UNSPEC -4#define PPCPIA_PARPORT_AUTO -3#define PPCPIA_PARPORT_OFF -2#define PPCPIA_PARPORT_NONE -1#ifdef MODULEstatic int parport_nr[PARPORT_MAX] = {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC};static char *parport[PARPORT_MAX] = {NULL,};MODULE_AUTHOR("B. Huisman <bhuism@cs.utwente.nl> & Peter Pregler <Peter_Pregler@email.com>");MODULE_DESCRIPTION("Parallel port driver for Vision CPiA based cameras");#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10))MODULE_LICENSE("GPL");#endifMODULE_PARM(parport, "1-" __MODULE_STRING(PARPORT_MAX) "s");MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp.");#elsestatic int parport_nr[PARPORT_MAX] __initdata =	{[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC};static int parport_ptr = 0;#endif#define NIBBLE_UPLOAD 0x00#define ECP_UPLOAD    0x01struct pp_cam_entry {	struct pardevice *pdev;	struct parport *port;#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0))	struct tq_struct cb_task;#else	struct work_struct cb_task;#endif	int open_count;	wait_queue_head_t wq_stream;	/* image state flags */	int image_ready;	/* we got an interrupt */	int image_complete;	/* we have seen 4 EOI */	int streaming; /* we are in streaming mode */	int stream_irq;	int upload_mode;  /* IEEE1284 mode used for uploads  */};static struct cpia_camera_ops cpia_pp_ops = {	cpia_pp_open,	cpia_pp_registerCallback,	cpia_pp_transferCmd,	cpia_pp_streamStart,	cpia_pp_streamStop,	cpia_pp_streamRead,	cpia_pp_close,	CAM_TYPE_PP,	cpia_pp_upload_mode,	1,	THIS_MODULE};static LIST_HEAD(cam_list);static spinlock_t cam_list_lock_pp;/* FIXME */static void cpia_parport_enable_irq( struct parport *port ) {	parport_enable_irq(port);	mdelay(10);	return;}static void cpia_parport_disable_irq( struct parport *port ) {	parport_disable_irq(port);	mdelay(10);	return;}/**************************************************************************** * *  Low level parport functions for nibble and ECP DMA uploads * ***************************************************************************//* Special CPiA PPC modes: These are invoked by using the 1284 Extensibilty * Link Flag during negotiation */  #define UPLOAD_FLAG  0x08#define NIBBLE_TRANSFER 0x01#define ECP_TRANSFER 0x03#define CPIA_UPLOAD_CHUNKSIZE 4096       /* for non-ECP hardware uploads *//* FIXME: what chunksize for non-DMA ECP hardware (PIO) ? */#define CPIA_FIFO_UPLOAD_CHUNKSIZE 4096  /* for ECP PIO hardware uploads *//*  CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). *//* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */static size_t cpia_read_nibble (struct parport *port, 			 void *buffer, size_t len, 			 int flags){  /* adapted verbatim, with one change, from parport_ieee1284_read_nibble()     in drivers/parport/ieee1284-ops.c, by Tim Waugh */	unsigned char *buf = buffer;	int i;	unsigned char byte = 0;	len *= 2; /* in nibbles */	for (i=0; i < len; i++) {		unsigned char nibble;		/* The CPiA firmware suppresses the use of nDataAvail (nFault LO)		 * after every second nibble to signal that more		 * data is available.  (the total number of Bytes that		 * should be sent is known; if too few are received, an error		 * will be recorded after a timeout).  		 * This is incompatible with parport_ieee1284_read_nibble(),		 * which expects to find nFault LO after every second nibble.		 */		/* Solution: modify cpia_read_nibble to only check for 		 * nDataAvail before the first nibble is sent.		 */		/* Does the error line indicate end of data? */		if (((i /*& 1*/) == 0) &&		    (parport_read_status(port) & PARPORT_STATUS_ERROR)) {			port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;				DBG("%s: No more nibble data (%d bytes)\n",				port->name, i/2);			/* Go to reverse idle phase. */			parport_frob_control (port,					      PARPORT_CONTROL_AUTOFD,					      PARPORT_CONTROL_AUTOFD);			port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;			break;		}		/* Event 7: Set nAutoFd low. */		parport_frob_control (port,				      PARPORT_CONTROL_AUTOFD,				      PARPORT_CONTROL_AUTOFD);		/* Event 9: nAck goes low. */		port->ieee1284.phase = IEEE1284_PH_REV_DATA;		if (parport_wait_peripheral (port,					     PARPORT_STATUS_ACK, 0)) {			/* Timeout -- no more data? */				 DBG("%s: Nibble timeout at event 9 (%d bytes)\n",				 port->name, i/2);			parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);			break;		}		/* Read a nibble. */		nibble = parport_read_status (port) >> 3;		nibble &= ~8;		if ((nibble & 0x10) == 0)			nibble |= 8;		nibble &= 0xf;		/* Event 10: Set nAutoFd high. */		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);		/* Event 11: nAck goes high. */		if (parport_wait_peripheral (port,					     PARPORT_STATUS_ACK,					     PARPORT_STATUS_ACK)) {			/* Timeout -- no more data? */			DBG("%s: Nibble timeout at event 11\n",				 port->name);			break;		}		if (i & 1) {			/* Second nibble */			byte |= nibble << 4;			*buf++ = byte;		} else 			byte = nibble;	}	i /= 2; /* i is now in bytes */	if (i == len) {		/* Read the last nibble without checking data avail. */		port = port->physport;		if (parport_read_status (port) & PARPORT_STATUS_ERROR)			port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;		else			port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;	}	return i;}/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1) * (See CPiA Data sheet p. 31)  *  * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a  * nonstandard variant of nibble mode which allows the same (mediocre)  * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable  * parallel ports, but works also for  non-TRISTATE-capable ports. * (Standard nibble mode only send 4 bits per cycle) * */static size_t cpia_read_nibble_stream(struct parport *port, 			       void *buffer, size_t len, 			       int flags){	int i;	unsigned char *buf = buffer;	int endseen = 0;	for (i=0; i < len; i++) {		unsigned char nibble[2], byte = 0;		int j;		/* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */ 		if (endseen > 3 )			break;		/* Event 7: Set nAutoFd low. */		parport_frob_control (port,				      PARPORT_CONTROL_AUTOFD,				      PARPORT_CONTROL_AUTOFD);				/* Event 9: nAck goes low. */		port->ieee1284.phase = IEEE1284_PH_REV_DATA;		if (parport_wait_peripheral (port,					     PARPORT_STATUS_ACK, 0)) {			/* Timeout -- no more data? */				 DBG("%s: Nibble timeout at event 9 (%d bytes)\n",				 port->name, i/2);			parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);			break;		}		/* Read lower nibble */		nibble[0] = parport_read_status (port) >>3;				/* Event 10: Set nAutoFd high. */		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);		/* Event 11: nAck goes high. */		if (parport_wait_peripheral (port,					     PARPORT_STATUS_ACK,					     PARPORT_STATUS_ACK)) {			/* Timeout -- no more data? */			DBG("%s: Nibble timeout at event 11\n",				 port->name);			break;		}				/* Read upper nibble */		nibble[1] = parport_read_status (port) >>3;				/* reassemble the byte */		for (j = 0; j < 2 ; j++ ) {			nibble[j] &= ~8;			if ((nibble[j] & 0x10) == 0)				nibble[j] |= 8;			nibble[j] &= 0xf;		}		byte = (nibble[0] |(nibble[1] << 4));		*buf++ = byte;		if(byte == EOI)		  endseen++;		else		  endseen = 0;	}	return i;}#ifdef CPIA_PARPORT_DMA/* forward declarations for IEEE1284 ECP DMA read support  */static int change_mode(struct parport *, int );static void frob_econtrol (struct parport *, unsigned char, unsigned char);/* DMA support here thanks to: Blaise Gassend <blaise@gassend.com> *//*ECP parport lowlevel IEEE1284 DMA read support: */#define ECR_PS2 01#define ECR_ECP 03/* this an adaptation of code from parport_pc_ecp_read_block_pio() and * parport_pc_fifo_write_block_dma() */static size_t cpia_ecp_read_block_dma (struct parport *port,				       void *bufv, size_t length, int flags){	int r = 0, endseen = 0;	unsigned long dmaflag;	size_t left = length;	const struct parport_pc_private *priv = port->physport->private_data;	dma_addr_t dma_addr, dma_handle = 0;	size_t maxlen = 0x10000; /* max 64k per DMA transfer */	char *buf = bufv;	unsigned long start = (unsigned long) buf;	unsigned long end = (unsigned long) buf + length - 1;	size_t count = length;		if (length == 0)		return 0;		/* Special case: a timeout of zero means we cannot call schedule(). */	if (!port->cad->timeout)		return parport_ieee1284_ecp_read_data (port, buf,						       length, flags);		port = port->physport;		if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) {		/* change to reverse-idle phase (must be in forward-idle) */				/* Event 38: Set nAutoFd low (also make sure nStrobe is high) */ 		parport_frob_control (port,				      PARPORT_CONTROL_STROBE |PARPORT_CONTROL_AUTOFD,				      PARPORT_CONTROL_AUTOFD);		parport_pc_data_reverse (port); /* Must be in PS2 mode */		udelay (5);				/* Event 39: Set nInit low to initiate bus reversal */		parport_frob_control (port,				      PARPORT_CONTROL_INIT,				      0);				/* Event 40: Wait for  nAckReverse (PError) to go low */		if ((r = parport_wait_peripheral (port, 						  PARPORT_STATUS_PAPEROUT, 						  0))){			printk (KERN_DEBUG "%s: PE timeout Event 40 (%d) "				"in ecp_read_block_dma\n", port->name, r);			return 0;		}				port->ieee1284.phase = IEEE1284_PH_REV_DATA;				parport_frob_control (port,				      PARPORT_CONTROL_STROBE |PARPORT_CONTROL_AUTOFD,				      PARPORT_CONTROL_AUTOFD);		if (change_mode (port, ECR_ECP))      /* ECP FIFO */			printk (KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n", 				port->name);				/* the first byte must be collected manually */		/* Event 43: Wait for nAck to go low */		if( parport_wait_peripheral (port, 					     PARPORT_STATUS_ACK, 					     0)) {			/* timed out while reading -- no data */			printk (KERN_DEBUG "DMA read timed out (initial byte)\n");			goto out_no_data;		}#if 0   /* this is active in parport_pc_ecp_read_block_pio */		/* read byte */		*buf++ = inb (DATA (port));	       	left--;#endif				/* Event 44: nAutoFd (HostAck) goes high to acknowledge */		parport_pc_frob_control (port,					 PARPORT_CONTROL_AUTOFD,					 0);		#if 1  /* this is commented out  in parport_pc_ecp_read_block_pio */		/* Event 45: Wait for nAck to go high */		if (parport_wait_peripheral (port, 					     PARPORT_STATUS_ACK, 					     PARPORT_STATUS_ACK)) {			/* timed out while waiting for peripheral to respond to ack */			printk (KERN_DEBUG "ECP DMA read timed out (waiting for nAck)\n");						/* keep hold of the byte we've got already */			goto out_no_data;		}#endif	}	#if 0   /* active in parport_pc_ecp_read_block_pio */	/* Event 46: nAutoFd (HostAck) goes low to accept more data */	parport_pc_frob_control (port,				 PARPORT_CONTROL_AUTOFD,				 PARPORT_CONTROL_AUTOFD);#endif	        if (!left) 		goto out_no_data;		/* now do the DMA transfer (adapted from parport_pc_fifo_write_block_dma) */		if (end < MAX_DMA_ADDRESS) {		/* If it would cross a 64k boundary, cap it at the end. */		if ((start ^ end) & ~0xffffUL)			maxlen = 0x10000 - (start & 0xffff);				dma_addr = dma_handle = pci_map_single(priv->dev, (void *)buf, length,						       PCI_DMA_FROMDEVICE);        } else {		/* above 16 MB we use a bounce buffer as ISA-DMA is not possible */		maxlen   = PAGE_SIZE;          /* sizeof(priv->dma_buf) */		dma_addr = priv->dma_handle;	}		DBG ("DMA buffer is ready\n");	

⌨️ 快捷键说明

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