1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /* IEEE-1284 operations for parport.
31da177e4SLinus Torvalds *
41da177e4SLinus Torvalds * This file is for generic IEEE 1284 operations. The idea is that
51da177e4SLinus Torvalds * they are used by the low-level drivers. If they have a special way
61da177e4SLinus Torvalds * of doing something, they can provide their own routines (and put
71da177e4SLinus Torvalds * the function pointers in port->ops); if not, they can just use these
81da177e4SLinus Torvalds * as a fallback.
91da177e4SLinus Torvalds *
101da177e4SLinus Torvalds * Note: Make no assumptions about hardware or architecture in this file!
111da177e4SLinus Torvalds *
121da177e4SLinus Torvalds * Author: Tim Waugh <tim@cyberelk.demon.co.uk>
131da177e4SLinus Torvalds * Fixed AUTOFD polarity in ecp_forward_to_reverse(). Fred Barnes, 1999
141da177e4SLinus Torvalds * Software emulated EPP fixes, Fred Barnes, 04/2001.
151da177e4SLinus Torvalds */
161da177e4SLinus Torvalds
171da177e4SLinus Torvalds
181da177e4SLinus Torvalds #include <linux/module.h>
191da177e4SLinus Torvalds #include <linux/parport.h>
201da177e4SLinus Torvalds #include <linux/delay.h>
21174cd4b1SIngo Molnar #include <linux/sched/signal.h>
227c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
231da177e4SLinus Torvalds
241da177e4SLinus Torvalds #undef DEBUG /* undef me for production */
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds #ifdef CONFIG_LP_CONSOLE
271da177e4SLinus Torvalds #undef DEBUG /* Don't want a garbled console */
281da177e4SLinus Torvalds #endif
291da177e4SLinus Torvalds
301da177e4SLinus Torvalds /*** *
311da177e4SLinus Torvalds * One-way data transfer functions. *
321da177e4SLinus Torvalds * ***/
331da177e4SLinus Torvalds
341da177e4SLinus Torvalds /* Compatibility mode. */
parport_ieee1284_write_compat(struct parport * port,const void * buffer,size_t len,int flags)351da177e4SLinus Torvalds size_t parport_ieee1284_write_compat (struct parport *port,
361da177e4SLinus Torvalds const void *buffer, size_t len,
371da177e4SLinus Torvalds int flags)
381da177e4SLinus Torvalds {
391da177e4SLinus Torvalds int no_irq = 1;
401da177e4SLinus Torvalds ssize_t count = 0;
411da177e4SLinus Torvalds const unsigned char *addr = buffer;
421da177e4SLinus Torvalds unsigned char byte;
431da177e4SLinus Torvalds struct pardevice *dev = port->physport->cad;
441da177e4SLinus Torvalds unsigned char ctl = (PARPORT_CONTROL_SELECT
451da177e4SLinus Torvalds | PARPORT_CONTROL_INIT);
461da177e4SLinus Torvalds
471da177e4SLinus Torvalds if (port->irq != PARPORT_IRQ_NONE) {
481da177e4SLinus Torvalds parport_enable_irq (port);
491da177e4SLinus Torvalds no_irq = 0;
501da177e4SLinus Torvalds }
511da177e4SLinus Torvalds
521da177e4SLinus Torvalds port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
531da177e4SLinus Torvalds parport_write_control (port, ctl);
541da177e4SLinus Torvalds parport_data_forward (port);
551da177e4SLinus Torvalds while (count < len) {
561da177e4SLinus Torvalds unsigned long expire = jiffies + dev->timeout;
577b4ccf8dSNishanth Aravamudan long wait = msecs_to_jiffies(10);
581da177e4SLinus Torvalds unsigned char mask = (PARPORT_STATUS_ERROR
591da177e4SLinus Torvalds | PARPORT_STATUS_BUSY);
601da177e4SLinus Torvalds unsigned char val = (PARPORT_STATUS_ERROR
611da177e4SLinus Torvalds | PARPORT_STATUS_BUSY);
621da177e4SLinus Torvalds
631da177e4SLinus Torvalds /* Wait until the peripheral's ready */
641da177e4SLinus Torvalds do {
651da177e4SLinus Torvalds /* Is the peripheral ready yet? */
661da177e4SLinus Torvalds if (!parport_wait_peripheral (port, mask, val))
671da177e4SLinus Torvalds /* Skip the loop */
681da177e4SLinus Torvalds goto ready;
691da177e4SLinus Torvalds
701da177e4SLinus Torvalds /* Is the peripheral upset? */
711da177e4SLinus Torvalds if ((parport_read_status (port) &
721da177e4SLinus Torvalds (PARPORT_STATUS_PAPEROUT |
731da177e4SLinus Torvalds PARPORT_STATUS_SELECT |
741da177e4SLinus Torvalds PARPORT_STATUS_ERROR))
751da177e4SLinus Torvalds != (PARPORT_STATUS_SELECT |
761da177e4SLinus Torvalds PARPORT_STATUS_ERROR))
771da177e4SLinus Torvalds /* If nFault is asserted (i.e. no
781da177e4SLinus Torvalds * error) and PAPEROUT and SELECT are
791da177e4SLinus Torvalds * just red herrings, give the driver
801da177e4SLinus Torvalds * a chance to check it's happy with
811da177e4SLinus Torvalds * that before continuing. */
821da177e4SLinus Torvalds goto stop;
831da177e4SLinus Torvalds
841da177e4SLinus Torvalds /* Have we run out of time? */
851da177e4SLinus Torvalds if (!time_before (jiffies, expire))
861da177e4SLinus Torvalds break;
871da177e4SLinus Torvalds
881da177e4SLinus Torvalds /* Yield the port for a while. If this is the
891da177e4SLinus Torvalds first time around the loop, don't let go of
901da177e4SLinus Torvalds the port. This way, we find out if we have
911da177e4SLinus Torvalds our interrupt handler called. */
921da177e4SLinus Torvalds if (count && no_irq) {
931da177e4SLinus Torvalds parport_release (dev);
947b4ccf8dSNishanth Aravamudan schedule_timeout_interruptible(wait);
951da177e4SLinus Torvalds parport_claim_or_block (dev);
961da177e4SLinus Torvalds }
971da177e4SLinus Torvalds else
981da177e4SLinus Torvalds /* We must have the device claimed here */
991da177e4SLinus Torvalds parport_wait_event (port, wait);
1001da177e4SLinus Torvalds
1011da177e4SLinus Torvalds /* Is there a signal pending? */
1021da177e4SLinus Torvalds if (signal_pending (current))
1031da177e4SLinus Torvalds break;
1041da177e4SLinus Torvalds
1051da177e4SLinus Torvalds /* Wait longer next time. */
1061da177e4SLinus Torvalds wait *= 2;
1071da177e4SLinus Torvalds } while (time_before (jiffies, expire));
1081da177e4SLinus Torvalds
1091da177e4SLinus Torvalds if (signal_pending (current))
1101da177e4SLinus Torvalds break;
1111da177e4SLinus Torvalds
112d98ce9feSJoe Perches pr_debug("%s: Timed out\n", port->name);
1131da177e4SLinus Torvalds break;
1141da177e4SLinus Torvalds
1151da177e4SLinus Torvalds ready:
1161da177e4SLinus Torvalds /* Write the character to the data lines. */
1171da177e4SLinus Torvalds byte = *addr++;
1181da177e4SLinus Torvalds parport_write_data (port, byte);
1191da177e4SLinus Torvalds udelay (1);
1201da177e4SLinus Torvalds
1211da177e4SLinus Torvalds /* Pulse strobe. */
1221da177e4SLinus Torvalds parport_write_control (port, ctl | PARPORT_CONTROL_STROBE);
1231da177e4SLinus Torvalds udelay (1); /* strobe */
1241da177e4SLinus Torvalds
1251da177e4SLinus Torvalds parport_write_control (port, ctl);
1261da177e4SLinus Torvalds udelay (1); /* hold */
1271da177e4SLinus Torvalds
1281da177e4SLinus Torvalds /* Assume the peripheral received it. */
1291da177e4SLinus Torvalds count++;
1301da177e4SLinus Torvalds
1311da177e4SLinus Torvalds /* Let another process run if it needs to. */
1321da177e4SLinus Torvalds if (time_before (jiffies, expire))
1331da177e4SLinus Torvalds if (!parport_yield_blocking (dev)
1341da177e4SLinus Torvalds && need_resched())
1351da177e4SLinus Torvalds schedule ();
1361da177e4SLinus Torvalds }
1371da177e4SLinus Torvalds stop:
1381da177e4SLinus Torvalds port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
1391da177e4SLinus Torvalds
1401da177e4SLinus Torvalds return count;
1411da177e4SLinus Torvalds }
1421da177e4SLinus Torvalds
1431da177e4SLinus Torvalds /* Nibble mode. */
parport_ieee1284_read_nibble(struct parport * port,void * buffer,size_t len,int flags)1441da177e4SLinus Torvalds size_t parport_ieee1284_read_nibble (struct parport *port,
1451da177e4SLinus Torvalds void *buffer, size_t len,
1461da177e4SLinus Torvalds int flags)
1471da177e4SLinus Torvalds {
1481da177e4SLinus Torvalds #ifndef CONFIG_PARPORT_1284
1491da177e4SLinus Torvalds return 0;
1501da177e4SLinus Torvalds #else
1511da177e4SLinus Torvalds unsigned char *buf = buffer;
1521da177e4SLinus Torvalds int i;
1531da177e4SLinus Torvalds unsigned char byte = 0;
1541da177e4SLinus Torvalds
1551da177e4SLinus Torvalds len *= 2; /* in nibbles */
1561da177e4SLinus Torvalds for (i=0; i < len; i++) {
1571da177e4SLinus Torvalds unsigned char nibble;
1581da177e4SLinus Torvalds
1591da177e4SLinus Torvalds /* Does the error line indicate end of data? */
1601da177e4SLinus Torvalds if (((i & 1) == 0) &&
1611da177e4SLinus Torvalds (parport_read_status(port) & PARPORT_STATUS_ERROR)) {
162742ec650SMarko Kohtala goto end_of_data;
1631da177e4SLinus Torvalds }
1641da177e4SLinus Torvalds
1651da177e4SLinus Torvalds /* Event 7: Set nAutoFd low. */
1661da177e4SLinus Torvalds parport_frob_control (port,
1671da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD,
1681da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD);
1691da177e4SLinus Torvalds
1701da177e4SLinus Torvalds /* Event 9: nAck goes low. */
1711da177e4SLinus Torvalds port->ieee1284.phase = IEEE1284_PH_REV_DATA;
1721da177e4SLinus Torvalds if (parport_wait_peripheral (port,
1731da177e4SLinus Torvalds PARPORT_STATUS_ACK, 0)) {
1741da177e4SLinus Torvalds /* Timeout -- no more data? */
175d98ce9feSJoe Perches pr_debug("%s: Nibble timeout at event 9 (%d bytes)\n",
1761da177e4SLinus Torvalds port->name, i / 2);
1771da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
1781da177e4SLinus Torvalds break;
1791da177e4SLinus Torvalds }
1801da177e4SLinus Torvalds
1811da177e4SLinus Torvalds
1821da177e4SLinus Torvalds /* Read a nibble. */
1831da177e4SLinus Torvalds nibble = parport_read_status (port) >> 3;
1841da177e4SLinus Torvalds nibble &= ~8;
1851da177e4SLinus Torvalds if ((nibble & 0x10) == 0)
1861da177e4SLinus Torvalds nibble |= 8;
1871da177e4SLinus Torvalds nibble &= 0xf;
1881da177e4SLinus Torvalds
1891da177e4SLinus Torvalds /* Event 10: Set nAutoFd high. */
1901da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
1911da177e4SLinus Torvalds
1921da177e4SLinus Torvalds /* Event 11: nAck goes high. */
1931da177e4SLinus Torvalds if (parport_wait_peripheral (port,
1941da177e4SLinus Torvalds PARPORT_STATUS_ACK,
1951da177e4SLinus Torvalds PARPORT_STATUS_ACK)) {
1961da177e4SLinus Torvalds /* Timeout -- no more data? */
197d98ce9feSJoe Perches pr_debug("%s: Nibble timeout at event 11\n",
1981da177e4SLinus Torvalds port->name);
1991da177e4SLinus Torvalds break;
2001da177e4SLinus Torvalds }
2011da177e4SLinus Torvalds
2021da177e4SLinus Torvalds if (i & 1) {
2031da177e4SLinus Torvalds /* Second nibble */
2041da177e4SLinus Torvalds byte |= nibble << 4;
2051da177e4SLinus Torvalds *buf++ = byte;
2061da177e4SLinus Torvalds } else
2071da177e4SLinus Torvalds byte = nibble;
2081da177e4SLinus Torvalds }
2091da177e4SLinus Torvalds
2101da177e4SLinus Torvalds if (i == len) {
2111da177e4SLinus Torvalds /* Read the last nibble without checking data avail. */
212742ec650SMarko Kohtala if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
213742ec650SMarko Kohtala end_of_data:
214d98ce9feSJoe Perches pr_debug("%s: No more nibble data (%d bytes)\n",
215742ec650SMarko Kohtala port->name, i / 2);
216742ec650SMarko Kohtala
217742ec650SMarko Kohtala /* Go to reverse idle phase. */
218742ec650SMarko Kohtala parport_frob_control (port,
219742ec650SMarko Kohtala PARPORT_CONTROL_AUTOFD,
220742ec650SMarko Kohtala PARPORT_CONTROL_AUTOFD);
221742ec650SMarko Kohtala port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
222742ec650SMarko Kohtala }
2231da177e4SLinus Torvalds else
224742ec650SMarko Kohtala port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
2251da177e4SLinus Torvalds }
2261da177e4SLinus Torvalds
227742ec650SMarko Kohtala return i/2;
2281da177e4SLinus Torvalds #endif /* IEEE1284 support */
2291da177e4SLinus Torvalds }
2301da177e4SLinus Torvalds
2311da177e4SLinus Torvalds /* Byte mode. */
parport_ieee1284_read_byte(struct parport * port,void * buffer,size_t len,int flags)2321da177e4SLinus Torvalds size_t parport_ieee1284_read_byte (struct parport *port,
2331da177e4SLinus Torvalds void *buffer, size_t len,
2341da177e4SLinus Torvalds int flags)
2351da177e4SLinus Torvalds {
2361da177e4SLinus Torvalds #ifndef CONFIG_PARPORT_1284
2371da177e4SLinus Torvalds return 0;
2381da177e4SLinus Torvalds #else
2391da177e4SLinus Torvalds unsigned char *buf = buffer;
2401da177e4SLinus Torvalds ssize_t count = 0;
2411da177e4SLinus Torvalds
2421da177e4SLinus Torvalds for (count = 0; count < len; count++) {
2431da177e4SLinus Torvalds unsigned char byte;
2441da177e4SLinus Torvalds
2451da177e4SLinus Torvalds /* Data available? */
2461da177e4SLinus Torvalds if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
247742ec650SMarko Kohtala goto end_of_data;
2481da177e4SLinus Torvalds }
2491da177e4SLinus Torvalds
2501da177e4SLinus Torvalds /* Event 14: Place data bus in high impedance state. */
2511da177e4SLinus Torvalds parport_data_reverse (port);
2521da177e4SLinus Torvalds
2531da177e4SLinus Torvalds /* Event 7: Set nAutoFd low. */
2541da177e4SLinus Torvalds parport_frob_control (port,
2551da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD,
2561da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD);
2571da177e4SLinus Torvalds
2581da177e4SLinus Torvalds /* Event 9: nAck goes low. */
2591da177e4SLinus Torvalds port->physport->ieee1284.phase = IEEE1284_PH_REV_DATA;
2601da177e4SLinus Torvalds if (parport_wait_peripheral (port,
2611da177e4SLinus Torvalds PARPORT_STATUS_ACK,
2621da177e4SLinus Torvalds 0)) {
2631da177e4SLinus Torvalds /* Timeout -- no more data? */
2641da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
2651da177e4SLinus Torvalds 0);
266d98ce9feSJoe Perches pr_debug("%s: Byte timeout at event 9\n", port->name);
2671da177e4SLinus Torvalds break;
2681da177e4SLinus Torvalds }
2691da177e4SLinus Torvalds
2701da177e4SLinus Torvalds byte = parport_read_data (port);
2711da177e4SLinus Torvalds *buf++ = byte;
2721da177e4SLinus Torvalds
2731da177e4SLinus Torvalds /* Event 10: Set nAutoFd high */
2741da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
2751da177e4SLinus Torvalds
2761da177e4SLinus Torvalds /* Event 11: nAck goes high. */
2771da177e4SLinus Torvalds if (parport_wait_peripheral (port,
2781da177e4SLinus Torvalds PARPORT_STATUS_ACK,
2791da177e4SLinus Torvalds PARPORT_STATUS_ACK)) {
2801da177e4SLinus Torvalds /* Timeout -- no more data? */
281d98ce9feSJoe Perches pr_debug("%s: Byte timeout at event 11\n", port->name);
2821da177e4SLinus Torvalds break;
2831da177e4SLinus Torvalds }
2841da177e4SLinus Torvalds
2851da177e4SLinus Torvalds /* Event 16: Set nStrobe low. */
2861da177e4SLinus Torvalds parport_frob_control (port,
2871da177e4SLinus Torvalds PARPORT_CONTROL_STROBE,
2881da177e4SLinus Torvalds PARPORT_CONTROL_STROBE);
2891da177e4SLinus Torvalds udelay (5);
2901da177e4SLinus Torvalds
2911da177e4SLinus Torvalds /* Event 17: Set nStrobe high. */
2921da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
2931da177e4SLinus Torvalds }
2941da177e4SLinus Torvalds
2951da177e4SLinus Torvalds if (count == len) {
2961da177e4SLinus Torvalds /* Read the last byte without checking data avail. */
297742ec650SMarko Kohtala if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
298742ec650SMarko Kohtala end_of_data:
299d98ce9feSJoe Perches pr_debug("%s: No more byte data (%zd bytes)\n",
300742ec650SMarko Kohtala port->name, count);
301742ec650SMarko Kohtala
302742ec650SMarko Kohtala /* Go to reverse idle phase. */
303742ec650SMarko Kohtala parport_frob_control (port,
304742ec650SMarko Kohtala PARPORT_CONTROL_AUTOFD,
305742ec650SMarko Kohtala PARPORT_CONTROL_AUTOFD);
306742ec650SMarko Kohtala port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
307742ec650SMarko Kohtala }
3081da177e4SLinus Torvalds else
309742ec650SMarko Kohtala port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
3101da177e4SLinus Torvalds }
3111da177e4SLinus Torvalds
3121da177e4SLinus Torvalds return count;
3131da177e4SLinus Torvalds #endif /* IEEE1284 support */
3141da177e4SLinus Torvalds }
3151da177e4SLinus Torvalds
3161da177e4SLinus Torvalds /*** *
3171da177e4SLinus Torvalds * ECP Functions. *
3181da177e4SLinus Torvalds * ***/
3191da177e4SLinus Torvalds
3201da177e4SLinus Torvalds #ifdef CONFIG_PARPORT_1284
3211da177e4SLinus Torvalds
3221da177e4SLinus Torvalds static inline
ecp_forward_to_reverse(struct parport * port)3231da177e4SLinus Torvalds int ecp_forward_to_reverse (struct parport *port)
3241da177e4SLinus Torvalds {
3251da177e4SLinus Torvalds int retval;
3261da177e4SLinus Torvalds
3271da177e4SLinus Torvalds /* Event 38: Set nAutoFd low */
3281da177e4SLinus Torvalds parport_frob_control (port,
3291da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD,
3301da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD);
3311da177e4SLinus Torvalds parport_data_reverse (port);
3321da177e4SLinus Torvalds udelay (5);
3331da177e4SLinus Torvalds
3341da177e4SLinus Torvalds /* Event 39: Set nInit low to initiate bus reversal */
3351da177e4SLinus Torvalds parport_frob_control (port,
3361da177e4SLinus Torvalds PARPORT_CONTROL_INIT,
3371da177e4SLinus Torvalds 0);
3381da177e4SLinus Torvalds
3391da177e4SLinus Torvalds /* Event 40: PError goes low */
3401da177e4SLinus Torvalds retval = parport_wait_peripheral (port,
3411da177e4SLinus Torvalds PARPORT_STATUS_PAPEROUT, 0);
3421da177e4SLinus Torvalds
3431da177e4SLinus Torvalds if (!retval) {
344d98ce9feSJoe Perches pr_debug("%s: ECP direction: reverse\n", port->name);
3451da177e4SLinus Torvalds port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
3461da177e4SLinus Torvalds } else {
347d98ce9feSJoe Perches pr_debug("%s: ECP direction: failed to reverse\n", port->name);
3481da177e4SLinus Torvalds port->ieee1284.phase = IEEE1284_PH_ECP_DIR_UNKNOWN;
3491da177e4SLinus Torvalds }
3501da177e4SLinus Torvalds
3511da177e4SLinus Torvalds return retval;
3521da177e4SLinus Torvalds }
3531da177e4SLinus Torvalds
3541da177e4SLinus Torvalds static inline
ecp_reverse_to_forward(struct parport * port)3551da177e4SLinus Torvalds int ecp_reverse_to_forward (struct parport *port)
3561da177e4SLinus Torvalds {
3571da177e4SLinus Torvalds int retval;
3581da177e4SLinus Torvalds
3591da177e4SLinus Torvalds /* Event 47: Set nInit high */
3601da177e4SLinus Torvalds parport_frob_control (port,
3611da177e4SLinus Torvalds PARPORT_CONTROL_INIT
3621da177e4SLinus Torvalds | PARPORT_CONTROL_AUTOFD,
3631da177e4SLinus Torvalds PARPORT_CONTROL_INIT
3641da177e4SLinus Torvalds | PARPORT_CONTROL_AUTOFD);
3651da177e4SLinus Torvalds
3661da177e4SLinus Torvalds /* Event 49: PError goes high */
3671da177e4SLinus Torvalds retval = parport_wait_peripheral (port,
3681da177e4SLinus Torvalds PARPORT_STATUS_PAPEROUT,
3691da177e4SLinus Torvalds PARPORT_STATUS_PAPEROUT);
3701da177e4SLinus Torvalds
3711da177e4SLinus Torvalds if (!retval) {
3721da177e4SLinus Torvalds parport_data_forward (port);
373d98ce9feSJoe Perches pr_debug("%s: ECP direction: forward\n", port->name);
3741da177e4SLinus Torvalds port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
3751da177e4SLinus Torvalds } else {
376d98ce9feSJoe Perches pr_debug("%s: ECP direction: failed to switch forward\n",
3771da177e4SLinus Torvalds port->name);
3781da177e4SLinus Torvalds port->ieee1284.phase = IEEE1284_PH_ECP_DIR_UNKNOWN;
3791da177e4SLinus Torvalds }
3801da177e4SLinus Torvalds
3811da177e4SLinus Torvalds
3821da177e4SLinus Torvalds return retval;
3831da177e4SLinus Torvalds }
3841da177e4SLinus Torvalds
3851da177e4SLinus Torvalds #endif /* IEEE1284 support */
3861da177e4SLinus Torvalds
3871da177e4SLinus Torvalds /* ECP mode, forward channel, data. */
parport_ieee1284_ecp_write_data(struct parport * port,const void * buffer,size_t len,int flags)3881da177e4SLinus Torvalds size_t parport_ieee1284_ecp_write_data (struct parport *port,
3891da177e4SLinus Torvalds const void *buffer, size_t len,
3901da177e4SLinus Torvalds int flags)
3911da177e4SLinus Torvalds {
3921da177e4SLinus Torvalds #ifndef CONFIG_PARPORT_1284
3931da177e4SLinus Torvalds return 0;
3941da177e4SLinus Torvalds #else
3951da177e4SLinus Torvalds const unsigned char *buf = buffer;
3961da177e4SLinus Torvalds size_t written;
3971da177e4SLinus Torvalds int retry;
3981da177e4SLinus Torvalds
3991da177e4SLinus Torvalds port = port->physport;
4001da177e4SLinus Torvalds
4011da177e4SLinus Torvalds if (port->ieee1284.phase != IEEE1284_PH_FWD_IDLE)
4021da177e4SLinus Torvalds if (ecp_reverse_to_forward (port))
4031da177e4SLinus Torvalds return 0;
4041da177e4SLinus Torvalds
4051da177e4SLinus Torvalds port->ieee1284.phase = IEEE1284_PH_FWD_DATA;
4061da177e4SLinus Torvalds
4071da177e4SLinus Torvalds /* HostAck high (data, not command) */
4081da177e4SLinus Torvalds parport_frob_control (port,
4091da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD
4101da177e4SLinus Torvalds | PARPORT_CONTROL_STROBE
4111da177e4SLinus Torvalds | PARPORT_CONTROL_INIT,
4121da177e4SLinus Torvalds PARPORT_CONTROL_INIT);
4131da177e4SLinus Torvalds for (written = 0; written < len; written++, buf++) {
4141da177e4SLinus Torvalds unsigned long expire = jiffies + port->cad->timeout;
4151da177e4SLinus Torvalds unsigned char byte;
4161da177e4SLinus Torvalds
4171da177e4SLinus Torvalds byte = *buf;
4181da177e4SLinus Torvalds try_again:
4191da177e4SLinus Torvalds parport_write_data (port, byte);
4201da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_STROBE,
4211da177e4SLinus Torvalds PARPORT_CONTROL_STROBE);
4221da177e4SLinus Torvalds udelay (5);
4231da177e4SLinus Torvalds for (retry = 0; retry < 100; retry++) {
4241da177e4SLinus Torvalds if (!parport_wait_peripheral (port,
4251da177e4SLinus Torvalds PARPORT_STATUS_BUSY, 0))
4261da177e4SLinus Torvalds goto success;
4271da177e4SLinus Torvalds
4281da177e4SLinus Torvalds if (signal_pending (current)) {
4291da177e4SLinus Torvalds parport_frob_control (port,
4301da177e4SLinus Torvalds PARPORT_CONTROL_STROBE,
4311da177e4SLinus Torvalds 0);
4321da177e4SLinus Torvalds break;
4331da177e4SLinus Torvalds }
4341da177e4SLinus Torvalds }
4351da177e4SLinus Torvalds
4361da177e4SLinus Torvalds /* Time for Host Transfer Recovery (page 41 of IEEE1284) */
437d98ce9feSJoe Perches pr_debug("%s: ECP transfer stalled!\n", port->name);
4381da177e4SLinus Torvalds
4391da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_INIT,
4401da177e4SLinus Torvalds PARPORT_CONTROL_INIT);
4411da177e4SLinus Torvalds udelay (50);
4421da177e4SLinus Torvalds if (parport_read_status (port) & PARPORT_STATUS_PAPEROUT) {
4431da177e4SLinus Torvalds /* It's buggered. */
4441da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
4451da177e4SLinus Torvalds break;
4461da177e4SLinus Torvalds }
4471da177e4SLinus Torvalds
4481da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
4491da177e4SLinus Torvalds udelay (50);
4501da177e4SLinus Torvalds if (!(parport_read_status (port) & PARPORT_STATUS_PAPEROUT))
4511da177e4SLinus Torvalds break;
4521da177e4SLinus Torvalds
453d98ce9feSJoe Perches pr_debug("%s: Host transfer recovered\n", port->name);
4541da177e4SLinus Torvalds
4551da177e4SLinus Torvalds if (time_after_eq (jiffies, expire)) break;
4561da177e4SLinus Torvalds goto try_again;
4571da177e4SLinus Torvalds success:
4581da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
4591da177e4SLinus Torvalds udelay (5);
4601da177e4SLinus Torvalds if (parport_wait_peripheral (port,
4611da177e4SLinus Torvalds PARPORT_STATUS_BUSY,
4621da177e4SLinus Torvalds PARPORT_STATUS_BUSY))
4631da177e4SLinus Torvalds /* Peripheral hasn't accepted the data. */
4641da177e4SLinus Torvalds break;
4651da177e4SLinus Torvalds }
4661da177e4SLinus Torvalds
4671da177e4SLinus Torvalds port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
4681da177e4SLinus Torvalds
4691da177e4SLinus Torvalds return written;
4701da177e4SLinus Torvalds #endif /* IEEE1284 support */
4711da177e4SLinus Torvalds }
4721da177e4SLinus Torvalds
4731da177e4SLinus Torvalds /* ECP mode, reverse channel, data. */
parport_ieee1284_ecp_read_data(struct parport * port,void * buffer,size_t len,int flags)4741da177e4SLinus Torvalds size_t parport_ieee1284_ecp_read_data (struct parport *port,
4751da177e4SLinus Torvalds void *buffer, size_t len, int flags)
4761da177e4SLinus Torvalds {
4771da177e4SLinus Torvalds #ifndef CONFIG_PARPORT_1284
4781da177e4SLinus Torvalds return 0;
4791da177e4SLinus Torvalds #else
4801da177e4SLinus Torvalds struct pardevice *dev = port->cad;
4811da177e4SLinus Torvalds unsigned char *buf = buffer;
4821da177e4SLinus Torvalds int rle_count = 0; /* shut gcc up */
4831da177e4SLinus Torvalds unsigned char ctl;
4841da177e4SLinus Torvalds int rle = 0;
4851da177e4SLinus Torvalds ssize_t count = 0;
4861da177e4SLinus Torvalds
4871da177e4SLinus Torvalds port = port->physport;
4881da177e4SLinus Torvalds
4891da177e4SLinus Torvalds if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE)
4901da177e4SLinus Torvalds if (ecp_forward_to_reverse (port))
4911da177e4SLinus Torvalds return 0;
4921da177e4SLinus Torvalds
4931da177e4SLinus Torvalds port->ieee1284.phase = IEEE1284_PH_REV_DATA;
4941da177e4SLinus Torvalds
4951da177e4SLinus Torvalds /* Set HostAck low to start accepting data. */
4961da177e4SLinus Torvalds ctl = parport_read_control (port);
4971da177e4SLinus Torvalds ctl &= ~(PARPORT_CONTROL_STROBE | PARPORT_CONTROL_INIT |
4981da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD);
4991da177e4SLinus Torvalds parport_write_control (port,
5001da177e4SLinus Torvalds ctl | PARPORT_CONTROL_AUTOFD);
5011da177e4SLinus Torvalds while (count < len) {
5021da177e4SLinus Torvalds unsigned long expire = jiffies + dev->timeout;
5031da177e4SLinus Torvalds unsigned char byte;
5041da177e4SLinus Torvalds int command;
5051da177e4SLinus Torvalds
5061da177e4SLinus Torvalds /* Event 43: Peripheral sets nAck low. It can take as
5071da177e4SLinus Torvalds long as it wants. */
5081da177e4SLinus Torvalds while (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) {
5091da177e4SLinus Torvalds /* The peripheral hasn't given us data in
5101da177e4SLinus Torvalds 35ms. If we have data to give back to the
5111da177e4SLinus Torvalds caller, do it now. */
5121da177e4SLinus Torvalds if (count)
5131da177e4SLinus Torvalds goto out;
5141da177e4SLinus Torvalds
5151da177e4SLinus Torvalds /* If we've used up all the time we were allowed,
5161da177e4SLinus Torvalds give up altogether. */
5171da177e4SLinus Torvalds if (!time_before (jiffies, expire))
5181da177e4SLinus Torvalds goto out;
5191da177e4SLinus Torvalds
5201da177e4SLinus Torvalds /* Yield the port for a while. */
521*0be883a0SColin Ian King if (dev->port->irq != PARPORT_IRQ_NONE) {
5221da177e4SLinus Torvalds parport_release (dev);
5237b4ccf8dSNishanth Aravamudan schedule_timeout_interruptible(msecs_to_jiffies(40));
5241da177e4SLinus Torvalds parport_claim_or_block (dev);
5251da177e4SLinus Torvalds }
5261da177e4SLinus Torvalds else
5271da177e4SLinus Torvalds /* We must have the device claimed here. */
5287b4ccf8dSNishanth Aravamudan parport_wait_event (port, msecs_to_jiffies(40));
5291da177e4SLinus Torvalds
5301da177e4SLinus Torvalds /* Is there a signal pending? */
5311da177e4SLinus Torvalds if (signal_pending (current))
5321da177e4SLinus Torvalds goto out;
5331da177e4SLinus Torvalds }
5341da177e4SLinus Torvalds
5351da177e4SLinus Torvalds /* Is this a command? */
5361da177e4SLinus Torvalds if (rle)
5371da177e4SLinus Torvalds /* The last byte was a run-length count, so
5381da177e4SLinus Torvalds this can't be as well. */
5391da177e4SLinus Torvalds command = 0;
5401da177e4SLinus Torvalds else
5411da177e4SLinus Torvalds command = (parport_read_status (port) &
5421da177e4SLinus Torvalds PARPORT_STATUS_BUSY) ? 1 : 0;
5431da177e4SLinus Torvalds
5441da177e4SLinus Torvalds /* Read the data. */
5451da177e4SLinus Torvalds byte = parport_read_data (port);
5461da177e4SLinus Torvalds
5471da177e4SLinus Torvalds /* If this is a channel command, rather than an RLE
5481da177e4SLinus Torvalds command or a normal data byte, don't accept it. */
5491da177e4SLinus Torvalds if (command) {
5501da177e4SLinus Torvalds if (byte & 0x80) {
551d98ce9feSJoe Perches pr_debug("%s: stopping short at channel command (%02x)\n",
5521da177e4SLinus Torvalds port->name, byte);
5531da177e4SLinus Torvalds goto out;
5541da177e4SLinus Torvalds }
5551da177e4SLinus Torvalds else if (port->ieee1284.mode != IEEE1284_MODE_ECPRLE)
556d98ce9feSJoe Perches pr_debug("%s: device illegally using RLE; accepting anyway\n",
5571da177e4SLinus Torvalds port->name);
5581da177e4SLinus Torvalds
5591da177e4SLinus Torvalds rle_count = byte + 1;
5601da177e4SLinus Torvalds
5611da177e4SLinus Torvalds /* Are we allowed to read that many bytes? */
5621da177e4SLinus Torvalds if (rle_count > (len - count)) {
563d98ce9feSJoe Perches pr_debug("%s: leaving %d RLE bytes for next time\n",
564d98ce9feSJoe Perches port->name, rle_count);
5651da177e4SLinus Torvalds break;
5661da177e4SLinus Torvalds }
5671da177e4SLinus Torvalds
5681da177e4SLinus Torvalds rle = 1;
5691da177e4SLinus Torvalds }
5701da177e4SLinus Torvalds
5711da177e4SLinus Torvalds /* Event 44: Set HostAck high, acknowledging handshake. */
5721da177e4SLinus Torvalds parport_write_control (port, ctl);
5731da177e4SLinus Torvalds
5741da177e4SLinus Torvalds /* Event 45: The peripheral has 35ms to set nAck high. */
5751da177e4SLinus Torvalds if (parport_wait_peripheral (port, PARPORT_STATUS_ACK,
5761da177e4SLinus Torvalds PARPORT_STATUS_ACK)) {
5771da177e4SLinus Torvalds /* It's gone wrong. Return what data we have
5781da177e4SLinus Torvalds to the caller. */
579d98ce9feSJoe Perches pr_debug("ECP read timed out at 45\n");
5801da177e4SLinus Torvalds
5811da177e4SLinus Torvalds if (command)
582decf26f6SJoe Perches pr_warn("%s: command ignored (%02x)\n",
5831da177e4SLinus Torvalds port->name, byte);
5841da177e4SLinus Torvalds
5851da177e4SLinus Torvalds break;
5861da177e4SLinus Torvalds }
5871da177e4SLinus Torvalds
5881da177e4SLinus Torvalds /* Event 46: Set HostAck low and accept the data. */
5891da177e4SLinus Torvalds parport_write_control (port,
5901da177e4SLinus Torvalds ctl | PARPORT_CONTROL_AUTOFD);
5911da177e4SLinus Torvalds
5921da177e4SLinus Torvalds /* If we just read a run-length count, fetch the data. */
5931da177e4SLinus Torvalds if (command)
5941da177e4SLinus Torvalds continue;
5951da177e4SLinus Torvalds
5961da177e4SLinus Torvalds /* If this is the byte after a run-length count, decompress. */
5971da177e4SLinus Torvalds if (rle) {
5981da177e4SLinus Torvalds rle = 0;
5991da177e4SLinus Torvalds memset (buf, byte, rle_count);
6001da177e4SLinus Torvalds buf += rle_count;
6011da177e4SLinus Torvalds count += rle_count;
602d98ce9feSJoe Perches pr_debug("%s: decompressed to %d bytes\n",
6031da177e4SLinus Torvalds port->name, rle_count);
6041da177e4SLinus Torvalds } else {
6051da177e4SLinus Torvalds /* Normal data byte. */
6061da177e4SLinus Torvalds *buf = byte;
6071da177e4SLinus Torvalds buf++, count++;
6081da177e4SLinus Torvalds }
6091da177e4SLinus Torvalds }
6101da177e4SLinus Torvalds
6111da177e4SLinus Torvalds out:
6121da177e4SLinus Torvalds port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
6131da177e4SLinus Torvalds return count;
6141da177e4SLinus Torvalds #endif /* IEEE1284 support */
6151da177e4SLinus Torvalds }
6161da177e4SLinus Torvalds
6171da177e4SLinus Torvalds /* ECP mode, forward channel, commands. */
parport_ieee1284_ecp_write_addr(struct parport * port,const void * buffer,size_t len,int flags)6181da177e4SLinus Torvalds size_t parport_ieee1284_ecp_write_addr (struct parport *port,
6191da177e4SLinus Torvalds const void *buffer, size_t len,
6201da177e4SLinus Torvalds int flags)
6211da177e4SLinus Torvalds {
6221da177e4SLinus Torvalds #ifndef CONFIG_PARPORT_1284
6231da177e4SLinus Torvalds return 0;
6241da177e4SLinus Torvalds #else
6251da177e4SLinus Torvalds const unsigned char *buf = buffer;
6261da177e4SLinus Torvalds size_t written;
6271da177e4SLinus Torvalds int retry;
6281da177e4SLinus Torvalds
6291da177e4SLinus Torvalds port = port->physport;
6301da177e4SLinus Torvalds
6311da177e4SLinus Torvalds if (port->ieee1284.phase != IEEE1284_PH_FWD_IDLE)
6321da177e4SLinus Torvalds if (ecp_reverse_to_forward (port))
6331da177e4SLinus Torvalds return 0;
6341da177e4SLinus Torvalds
6351da177e4SLinus Torvalds port->ieee1284.phase = IEEE1284_PH_FWD_DATA;
6361da177e4SLinus Torvalds
6371da177e4SLinus Torvalds /* HostAck low (command, not data) */
6381da177e4SLinus Torvalds parport_frob_control (port,
6391da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD
6401da177e4SLinus Torvalds | PARPORT_CONTROL_STROBE
6411da177e4SLinus Torvalds | PARPORT_CONTROL_INIT,
6421da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD
6431da177e4SLinus Torvalds | PARPORT_CONTROL_INIT);
6441da177e4SLinus Torvalds for (written = 0; written < len; written++, buf++) {
6451da177e4SLinus Torvalds unsigned long expire = jiffies + port->cad->timeout;
6461da177e4SLinus Torvalds unsigned char byte;
6471da177e4SLinus Torvalds
6481da177e4SLinus Torvalds byte = *buf;
6491da177e4SLinus Torvalds try_again:
6501da177e4SLinus Torvalds parport_write_data (port, byte);
6511da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_STROBE,
6521da177e4SLinus Torvalds PARPORT_CONTROL_STROBE);
6531da177e4SLinus Torvalds udelay (5);
6541da177e4SLinus Torvalds for (retry = 0; retry < 100; retry++) {
6551da177e4SLinus Torvalds if (!parport_wait_peripheral (port,
6561da177e4SLinus Torvalds PARPORT_STATUS_BUSY, 0))
6571da177e4SLinus Torvalds goto success;
6581da177e4SLinus Torvalds
6591da177e4SLinus Torvalds if (signal_pending (current)) {
6601da177e4SLinus Torvalds parport_frob_control (port,
6611da177e4SLinus Torvalds PARPORT_CONTROL_STROBE,
6621da177e4SLinus Torvalds 0);
6631da177e4SLinus Torvalds break;
6641da177e4SLinus Torvalds }
6651da177e4SLinus Torvalds }
6661da177e4SLinus Torvalds
6671da177e4SLinus Torvalds /* Time for Host Transfer Recovery (page 41 of IEEE1284) */
668d98ce9feSJoe Perches pr_debug("%s: ECP transfer stalled!\n", port->name);
6691da177e4SLinus Torvalds
6701da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_INIT,
6711da177e4SLinus Torvalds PARPORT_CONTROL_INIT);
6721da177e4SLinus Torvalds udelay (50);
6731da177e4SLinus Torvalds if (parport_read_status (port) & PARPORT_STATUS_PAPEROUT) {
6741da177e4SLinus Torvalds /* It's buggered. */
6751da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
6761da177e4SLinus Torvalds break;
6771da177e4SLinus Torvalds }
6781da177e4SLinus Torvalds
6791da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
6801da177e4SLinus Torvalds udelay (50);
6811da177e4SLinus Torvalds if (!(parport_read_status (port) & PARPORT_STATUS_PAPEROUT))
6821da177e4SLinus Torvalds break;
6831da177e4SLinus Torvalds
684d98ce9feSJoe Perches pr_debug("%s: Host transfer recovered\n", port->name);
6851da177e4SLinus Torvalds
6861da177e4SLinus Torvalds if (time_after_eq (jiffies, expire)) break;
6871da177e4SLinus Torvalds goto try_again;
6881da177e4SLinus Torvalds success:
6891da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
6901da177e4SLinus Torvalds udelay (5);
6911da177e4SLinus Torvalds if (parport_wait_peripheral (port,
6921da177e4SLinus Torvalds PARPORT_STATUS_BUSY,
6931da177e4SLinus Torvalds PARPORT_STATUS_BUSY))
6941da177e4SLinus Torvalds /* Peripheral hasn't accepted the data. */
6951da177e4SLinus Torvalds break;
6961da177e4SLinus Torvalds }
6971da177e4SLinus Torvalds
6981da177e4SLinus Torvalds port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
6991da177e4SLinus Torvalds
7001da177e4SLinus Torvalds return written;
7011da177e4SLinus Torvalds #endif /* IEEE1284 support */
7021da177e4SLinus Torvalds }
7031da177e4SLinus Torvalds
7041da177e4SLinus Torvalds /*** *
7051da177e4SLinus Torvalds * EPP functions. *
7061da177e4SLinus Torvalds * ***/
7071da177e4SLinus Torvalds
7081da177e4SLinus Torvalds /* EPP mode, forward channel, data. */
parport_ieee1284_epp_write_data(struct parport * port,const void * buffer,size_t len,int flags)7091da177e4SLinus Torvalds size_t parport_ieee1284_epp_write_data (struct parport *port,
7101da177e4SLinus Torvalds const void *buffer, size_t len,
7111da177e4SLinus Torvalds int flags)
7121da177e4SLinus Torvalds {
7131da177e4SLinus Torvalds unsigned char *bp = (unsigned char *) buffer;
7141da177e4SLinus Torvalds size_t ret = 0;
7151da177e4SLinus Torvalds
7161da177e4SLinus Torvalds /* set EPP idle state (just to make sure) with strobe low */
7171da177e4SLinus Torvalds parport_frob_control (port,
7181da177e4SLinus Torvalds PARPORT_CONTROL_STROBE |
7191da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD |
7201da177e4SLinus Torvalds PARPORT_CONTROL_SELECT |
7211da177e4SLinus Torvalds PARPORT_CONTROL_INIT,
7221da177e4SLinus Torvalds PARPORT_CONTROL_STROBE |
7231da177e4SLinus Torvalds PARPORT_CONTROL_INIT);
7241da177e4SLinus Torvalds port->ops->data_forward (port);
7251da177e4SLinus Torvalds for (; len > 0; len--, bp++) {
7261da177e4SLinus Torvalds /* Event 62: Write data and set autofd low */
7271da177e4SLinus Torvalds parport_write_data (port, *bp);
7281da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
7291da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD);
7301da177e4SLinus Torvalds
7311da177e4SLinus Torvalds /* Event 58: wait for busy (nWait) to go high */
7321da177e4SLinus Torvalds if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 10))
7331da177e4SLinus Torvalds break;
7341da177e4SLinus Torvalds
7351da177e4SLinus Torvalds /* Event 63: set nAutoFd (nDStrb) high */
7361da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
7371da177e4SLinus Torvalds
7381da177e4SLinus Torvalds /* Event 60: wait for busy (nWait) to go low */
7391da177e4SLinus Torvalds if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
7401da177e4SLinus Torvalds PARPORT_STATUS_BUSY, 5))
7411da177e4SLinus Torvalds break;
7421da177e4SLinus Torvalds
7431da177e4SLinus Torvalds ret++;
7441da177e4SLinus Torvalds }
7451da177e4SLinus Torvalds
7461da177e4SLinus Torvalds /* Event 61: set strobe (nWrite) high */
7471da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
7481da177e4SLinus Torvalds
7491da177e4SLinus Torvalds return ret;
7501da177e4SLinus Torvalds }
7511da177e4SLinus Torvalds
7521da177e4SLinus Torvalds /* EPP mode, reverse channel, data. */
parport_ieee1284_epp_read_data(struct parport * port,void * buffer,size_t len,int flags)7531da177e4SLinus Torvalds size_t parport_ieee1284_epp_read_data (struct parport *port,
7541da177e4SLinus Torvalds void *buffer, size_t len,
7551da177e4SLinus Torvalds int flags)
7561da177e4SLinus Torvalds {
7571da177e4SLinus Torvalds unsigned char *bp = (unsigned char *) buffer;
7581da177e4SLinus Torvalds unsigned ret = 0;
7591da177e4SLinus Torvalds
7601da177e4SLinus Torvalds /* set EPP idle state (just to make sure) with strobe high */
7611da177e4SLinus Torvalds parport_frob_control (port,
7621da177e4SLinus Torvalds PARPORT_CONTROL_STROBE |
7631da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD |
7641da177e4SLinus Torvalds PARPORT_CONTROL_SELECT |
7651da177e4SLinus Torvalds PARPORT_CONTROL_INIT,
7661da177e4SLinus Torvalds PARPORT_CONTROL_INIT);
7671da177e4SLinus Torvalds port->ops->data_reverse (port);
7681da177e4SLinus Torvalds for (; len > 0; len--, bp++) {
7691da177e4SLinus Torvalds /* Event 67: set nAutoFd (nDStrb) low */
7701da177e4SLinus Torvalds parport_frob_control (port,
7711da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD,
7721da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD);
7731da177e4SLinus Torvalds /* Event 58: wait for Busy to go high */
7741da177e4SLinus Torvalds if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0)) {
7751da177e4SLinus Torvalds break;
7761da177e4SLinus Torvalds }
7771da177e4SLinus Torvalds
7781da177e4SLinus Torvalds *bp = parport_read_data (port);
7791da177e4SLinus Torvalds
7801da177e4SLinus Torvalds /* Event 63: set nAutoFd (nDStrb) high */
7811da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
7821da177e4SLinus Torvalds
7831da177e4SLinus Torvalds /* Event 60: wait for Busy to go low */
7841da177e4SLinus Torvalds if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
7851da177e4SLinus Torvalds PARPORT_STATUS_BUSY, 5)) {
7861da177e4SLinus Torvalds break;
7871da177e4SLinus Torvalds }
7881da177e4SLinus Torvalds
7891da177e4SLinus Torvalds ret++;
7901da177e4SLinus Torvalds }
7911da177e4SLinus Torvalds port->ops->data_forward (port);
7921da177e4SLinus Torvalds
7931da177e4SLinus Torvalds return ret;
7941da177e4SLinus Torvalds }
7951da177e4SLinus Torvalds
7961da177e4SLinus Torvalds /* EPP mode, forward channel, addresses. */
parport_ieee1284_epp_write_addr(struct parport * port,const void * buffer,size_t len,int flags)7971da177e4SLinus Torvalds size_t parport_ieee1284_epp_write_addr (struct parport *port,
7981da177e4SLinus Torvalds const void *buffer, size_t len,
7991da177e4SLinus Torvalds int flags)
8001da177e4SLinus Torvalds {
8011da177e4SLinus Torvalds unsigned char *bp = (unsigned char *) buffer;
8021da177e4SLinus Torvalds size_t ret = 0;
8031da177e4SLinus Torvalds
8041da177e4SLinus Torvalds /* set EPP idle state (just to make sure) with strobe low */
8051da177e4SLinus Torvalds parport_frob_control (port,
8061da177e4SLinus Torvalds PARPORT_CONTROL_STROBE |
8071da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD |
8081da177e4SLinus Torvalds PARPORT_CONTROL_SELECT |
8091da177e4SLinus Torvalds PARPORT_CONTROL_INIT,
8101da177e4SLinus Torvalds PARPORT_CONTROL_STROBE |
8111da177e4SLinus Torvalds PARPORT_CONTROL_INIT);
8121da177e4SLinus Torvalds port->ops->data_forward (port);
8131da177e4SLinus Torvalds for (; len > 0; len--, bp++) {
8141da177e4SLinus Torvalds /* Event 56: Write data and set nAStrb low. */
8151da177e4SLinus Torvalds parport_write_data (port, *bp);
8161da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_SELECT,
8171da177e4SLinus Torvalds PARPORT_CONTROL_SELECT);
8181da177e4SLinus Torvalds
8191da177e4SLinus Torvalds /* Event 58: wait for busy (nWait) to go high */
8201da177e4SLinus Torvalds if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 10))
8211da177e4SLinus Torvalds break;
8221da177e4SLinus Torvalds
8231da177e4SLinus Torvalds /* Event 59: set nAStrb high */
8241da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
8251da177e4SLinus Torvalds
8261da177e4SLinus Torvalds /* Event 60: wait for busy (nWait) to go low */
8271da177e4SLinus Torvalds if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
8281da177e4SLinus Torvalds PARPORT_STATUS_BUSY, 5))
8291da177e4SLinus Torvalds break;
8301da177e4SLinus Torvalds
8311da177e4SLinus Torvalds ret++;
8321da177e4SLinus Torvalds }
8331da177e4SLinus Torvalds
8341da177e4SLinus Torvalds /* Event 61: set strobe (nWrite) high */
8351da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
8361da177e4SLinus Torvalds
8371da177e4SLinus Torvalds return ret;
8381da177e4SLinus Torvalds }
8391da177e4SLinus Torvalds
8401da177e4SLinus Torvalds /* EPP mode, reverse channel, addresses. */
parport_ieee1284_epp_read_addr(struct parport * port,void * buffer,size_t len,int flags)8411da177e4SLinus Torvalds size_t parport_ieee1284_epp_read_addr (struct parport *port,
8421da177e4SLinus Torvalds void *buffer, size_t len,
8431da177e4SLinus Torvalds int flags)
8441da177e4SLinus Torvalds {
8451da177e4SLinus Torvalds unsigned char *bp = (unsigned char *) buffer;
8461da177e4SLinus Torvalds unsigned ret = 0;
8471da177e4SLinus Torvalds
8481da177e4SLinus Torvalds /* Set EPP idle state (just to make sure) with strobe high */
8491da177e4SLinus Torvalds parport_frob_control (port,
8501da177e4SLinus Torvalds PARPORT_CONTROL_STROBE |
8511da177e4SLinus Torvalds PARPORT_CONTROL_AUTOFD |
8521da177e4SLinus Torvalds PARPORT_CONTROL_SELECT |
8531da177e4SLinus Torvalds PARPORT_CONTROL_INIT,
8541da177e4SLinus Torvalds PARPORT_CONTROL_INIT);
8551da177e4SLinus Torvalds port->ops->data_reverse (port);
8561da177e4SLinus Torvalds for (; len > 0; len--, bp++) {
8571da177e4SLinus Torvalds /* Event 64: set nSelectIn (nAStrb) low */
8581da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_SELECT,
8591da177e4SLinus Torvalds PARPORT_CONTROL_SELECT);
8601da177e4SLinus Torvalds
8611da177e4SLinus Torvalds /* Event 58: wait for Busy to go high */
8621da177e4SLinus Torvalds if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0)) {
8631da177e4SLinus Torvalds break;
8641da177e4SLinus Torvalds }
8651da177e4SLinus Torvalds
8661da177e4SLinus Torvalds *bp = parport_read_data (port);
8671da177e4SLinus Torvalds
8681da177e4SLinus Torvalds /* Event 59: set nSelectIn (nAStrb) high */
8691da177e4SLinus Torvalds parport_frob_control (port, PARPORT_CONTROL_SELECT,
87013050d89SStephan Boettcher 0);
8711da177e4SLinus Torvalds
8721da177e4SLinus Torvalds /* Event 60: wait for Busy to go low */
8731da177e4SLinus Torvalds if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
8741da177e4SLinus Torvalds PARPORT_STATUS_BUSY, 5))
8751da177e4SLinus Torvalds break;
8761da177e4SLinus Torvalds
8771da177e4SLinus Torvalds ret++;
8781da177e4SLinus Torvalds }
8791da177e4SLinus Torvalds port->ops->data_forward (port);
8801da177e4SLinus Torvalds
8811da177e4SLinus Torvalds return ret;
8821da177e4SLinus Torvalds }
8831da177e4SLinus Torvalds
8841da177e4SLinus Torvalds EXPORT_SYMBOL(parport_ieee1284_ecp_write_data);
8851da177e4SLinus Torvalds EXPORT_SYMBOL(parport_ieee1284_ecp_read_data);
8861da177e4SLinus Torvalds EXPORT_SYMBOL(parport_ieee1284_ecp_write_addr);
8871da177e4SLinus Torvalds EXPORT_SYMBOL(parport_ieee1284_write_compat);
8881da177e4SLinus Torvalds EXPORT_SYMBOL(parport_ieee1284_read_nibble);
8891da177e4SLinus Torvalds EXPORT_SYMBOL(parport_ieee1284_read_byte);
8901da177e4SLinus Torvalds EXPORT_SYMBOL(parport_ieee1284_epp_write_data);
8911da177e4SLinus Torvalds EXPORT_SYMBOL(parport_ieee1284_epp_read_data);
8921da177e4SLinus Torvalds EXPORT_SYMBOL(parport_ieee1284_epp_write_addr);
8931da177e4SLinus Torvalds EXPORT_SYMBOL(parport_ieee1284_epp_read_addr);
894