[Linux-parport] Problem with ECP+EPP

vdb128 at picaros.org vdb128 at picaros.org
Wed Apr 20 13:18:04 EDT 2005


> > > /* Check for Intel bug. */
> > > if (priv->ecr) {
> > > 	unsigned char i;
> > > 	for (i = 0x00; i < 0x80; i += 0x20) {
> > > 		ECR_WRITE (pb, i);
> > > 		if (clear_epp_timeout (pb)) {
> > > 			/* Phony EPP in ECP. */
> > > 			return 0;
> > > 		}
> > > 	}
> > > }

This code often disables the EPP mode where it shouldn't.  Moreover,
it enables interrupts and usually initiates a spurious interrupt.  If
another handler is already installed (shared IRQ) then the 
kernel will not disable the IRQ in the PIC, which leads to a screaming
interrupt for PCI cards ... locking up the system.  The PCI intx# lines
are level sensitive.

So I support removal of the Intel test and propose to combine 
parport_EPP_supported() and parport_ECPEPP_supported() into one 
routine.  This gives something like 

static int __devinit parport_EPP_supported(struct parport *pb) {
	struct parport_pc_private *priv = pb->private_data;
	int result=0;
	unsigned char oecr=0x34;

	if (priv->ecrok) {
	  oecr = inb (ECONTROL (pb));
	  /* Search for SMC style EPP+ECP mode */
	  ECR_WRITE (pb, ECR_EPP<<5 | 0x14);   /* EPP no interrupts for PCI */
	  outb (0x04, CONTROL (pb));
	}

	/*
	 * Theory:
	 *	Bit 0 of STR is the EPP timeout bit, this bit is 0
	 *	when EPP is possible and is set high when an EPP timeout
	 *	occurs (EPP uses the HALT line to stop the CPU while it does
	 *	the byte transfer, an EPP timeout occurs if the attached
	 *	device fails to respond after 10 micro seconds).
	 *
	 *	This bit is cleared by either reading it (National Semi, 
	 *	Netmos, Oxford Semi)
	 *	or writing a 1 to the bit (SMC, UMC, WinBond), others ???
	 *	This bit is always high in non EPP modes.  (except Netmos)
	 */

	/* If EPP timeout bit clear then EPP available */
	if (!clear_epp_timeout(pb)) 
		goto end;  /* No way to clear timeout */

	pb->modes |= PARPORT_MODE_EPP;

	/* Set up access functions to use EPP hardware. */
	if(!priv->ecrok) {
	  pb->ops->epp_read_data = parport_pc_epp_read_data;
	  pb->ops->epp_write_data = parport_pc_epp_write_data;
	  pb->ops->epp_read_addr = parport_pc_epp_read_addr;
	  pb->ops->epp_write_addr = parport_pc_epp_write_addr;
	} else {
	  /* Set up access functions to use ECP+EPP hardware. */
	  pb->ops->epp_read_data = parport_pc_ecpepp_read_data;
	  pb->ops->epp_write_data = parport_pc_ecpepp_write_data;
	  pb->ops->epp_read_addr = parport_pc_ecpepp_read_addr;
	  pb->ops->epp_write_addr = parport_pc_ecpepp_write_addr;
	}

	result=1;
 end:
	if (priv->ecrok) 
	  ECR_WRITE (pb, oecr);

	if (verbose_probing) {
	  printk (KERN_DEBUG "parport_EPP_supported(%s): result=%d\n", 
		  pb->name, result);
	}
	return(result);
}

The EPP detection in parport_pc_probe_port() then reduces to

  if (base != 0x3bc && !check_region(base+0x3, 5))
    parport_EPP_supported(p);

A further description is at  picaros.org/ftp/key/parport-2.4.23.diff .
This diff modifies too much but might get ported to the 2.6 kernel in
parts if there is interest.  (the cli sti should be replaced by semaphores)



More information about the Linux-parport mailing list