// SPDX-License-Identifier: GPL-2.0 /* IEEE-1284 operations for parport. * * This file is for generic IEEE 1284 operations. The idea is that * they are used by the low-level drivers. If they have a special way * of doing something, they can provide their own routines (and put * the function pointers in port->ops); if not, they can just use these * as a fallback. * * Note: Make no assumptions about hardware or architecture in this file! * * Author: Tim Waugh <tim@cyberelk.demon.co.uk> * Fixed AUTOFD polarity in ecp_forward_to_reverse(). Fred Barnes, 1999 * Software emulated EPP fixes, Fred Barnes, 04/2001.
*/
/* Wait until the peripheral's ready */ do { /* Is the peripheral ready yet? */ if (!parport_wait_peripheral (port, mask, val)) /* Skip the loop */ goto ready;
/* Is the peripheral upset? */ if ((parport_read_status (port) &
(PARPORT_STATUS_PAPEROUT |
PARPORT_STATUS_SELECT |
PARPORT_STATUS_ERROR))
!= (PARPORT_STATUS_SELECT |
PARPORT_STATUS_ERROR)) /* If nFault is asserted (i.e. no * error) and PAPEROUT and SELECT are * just red herrings, give the driver * a chance to check it's happy with
* that before continuing. */ goto stop;
/* Have we run out of time? */ if (!time_before (jiffies, expire)) break;
/* Yield the port for a while. If this is the first time around the loop, don't let go of the port. This way, we find out if we have
our interrupt handler called. */ if (count && no_irq) {
parport_release (dev);
schedule_timeout_interruptible(wait);
parport_claim_or_block (dev);
} else /* We must have the device claimed here */
parport_wait_event (port, wait);
/* Is there a signal pending? */ if (signal_pending (current)) break;
/* Wait longer next time. */
wait *= 2;
} while (time_before (jiffies, expire));
if (signal_pending (current)) break;
pr_debug("%s: Timed out\n", port->name); break;
ready: /* Write the character to the data lines. */
byte = *addr++;
parport_write_data (port, byte);
udelay (1);
parport_write_control (port, ctl);
udelay (1); /* hold */
/* Assume the peripheral received it. */
count++;
/* Let another process run if it needs to. */ if (time_before (jiffies, expire)) if (!parport_yield_blocking (dev)
&& need_resched())
schedule ();
}
stop:
port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
/* Event 11: nAck goes high. */ if (parport_wait_peripheral (port,
PARPORT_STATUS_ACK,
PARPORT_STATUS_ACK)) { /* Timeout -- no more data? */
pr_debug("%s: Nibble timeout at event 11\n",
port->name); break;
}
if (i & 1) { /* Second nibble */
byte |= nibble << 4;
*buf++ = byte;
} else
byte = nibble;
}
if (i == len) { /* Read the last nibble without checking data avail. */ if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
end_of_data:
pr_debug("%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;
} else
port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
}
if (count == len) { /* Read the last byte without checking data avail. */ if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
end_of_data:
pr_debug("%s: No more byte data (%zd bytes)\n",
port->name, count);
/* Go to reverse idle phase. */
parport_frob_control (port,
PARPORT_CONTROL_AUTOFD,
PARPORT_CONTROL_AUTOFD);
port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
} else
port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
}
return count; #endif/* IEEE1284 support */
}
/*** * * ECP Functions. *
* ***/
#ifdef CONFIG_PARPORT_1284
staticinline int ecp_forward_to_reverse (struct parport *port)
{ int retval;
if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) if (ecp_forward_to_reverse (port)) return 0;
port->ieee1284.phase = IEEE1284_PH_REV_DATA;
/* Set HostAck low to start accepting data. */
ctl = parport_read_control (port);
ctl &= ~(PARPORT_CONTROL_STROBE | PARPORT_CONTROL_INIT |
PARPORT_CONTROL_AUTOFD);
parport_write_control (port,
ctl | PARPORT_CONTROL_AUTOFD); while (count < len) { unsignedlong expire = jiffies + dev->timeout; unsignedchar byte; int command;
/* Event 43: Peripheral sets nAck low. It can take as
long as it wants. */ while (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) { /* The peripheral hasn't given us data in 35ms. If we have data to give back to the
caller, do it now. */ if (count) goto out;
/* If we've used up all the time we were allowed,
give up altogether. */ if (!time_before (jiffies, expire)) goto out;
/* Yield the port for a while. */ if (dev->port->irq != PARPORT_IRQ_NONE) {
parport_release (dev);
schedule_timeout_interruptible(msecs_to_jiffies(40));
parport_claim_or_block (dev);
} else /* We must have the device claimed here. */
parport_wait_event (port, msecs_to_jiffies(40));
/* Is there a signal pending? */ if (signal_pending (current)) goto out;
}
/* Is this a command? */ if (rle) /* The last byte was a run-length count, so
this can't be as well. */
command = 0; else
command = (parport_read_status (port) &
PARPORT_STATUS_BUSY) ? 1 : 0;
/* Read the data. */
byte = parport_read_data (port);
/* If this is a channel command, rather than an RLE
command or a normal data byte, don't accept it. */ if (command) { if (byte & 0x80) {
pr_debug("%s: stopping short at channel command (%02x)\n",
port->name, byte); goto out;
} elseif (port->ieee1284.mode != IEEE1284_MODE_ECPRLE)
pr_debug("%s: device illegally using RLE; accepting anyway\n",
port->name);
rle_count = byte + 1;
/* Are we allowed to read that many bytes? */ if (rle_count > (len - count)) {
pr_debug("%s: leaving %d RLE bytes for next time\n",
port->name, rle_count); break;
}
/* Event 45: The peripheral has 35ms to set nAck high. */ if (parport_wait_peripheral (port, PARPORT_STATUS_ACK,
PARPORT_STATUS_ACK)) { /* It's gone wrong. Return what data we have
to the caller. */
pr_debug("ECP read timed out at 45\n");
if (command)
pr_warn("%s: command ignored (%02x)\n",
port->name, byte);
break;
}
/* Event 46: Set HostAck low and accept the data. */
parport_write_control (port,
ctl | PARPORT_CONTROL_AUTOFD);
/* If we just read a run-length count, fetch the data. */ if (command) continue;
/* If this is the byte after a run-length count, decompress. */ if (rle) {
rle = 0;
memset (buf, byte, rle_count);
buf += rle_count;
count += rle_count;
pr_debug("%s: decompressed to %d bytes\n",
port->name, rle_count);
} else { /* Normal data byte. */
*buf = byte;
buf++, count++;
}
}
/* set EPP idle state (just to make sure) with strobe high */
parport_frob_control (port,
PARPORT_CONTROL_STROBE |
PARPORT_CONTROL_AUTOFD |
PARPORT_CONTROL_SELECT |
PARPORT_CONTROL_INIT,
PARPORT_CONTROL_INIT);
port->ops->data_reverse (port); for (; len > 0; len--, bp++) { /* Event 67: set nAutoFd (nDStrb) low */
parport_frob_control (port,
PARPORT_CONTROL_AUTOFD,
PARPORT_CONTROL_AUTOFD); /* Event 58: wait for Busy to go high */ if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0)) { break;
}
*bp = parport_read_data (port);
/* Event 63: set nAutoFd (nDStrb) high */
parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
/* Event 60: wait for Busy to go low */ if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
PARPORT_STATUS_BUSY, 5)) { break;
}
/* Set EPP idle state (just to make sure) with strobe high */
parport_frob_control (port,
PARPORT_CONTROL_STROBE |
PARPORT_CONTROL_AUTOFD |
PARPORT_CONTROL_SELECT |
PARPORT_CONTROL_INIT,
PARPORT_CONTROL_INIT);
port->ops->data_reverse (port); for (; len > 0; len--, bp++) { /* Event 64: set nSelectIn (nAStrb) low */
parport_frob_control (port, PARPORT_CONTROL_SELECT,
PARPORT_CONTROL_SELECT);
/* Event 58: wait for Busy to go high */ if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0)) { break;
}
*bp = parport_read_data (port);
/* Event 59: set nSelectIn (nAStrb) high */
parport_frob_control (port, PARPORT_CONTROL_SELECT,
0);
/* Event 60: wait for Busy to go low */ if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
PARPORT_STATUS_BUSY, 5)) break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.