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

📄 parport_mfc3.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
字号:
/* Low-level parallel port routines for the Multiface 3 card * * Author: Joerg Dorchain <joerg@dorchain.net> * * (C) The elitist m68k Users(TM) * * based on the existing parport_amiga and lp_mfc * * * From the MFC3 documentation: *  * Miscellaneous PIA Details * ------------------------- *  * 	The two open-drain interrupt outputs /IRQA and /IRQB are routed to * /INT2 of the Z2 bus. *  * 	The CPU data bus of the PIA (D0-D7) is connected to D8-D15 on the Z2 * bus. This means that any PIA registers are accessed at even addresses. *  * Centronics Pin Connections for the PIA * -------------------------------------- *  * 	The following table shows the connections between the PIA and the * Centronics interface connector. These connections implement a single, but * very complete, Centronics type interface. The Pin column gives the pin * numbers of the PIA. The Centronics pin numbers can be found in the section * "Parallel Connectors". *  *  *    Pin | PIA | Dir | Centronics Names * -------+-----+-----+--------------------------------------------------------- *     19 | CB2 | --> | /STROBE (aka /DRDY) *  10-17 | PBx | <-> | DATA0 - DATA7 *     18 | CB1 | <-- | /ACK *     40 | CA1 | <-- | BUSY *      3 | PA1 | <-- | PAPER-OUT (aka POUT) *      4 | PA2 | <-- | SELECTED (aka SEL) *      9 | PA7 | --> | /INIT (aka /RESET or /INPUT-PRIME) *      6 | PA4 | <-- | /ERROR (aka /FAULT) *      7 | PA5 | --> | DIR (aka /SELECT-IN) *      8 | PA6 | --> | /AUTO-FEED-XT *     39 | CA2 | --> | open *      5 | PA3 | <-- | /ACK (same as CB1!) *      2 | PA0 | <-- | BUSY (same as CA1!) * -------+-----+-----+--------------------------------------------------------- *  * Should be enough to understand some of the driver. * * Per convention for normal use the port registers are visible. * If you need the data direction registers, restore the value in the * control register. */#include "multiface.h"#include <linux/module.h>#include <linux/init.h>#include <linux/parport.h>#include <linux/delay.h>#include <linux/mc6821.h>#include <linux/zorro.h>#include <asm/setup.h>#include <asm/amigahw.h>#include <asm/irq.h>#include <asm/amigaints.h>/* Maximum Number of Cards supported */#define MAX_MFC 5#undef DEBUG#ifdef DEBUG#define DPRINTK printk#elsestatic inline int DPRINTK(void *nothing, ...) {return 0;}#endifstatic struct parport *this_port[MAX_MFC] = {NULL, };static volatile int dummy; /* for trigger readds */#define pia(dev) ((struct pia *)(dev->base))static struct parport_operations pp_mfc3_ops;static void mfc3_write_data(struct parport *p, unsigned char data){DPRINTK("write_data %c\n",data);	dummy = pia(p)->pprb; /* clears irq bit */	/* Triggers also /STROBE.*/	pia(p)->pprb = data;}static unsigned char mfc3_read_data(struct parport *p){	/* clears interupt bit. Triggers also /STROBE. */	return pia(p)->pprb;}static unsigned char control_pc_to_mfc3(unsigned char control){	unsigned char ret = 32|64;	if (control & PARPORT_CONTROL_SELECT) /* XXX: What is SELECP? */		ret &= ~32; /* /SELECT_IN */	if (control & PARPORT_CONTROL_INIT) /* INITP */		ret |= 128;	if (control & PARPORT_CONTROL_AUTOFD) /* AUTOLF */		ret &= ~64;	if (control & PARPORT_CONTROL_STROBE) /* Strobe */		/* Handled directly by hardware */;	return ret;}static unsigned char control_mfc3_to_pc(unsigned char control){	unsigned char ret = PARPORT_CONTROL_STROBE 			  | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_SELECT;	if (control & 128) /* /INITP */		ret |= PARPORT_CONTROL_INIT;	if (control & 64) /* /AUTOLF */		ret &= ~PARPORT_CONTROL_AUTOFD;	if (control & 32) /* /SELECT_IN */		ret &= ~PARPORT_CONTROL_SELECT;	return ret;}static void mfc3_write_control(struct parport *p, unsigned char control){DPRINTK("write_control %02x\n",control);	pia(p)->ppra = (pia(p)->ppra & 0x1f) | control_pc_to_mfc3(control);}	static unsigned char mfc3_read_control( struct parport *p){DPRINTK("read_control \n");	return control_mfc3_to_pc(pia(p)->ppra & 0xe0);}static unsigned char mfc3_frob_control( struct parport *p, unsigned char mask, unsigned char val){	unsigned char old;DPRINTK("frob_control mask %02x, value %02x\n",mask,val);	old = mfc3_read_control(p);	mfc3_write_control(p, (old & ~mask) ^ val);	return old;}#if 0 /* currently unused */static unsigned char status_pc_to_mfc3(unsigned char status){	unsigned char ret = 1;	if (status & PARPORT_STATUS_BUSY) /* Busy */		ret &= ~1;	if (status & PARPORT_STATUS_ACK) /* Ack */		ret |= 8;	if (status & PARPORT_STATUS_PAPEROUT) /* PaperOut */		ret |= 2;	if (status & PARPORT_STATUS_SELECT) /* select */		ret |= 4;	if (status & PARPORT_STATUS_ERROR) /* error */		ret |= 16;	return ret;}#endifstatic unsigned char status_mfc3_to_pc(unsigned char status){	unsigned char ret = PARPORT_STATUS_BUSY;	if (status & 1) /* Busy */		ret &= ~PARPORT_STATUS_BUSY;	if (status & 2) /* PaperOut */		ret |= PARPORT_STATUS_PAPEROUT;	if (status & 4) /* Selected */		ret |= PARPORT_STATUS_SELECT;	if (status & 8) /* Ack */		ret |= PARPORT_STATUS_ACK;	if (status & 16) /* /ERROR */		ret |= PARPORT_STATUS_ERROR;	return ret;}#if 0 /* currently unused */static void mfc3_write_status( struct parport *p, unsigned char status){DPRINTK("write_status %02x\n",status);	pia(p)->ppra = (pia(p)->ppra & 0xe0) | status_pc_to_mfc3(status);}#endifstatic unsigned char mfc3_read_status(struct parport *p){	unsigned char status;	status = status_mfc3_to_pc(pia(p)->ppra & 0x1f);DPRINTK("read_status %02x\n", status);	return status;}#if 0 /* currently unused */static void mfc3_change_mode( struct parport *p, int m){	/* XXX: This port only has one mode, and I am	not sure about the corresponding PC-style mode*/}#endifstatic int use_cnt = 0;static void mfc3_interrupt(int irq, void *dev_id, struct pt_regs *regs){	int i;	for( i = 0; i < MAX_MFC; i++)		if (this_port[i] != NULL)			if (pia(this_port[i])->crb & 128) { /* Board caused interrupt */				dummy = pia(this_port[i])->pprb; /* clear irq bit */				parport_generic_irq(irq, this_port[i], regs);			}}static void mfc3_enable_irq(struct parport *p){	pia(p)->crb |= PIA_C1_ENABLE_IRQ;}static void mfc3_disable_irq(struct parport *p){	pia(p)->crb &= ~PIA_C1_ENABLE_IRQ;}static void mfc3_data_forward(struct parport *p){	DPRINTK("forward\n");	pia(p)->crb &= ~PIA_DDR; /* make data direction register visible */	pia(p)->pddrb = 255; /* all pins output */	pia(p)->crb |= PIA_DDR; /* make data register visible - default */}static void mfc3_data_reverse(struct parport *p){	DPRINTK("reverse\n");	pia(p)->crb &= ~PIA_DDR; /* make data direction register visible */	pia(p)->pddrb = 0; /* all pins input */	pia(p)->crb |= PIA_DDR; /* make data register visible - default */}static void mfc3_init_state(struct pardevice *dev, struct parport_state *s){	s->u.amiga.data = 0;	s->u.amiga.datadir = 255;	s->u.amiga.status = 0;	s->u.amiga.statusdir = 0xe0;}static void mfc3_save_state(struct parport *p, struct parport_state *s){	s->u.amiga.data = pia(p)->pprb;	pia(p)->crb &= ~PIA_DDR;	s->u.amiga.datadir = pia(p)->pddrb;	pia(p)->crb |= PIA_DDR;	s->u.amiga.status = pia(p)->ppra;	pia(p)->cra &= ~PIA_DDR;	s->u.amiga.statusdir = pia(p)->pddrb;	pia(p)->cra |= PIA_DDR;}static void mfc3_restore_state(struct parport *p, struct parport_state *s){	pia(p)->pprb = s->u.amiga.data;	pia(p)->crb &= ~PIA_DDR;	pia(p)->pddrb = s->u.amiga.datadir;	pia(p)->crb |= PIA_DDR;	pia(p)->ppra = s->u.amiga.status;	pia(p)->cra &= ~PIA_DDR;	pia(p)->pddrb = s->u.amiga.statusdir;	pia(p)->cra |= PIA_DDR;}static void mfc3_inc_use_count(void){	MOD_INC_USE_COUNT;}static void mfc3_dec_use_count(void){	MOD_DEC_USE_COUNT;}static struct parport_operations pp_mfc3_ops = {	mfc3_write_data,	mfc3_read_data,	mfc3_write_control,	mfc3_read_control,	mfc3_frob_control,	mfc3_read_status,	mfc3_enable_irq,	mfc3_disable_irq,	mfc3_data_forward, 	mfc3_data_reverse, 	mfc3_init_state,	mfc3_save_state,	mfc3_restore_state,	mfc3_inc_use_count,	mfc3_dec_use_count,	parport_ieee1284_epp_write_data,	parport_ieee1284_epp_read_data,	parport_ieee1284_epp_write_addr,	parport_ieee1284_epp_read_addr,	parport_ieee1284_ecp_write_data,	parport_ieee1284_ecp_read_data,	parport_ieee1284_ecp_write_addr,	parport_ieee1284_write_compat,	parport_ieee1284_read_nibble,	parport_ieee1284_read_byte,};/* ----------- Initialisation code --------------------------------- */int __init parport_mfc3_init(void){	struct parport *p;	int pias;	struct pia *pp;	struct zorro_dev *z = NULL;	if (!MACH_IS_AMIGA)		return -ENODEV;	while ((z = zorro_find_device(ZORRO_PROD_BSC_MULTIFACE_III, z))) {		unsigned long piabase = z->resource.start+PIABASE;		if (!request_mem_region(piabase, sizeof(struct pia), "PIA"))			continue;		pp = (struct pia *)ZTWO_VADDR(piabase);		pp->crb = 0;		pp->pddrb = 255; /* all data pins output */		pp->crb = PIA_DDR|32|8;		dummy = pp->pddrb; /* reading clears interrupt */		pp->cra = 0;		pp->pddra = 0xe0; /* /RESET,  /DIR ,/AUTO-FEED output */		pp->cra = PIA_DDR;		pp->ppra = 0; /* reset printer */		udelay(10);		pp->ppra = 128;		p = parport_register_port((unsigned long)pp, IRQ_AMIGA_PORTS,					  PARPORT_DMA_NONE, &pp_mfc3_ops);		if (!p)			goto out_port;		if (p->irq != PARPORT_IRQ_NONE) {			if (use_cnt++ == 0)				if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, SA_SHIRQ, p->name, &pp_mfc3_ops))					goto out_irq;		}		this_port[pias++] = p;		printk(KERN_INFO "%s: Multiface III port using irq\n", p->name);		/* XXX: set operating mode */		parport_proc_register(p);		p->private_data = (void *)piabase;		parport_announce_port (p);		if (pias >= MAX_MFC)			break;		continue;	out_irq:		parport_unregister_port(p);	out_port:		release_mem_region(piabase, sizeof(struct pia));	}	return pias ? 0 : -ENODEV;}void __exit parport_mfc3_exit(void){	int i;	for (i = 0; i < MAX_MFC; i++) {		if (!this_port[i])			continue;		if (!this_port[i]->irq != PARPORT_IRQ_NONE) {			if (--use_cnt == 0) 				free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops);		}		parport_proc_unregister(this_port[i]);		parport_unregister_port(this_port[i]);		release_mem_region(ZTWO_PADDR(this_port[i]->private_data), sizeof(struct pia));	}}MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");MODULE_DESCRIPTION("Parport Driver for Multiface 3 expansion cards Paralllel Port");MODULE_SUPPORTED_DEVICE("Multiface 3 Parallel Port");module_init(parport_mfc3_init)module_exit(parport_mfc3_exit)

⌨️ 快捷键说明

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