parport_pc.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,460 行 · 第 1/5 页

C
2,460
字号
	/* Set up ECP FIFO mode.*//*	parport_pc_frob_control (port,				 PARPORT_CONTROL_STROBE |				 PARPORT_CONTROL_AUTOFD,				 PARPORT_CONTROL_AUTOFD); */	r = change_mode (port, ECR_ECP); /* ECP FIFO */	if (r) printk (KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n", port->name);	port->ieee1284.phase = IEEE1284_PH_REV_DATA;	/* the first byte must be collected manually */dump_parport_state ("pre 43", port);	/* Event 43: Wait for nAck to go low */	r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0);	if (r) {		/* timed out while reading -- no data */		printk (KERN_DEBUG "PIO read timed out (initial byte)\n");		goto out_no_data;	}	/* read byte */	*bufp++ = inb (DATA (port));	left--;dump_parport_state ("43-44", port);	/* Event 44: nAutoFd (HostAck) goes high to acknowledge */	parport_pc_frob_control (port,				 PARPORT_CONTROL_AUTOFD,				 0);dump_parport_state ("pre 45", port);	/* Event 45: Wait for nAck to go high *//*	r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, PARPORT_STATUS_ACK); */dump_parport_state ("post 45", port);r = 0;	if (r) {		/* timed out while waiting for peripheral to respond to ack */		printk (KERN_DEBUG "ECP PIO read timed out (waiting for nAck)\n");		/* keep hold of the byte we've got already */		goto out_no_data;	}	/* Event 46: nAutoFd (HostAck) goes low to accept more data */	parport_pc_frob_control (port,				 PARPORT_CONTROL_AUTOFD,				 PARPORT_CONTROL_AUTOFD);dump_parport_state ("rev idle", port);	/* Do the transfer. */	while (left > fifofull) {		int ret;		unsigned long expire = jiffies + port->cad->timeout;		unsigned char ecrval = inb (ECONTROL (port));		if (need_resched() && time_before (jiffies, expire))			/* Can't yield the port. */			schedule ();		/* At this point, the FIFO may already be full. In                 * that case ECP is already holding back the                 * peripheral (assuming proper design) with a delayed                 * handshake.  Work fast to avoid a peripheral                 * timeout.  */		if (ecrval & 0x01) {			/* FIFO is empty. Wait for interrupt. */dump_parport_state ("FIFO empty", port);			/* Anyone else waiting for the port? */			if (port->waithead) {				printk (KERN_DEBUG "Somebody wants the port\n");				break;			}			/* Clear serviceIntr */			ECR_WRITE (port, ecrval & ~(1<<2));		false_alarm:dump_parport_state ("waiting", port);			ret = parport_wait_event (port, HZ);DPRINTK (KERN_DEBUG "parport_wait_event returned %d\n", ret);			if (ret < 0)				break;			ret = 0;			if (!time_before (jiffies, expire)) {				/* Timed out. */dump_parport_state ("timeout", port);				printk (KERN_DEBUG "PIO read timed out\n");				break;			}			ecrval = inb (ECONTROL (port));			if (!(ecrval & (1<<2))) {				if (need_resched() &&				    time_before (jiffies, expire)) {					schedule ();				}				goto false_alarm;			}			/* Depending on how the FIFO threshold was                         * set, how long interrupt service took, and                         * how fast the peripheral is, we might be                         * lucky and have a just filled FIFO. */			continue;		}		if (ecrval & 0x02) {			/* FIFO is full. */dump_parport_state ("FIFO full", port);			insb (fifo, bufp, fifo_depth);			bufp += fifo_depth;			left -= fifo_depth;			continue;		}DPRINTK (KERN_DEBUG "*** ecp_read_block_pio: reading one byte from the FIFO\n");		/* FIFO not filled.  We will cycle this loop for a while                 * and either the peripheral will fill it faster,                 * tripping a fast empty with insb, or we empty it. */		*bufp++ = inb (fifo);		left--;	}	/* scoop up anything left in the FIFO */	while (left && !(inb (ECONTROL (port) & 0x01))) {		*bufp++ = inb (fifo);		left--;	}	port->ieee1284.phase = IEEE1284_PH_REV_IDLE;dump_parport_state ("rev idle2", port);out_no_data:	/* Go to forward idle mode to shut the peripheral up (event 47). */	parport_frob_control (port, PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT);	/* event 49: PError goes high */	r = parport_wait_peripheral (port,				     PARPORT_STATUS_PAPEROUT,				     PARPORT_STATUS_PAPEROUT);	if (r) {		printk (KERN_DEBUG			"%s: PE timeout FWDIDLE (%d) in ecp_read_block_pio\n",			port->name, r);	}	port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;	/* Finish up. */	{		int lost = get_fifo_residue (port);		if (lost)			/* Shouldn't happen with compliant peripherals. */			printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n",				port->name, lost);	}dump_parport_state ("fwd idle", port);	return length - left;}#endif /* IEEE 1284 support */#endif /* Allowed to use FIFO/DMA *//* *	****************************************** *	INITIALISATION AND MODULE STUFF BELOW HERE *	****************************************** *//* GCC is not inlining extern inline function later overwriten to non-inline,   so we use outlined_ variants here.  */struct parport_operations parport_pc_ops = {	.write_data	= parport_pc_write_data,	.read_data	= parport_pc_read_data,	.write_control	= parport_pc_write_control,	.read_control	= parport_pc_read_control,	.frob_control	= parport_pc_frob_control,	.read_status	= parport_pc_read_status,	.enable_irq	= parport_pc_enable_irq,	.disable_irq	= parport_pc_disable_irq,	.data_forward	= parport_pc_data_forward,	.data_reverse	= parport_pc_data_reverse,	.init_state	= parport_pc_init_state,	.save_state	= parport_pc_save_state,	.restore_state	= parport_pc_restore_state,	.epp_write_data	= parport_ieee1284_epp_write_data,	.epp_read_data	= parport_ieee1284_epp_read_data,	.epp_write_addr	= parport_ieee1284_epp_write_addr,	.epp_read_addr	= parport_ieee1284_epp_read_addr,	.ecp_write_data	= parport_ieee1284_ecp_write_data,	.ecp_read_data	= parport_ieee1284_ecp_read_data,	.ecp_write_addr	= parport_ieee1284_ecp_write_addr,	.compat_write_data	= parport_ieee1284_write_compat,	.nibble_read_data	= parport_ieee1284_read_nibble,	.byte_read_data		= parport_ieee1284_read_byte,	.owner		= THIS_MODULE,};#ifdef CONFIG_PARPORT_PC_SUPERIO/* Super-IO chipset detection, Winbond, SMSC */static int __devinit show_parconfig_smsc37c669(int io, int key){	int cr1,cr4,cra,cr23,cr26,cr27,i=0;	static const char *modes[]={ "SPP and Bidirectional (PS/2)",					     "EPP and SPP",				     "ECP",				     "ECP and EPP" };	outb(key,io);	outb(key,io);	outb(1,io);	cr1=inb(io+1);	outb(4,io);	cr4=inb(io+1);	outb(0x0a,io);	cra=inb(io+1);	outb(0x23,io);	cr23=inb(io+1);	outb(0x26,io);	cr26=inb(io+1);	outb(0x27,io);	cr27=inb(io+1);	outb(0xaa,io);	if (verbose_probing) {		printk (KERN_INFO "SMSC 37c669 LPT Config: cr_1=0x%02x, 4=0x%02x, "			"A=0x%2x, 23=0x%02x, 26=0x%02x, 27=0x%02x\n",			cr1,cr4,cra,cr23,cr26,cr27);				/* The documentation calls DMA and IRQ-Lines by letters, so		   the board maker can/will wire them		   appropriately/randomly...  G=reserved H=IDE-irq, */		printk (KERN_INFO "SMSC LPT Config: io=0x%04x, irq=%c, dma=%c, "			"fifo threshold=%d\n", cr23*4,			(cr27 &0x0f) ? 'A'-1+(cr27 &0x0f): '-',			(cr26 &0x0f) ? 'A'-1+(cr26 &0x0f): '-', cra & 0x0f);		printk(KERN_INFO "SMSC LPT Config: enabled=%s power=%s\n",		       (cr23*4 >=0x100) ?"yes":"no", (cr1 & 4) ? "yes" : "no");		printk(KERN_INFO "SMSC LPT Config: Port mode=%s, EPP version =%s\n",		       (cr1 & 0x08 ) ? "Standard mode only (SPP)" : modes[cr4 & 0x03], 		       (cr4 & 0x40) ? "1.7" : "1.9");	}			/* Heuristics !  BIOS setup for this mainboard device limits	   the choices to standard settings, i.e. io-address and IRQ	   are related, however DMA can be 1 or 3, assume DMA_A=DMA1,	   DMA_C=DMA3 (this is true e.g. for TYAN 1564D Tomcat IV) */	if(cr23*4 >=0x100) { /* if active */		while((superios[i].io!= 0) && (i<NR_SUPERIOS))			i++;		if(i==NR_SUPERIOS)			printk(KERN_INFO "Super-IO: too many chips!\n");		else {			int d;			switch (cr23*4) {				case 0x3bc:					superios[i].io = 0x3bc;					superios[i].irq = 7;					break;				case 0x378:					superios[i].io = 0x378;					superios[i].irq = 7;					break;				case 0x278:					superios[i].io = 0x278;					superios[i].irq = 5;			}			if (io != superios[i].io) {				/* how many bytes? */				if (!request_region(superios[i].io, 3, "smsc parport")) {					superios[i].io = 0;					return 0;				}			}			d=(cr26 &0x0f);			if((d==1) || (d==3)) 				superios[i].dma= d;			else				superios[i].dma= PARPORT_DMA_NONE;			return 1;		} 	}	return 0;}static int __devinit show_parconfig_winbond(int io, int key){	int cr30,cr60,cr61,cr70,cr74,crf0,i=0;	static const char *modes[] = {		"Standard (SPP) and Bidirectional(PS/2)", /* 0 */		"EPP-1.9 and SPP",		"ECP",		"ECP and EPP-1.9",		"Standard (SPP)",		"EPP-1.7 and SPP",		/* 5 */		"undefined!",		"ECP and EPP-1.7" };	static char *irqtypes[] = { "pulsed low, high-Z", "follows nACK" };			/* The registers are called compatible-PnP because the           register layout is modelled after ISA-PnP, the access           method is just another ... */	outb(key,io);	outb(key,io);	outb(0x07,io);   /* Register 7: Select Logical Device */	outb(0x01,io+1); /* LD1 is Parallel Port */	outb(0x30,io);	cr30=inb(io+1);	outb(0x60,io);	cr60=inb(io+1);	outb(0x61,io);	cr61=inb(io+1);	outb(0x70,io);	cr70=inb(io+1);	outb(0x74,io);	cr74=inb(io+1);	outb(0xf0,io);	crf0=inb(io+1);	outb(0xaa,io);	if (verbose_probing) {		printk(KERN_INFO "Winbond LPT Config: cr_30=%02x 60,61=%02x%02x "		       "70=%02x 74=%02x, f0=%02x\n", cr30,cr60,cr61,cr70,cr74,crf0);		printk(KERN_INFO "Winbond LPT Config: active=%s, io=0x%02x%02x irq=%d, ", 		       (cr30 & 0x01) ? "yes":"no", cr60,cr61,cr70&0x0f );		if ((cr74 & 0x07) > 3)			printk("dma=none\n");		else			printk("dma=%d\n",cr74 & 0x07);		printk(KERN_INFO "Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n",		       irqtypes[crf0>>7], (crf0>>3)&0x0f);		printk(KERN_INFO "Winbond LPT Config: Port mode=%s\n", modes[crf0 & 0x07]);	}	if(cr30 & 0x01) { /* the settings can be interrogated later ... */		while((superios[i].io!= 0) && (i<NR_SUPERIOS))			i++;		if(i==NR_SUPERIOS) 			printk(KERN_INFO "Super-IO: too many chips!\n");		else {			superios[i].io = (cr60<<8)|cr61;			if (io != superios[i].io) {				/* how many bytes? */				if (!request_region(superios[i].io, 3, "winbond parport")) {					superios[i].io = 0;					return 0;				}			}			superios[i].irq = cr70&0x0f;			superios[i].dma = (((cr74 & 0x07) > 3) ?					   PARPORT_DMA_NONE : (cr74 & 0x07));			return 1;		}	}	return 0;}static int __devinit decode_winbond(int efer, int key, int devid, int devrev, int oldid){	const char *type = "unknown";	int id,progif=2;	if (devid == devrev)		/* simple heuristics, we happened to read some                   non-winbond register */		return 0;	id=(devid<<8) | devrev;	/* Values are from public data sheets pdf files, I can just           confirm 83977TF is correct :-) */	if      (id == 0x9771) type="83977F/AF";	else if (id == 0x9773) type="83977TF / SMSC 97w33x/97w34x";	else if (id == 0x9774) type="83977ATF";	else if ((id & ~0x0f) == 0x5270) type="83977CTF / SMSC 97w36x";	else if ((id & ~0x0f) == 0x52f0) type="83977EF / SMSC 97w35x";	else if ((id & ~0x0f) == 0x5210) type="83627";	else if ((id & ~0x0f) == 0x6010) type="83697HF";	else if ((oldid &0x0f ) == 0x0a) { type="83877F"; progif=1;}	else if ((oldid &0x0f ) == 0x0b) { type="83877AF"; progif=1;}	else if ((oldid &0x0f ) == 0x0c) { type="83877TF"; progif=1;}	else if ((oldid &0x0f ) == 0x0d) { type="83877ATF"; progif=1;}	else progif=0;	if (verbose_probing)		printk(KERN_INFO "Winbond chip at EFER=0x%x key=0x%02x "		       "devid=%02x devrev=%02x oldid=%02x type=%s\n", 		       efer, key, devid, devrev, oldid, type);	if (progif == 2)		return show_parconfig_winbond(efer,key);	return 0;}static int __devinit decode_smsc(int efer, int key, int devid, int devrev){        const char *type = "unknown";	int (*func)(int io, int key);        int id;        if (devid == devrev)		/* simple heuristics, we happened to read some                   non-smsc register */		return 0;	func=NULL;        id=(devid<<8) | devrev;	if	(id==0x0302) {type="37c669"; func=show_parconfig_smsc37c669;}	else if	(id==0x6582) type="37c665IR";	else if	(devid==0x65) type="37c665GT";	else if	(devid==0x66) type="37c666GT";	if (verbose_probing)		printk(KERN_INFO "SMSC chip at EFER=0x%x "		       "key=0x%02x devid=%02x devrev=%02x type=%s\n",		       efer, key, devid, devrev, type);	if (func)		return func(efer,key);	return 0;}static void __devinit winbond_check(int io, int key){	int devid,devrev,oldid,x_devid,x_devrev,x_oldid;	if (!request_region(io, 3, __FUNCTION__))		return;	/* First probe without key */	outb(0x20,io);	x_devid=inb(io+1);	outb(0x21,io);	x_devrev=inb(io+1);	outb(0x09,io);	x_oldid=inb(io+1);	outb(key,io);	outb(key,io);     /* Write Magic Sequence to EFER, extended                             funtion enable register */	outb(0x20,io);    /* Write EFIR, extended function index register */	devid=inb(io+1);  /* Read EFDR, extended function data register */	outb(0x21,io);	devrev=inb(io+1);	outb(0x09,io);	oldid=inb(io+1);	outb(0xaa,io);    /* Magic Seal */	if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid))		goto out; /* protection against false positives */	if (decode_winbond(io,key,devid,devrev,oldid));		return;out:	release_region(io, 3);}static void __devinit winbond_check2(int io,int key){        int devid,devrev,oldid,x_devid,x_devrev,x_oldid;	if (!request_region(io, 3, __FUNCTION__))		return;	/* First probe without the key */	outb(0x20,io+2);	x_devid=inb(io+2);	outb(0x21,io+1);	x_devrev=inb(io+2);	outb(0x09,io+1);	x_oldid=inb(io+2);        outb(key,io);     /* Write Magic Byte to EFER, extended                             funtion enable register */        outb(0x20,io+2);  /* Write EFIR, extended function index register */        devid=inb(io+2);  /* Read EFDR, extended function data register */        outb(0x21,io+1);

⌨️ 快捷键说明

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