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

📄 parport.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: parport.c,v 1.1.1.1 2004/02/04 12:55:28 laputa Exp $ *  * Elinux parallel port driver * NOTE! *   Since par0 shares DMA with ser2 and par 1 shares DMA with ser3 *   this should be handled if both are enabled at the same time. *   THIS IS NOT HANDLED YET! * * Copyright (c) 2001 Axis Communications AB *  * Author: Fredrik Hugosson * */#include <linux/module.h>#include <linux/init.h>#include <linux/parport.h>#include <linux/ioport.h>#include <linux/config.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <asm/setup.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/segment.h>#include <asm/system.h>#include <asm/svinto.h>#undef DEBUG#ifdef DEBUG#define DPRINTK printk#elsestatic inline int DPRINTK(void *nothing, ...) {return 0;}#endif/* * Etrax100 DMAchannels: * Par0 out : DMA2 * Par0 in  : DMA3 * Par1 out : DMA4 * Par1 in  : DMA5 * NOTE! par0 is shared with ser2 and par1 is shared with ser3 regarding *       DMA and DMA irq *///#define CONFIG_PAR0_INT 1//#define CONFIG_PAR1_INT 1#define SETF(var, reg, field, val) \	var = (var & ~IO_MASK(##reg##, field)) | IO_FIELD(##reg##, field, val)#define SETS(var, reg, field, val) \	var = (var & ~IO_MASK(##reg##, field)) | IO_STATE(##reg##, field, val)struct etrax100par_struct {	/* parallell port control */	volatile u32 *reg_ctrl_data; /* R_PARx_CTRL_DATA */	const volatile u32 *reg_status_data; /* R_PARx_STATUS_DATA */	volatile u32 *reg_config; /* R_PARx_CONFIG */	volatile u32 *reg_delay; /* R_PARx_DELAY */		/* DMA control */	int odma;	unsigned long dma_irq;  /* bitnr in R_IRQ_MASK2 for dmaX_descr */	volatile char *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR, output */	volatile u32 *ofirstadr;   /* adr to R_DMA_CHx_FIRST, output */	volatile char *ocmdadr;     /* adr to R_DMA_CHx_CMD, output */		volatile char *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR, input */	volatile u32 *ifirstadr;   /* adr to R_DMA_CHx_FIRST, input */	volatile char *icmdadr;     /* adr to R_DMA_CHx_CMD, input */	/* Non DMA interrupt stuff */	unsigned long int_irq; /* R_VECT_MASK_RD */	const volatile u32 *irq_mask_rd; /* R_IRQ_MASKX_RD */	volatile u32 *irq_mask_clr; /* R_IRQ_MASKX_RD */	const volatile u32 *irq_read; /* R_IRQ_READX */	volatile u32 *irq_mask_set; /* R_IRQ_MASKX_SET */	unsigned long irq_mask_tx;  /* bitmask in R_IRQ_ for tx (ready) int */	unsigned long irq_mask_rx;  /* bitmask in R_IRQ_ for rx (data) int */	unsigned long irq_mask_ecp_cmd;  /* mask in R_IRQ_ for ecp_cmd int */	unsigned long irq_mask_peri;  /* bitmask in R_IRQ_ for peri int */	int portnr;  	/* ----- end of fields initialised in port_table[] below ----- */	struct parport *port;  	/* Shadow registers */	volatile unsigned long reg_ctrl_data_shadow; /* for R_PARx_CTRL_DATA */	volatile unsigned long reg_config_shadow;    /* for R_PARx_CONFIG */	volatile unsigned long reg_delay_shadow;    /* for R_PARx_DELAY */};/* Always have the complete structs here, even if the port is not used! *  (that way we can index this by the port number) */static struct etrax100par_struct port_table[] = {	{ 		R_PAR0_CTRL_DATA,		R_PAR0_STATUS_DATA,		R_PAR0_CONFIG,		R_PAR0_DELAY,		/* DMA interrupt stuff */		2,		1U << 4, /* uses DMA 2 and 3 */		R_DMA_CH2_CLR_INTR,		R_DMA_CH2_FIRST,		R_DMA_CH2_CMD,		R_DMA_CH3_CLR_INTR,		R_DMA_CH3_FIRST,		R_DMA_CH3_CMD,		/* Non DMA interrupt stuff */		IO_BITNR(R_VECT_MASK_RD, par0),		R_IRQ_MASK0_RD,		R_IRQ_MASK0_CLR,		R_IRQ_READ0,		R_IRQ_MASK0_SET,		IO_FIELD(R_IRQ_MASK0_RD, par0_ready, 1U), /* tx (ready)*/		IO_FIELD(R_IRQ_MASK0_RD, par0_data, 1U), /* rx (data)*/		IO_FIELD(R_IRQ_MASK0_RD, par0_ecp_cmd, 1U), /* ecp_cmd */		IO_FIELD(R_IRQ_MASK0_RD, par0_peri, 1U), /* peri */		0	},	{		R_PAR1_CTRL_DATA,		R_PAR1_STATUS_DATA,		R_PAR1_CONFIG,		R_PAR1_DELAY,		/* DMA interrupt stuff */		4,		1U << 8, /* uses DMA 4 and 5 */				R_DMA_CH4_CLR_INTR,		R_DMA_CH4_FIRST,		R_DMA_CH4_CMD,		R_DMA_CH5_CLR_INTR,		R_DMA_CH5_FIRST,		R_DMA_CH5_CMD,		/* Non DMA interrupt stuff */		IO_BITNR(R_VECT_MASK_RD, par1),		R_IRQ_MASK1_RD,		R_IRQ_MASK1_CLR,		R_IRQ_READ1,		R_IRQ_MASK1_SET,		IO_FIELD(R_IRQ_MASK1_RD, par1_ready, 1U), /* tx (ready)*/		IO_FIELD(R_IRQ_MASK1_RD, par1_data, 1U), /* rx (data)*/		IO_FIELD(R_IRQ_MASK1_RD, par1_ecp_cmd, 1U), /* ecp_cmd */		IO_FIELD(R_IRQ_MASK1_RD, par1_peri, 1U), /* peri */		1	}};#define NR_PORTS (sizeof(port_table)/sizeof(struct etrax100par_struct))static voidparport_etrax_write_data(struct parport *p, unsigned char value){	struct etrax100par_struct *info =		(struct etrax100par_struct *)p->private_data;	DPRINTK("* E100 PP %d: etrax_write_data %02X\n", p->portnum, value);	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, data, value);	*info->reg_ctrl_data = info->reg_ctrl_data_shadow;}static unsigned charparport_etrax_read_data(struct parport *p){	unsigned char ret;	struct etrax100par_struct *info =		(struct etrax100par_struct *)p->private_data;	ret = IO_EXTRACT(R_PAR0_STATUS_DATA, data, *info->reg_status_data);	DPRINTK("* E100 PP %d: etrax_read_data %02X\n", p->portnum, ret);	return ret;}static voidparport_etrax_write_control(struct parport *p, unsigned char control){	struct etrax100par_struct *info =		(struct etrax100par_struct *)p->private_data;	DPRINTK("* E100 PP %d: etrax_write_control %02x\n", p->portnum, control);  	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, strb,	     (control & PARPORT_CONTROL_STROBE) > 0);	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, autofd,	     (control & PARPORT_CONTROL_AUTOFD) > 0);	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, init,	     (control & PARPORT_CONTROL_INIT) > 0);	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, seli,	     (control & PARPORT_CONTROL_SELECT) > 0);	*info->reg_ctrl_data = info->reg_ctrl_data_shadow;}static unsigned charparport_etrax_read_control( struct parport *p){	unsigned char ret = 0;	struct etrax100par_struct *info =		(struct etrax100par_struct *)p->private_data;	if (IO_EXTRACT(R_PAR0_CTRL_DATA, strb, info->reg_ctrl_data_shadow))		ret |= PARPORT_CONTROL_STROBE;	if (IO_EXTRACT(R_PAR0_CTRL_DATA, autofd, info->reg_ctrl_data_shadow))		ret |= PARPORT_CONTROL_AUTOFD;	if (IO_EXTRACT(R_PAR0_CTRL_DATA, init, info->reg_ctrl_data_shadow))		ret |= PARPORT_CONTROL_INIT;	if (IO_EXTRACT(R_PAR0_CTRL_DATA, seli, info->reg_ctrl_data_shadow))		ret |= PARPORT_CONTROL_SELECT;	DPRINTK("* E100 PP %d: etrax_read_control %02x\n", p->portnum, ret);	return ret;}static unsigned charparport_etrax_frob_control(struct parport *p, unsigned char mask,                           unsigned char val){	unsigned char old;	DPRINTK("* E100 PP %d: frob_control mask %02x, value %02x\n",		p->portnum, mask, val);	old = parport_etrax_read_control(p);	parport_etrax_write_control(p, (old & ~mask) ^ val);	return old;}static unsigned charparport_etrax_read_status(struct parport *p){	unsigned char ret = 0;	struct etrax100par_struct *info =		(struct etrax100par_struct *)p->private_data;	if (IO_EXTRACT(R_PAR0_STATUS_DATA, fault, *info->reg_status_data))		ret |= PARPORT_STATUS_ERROR;	if (IO_EXTRACT(R_PAR0_STATUS_DATA, sel, *info->reg_status_data))		ret |= PARPORT_STATUS_SELECT;	if (!IO_EXTRACT(R_PAR0_STATUS_DATA, perr, *info->reg_status_data))		ret |= PARPORT_STATUS_PAPEROUT;	if (IO_EXTRACT(R_PAR0_STATUS_DATA, ack, *info->reg_status_data))		ret |= PARPORT_STATUS_ACK;	if (!IO_EXTRACT(R_PAR0_STATUS_DATA, busy, *info->reg_status_data))		ret |= PARPORT_STATUS_BUSY;	DPRINTK("* E100 PP %d: status register %04x\n",		p->portnum, *info->reg_status_data);	DPRINTK("* E100 PP %d: read_status %02x\n", p->portnum, ret);	return ret;}static voidparport_etrax_enable_irq(struct parport *p){	struct etrax100par_struct *info =		(struct etrax100par_struct *)p->private_data;	*info->irq_mask_set = info->irq_mask_tx;	DPRINTK("* E100 PP %d: enable irq\n", p->portnum);}static voidparport_etrax_disable_irq(struct parport *p){

⌨️ 快捷键说明

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