|
Packit |
d36e9b |
/*
|
|
Packit |
d36e9b |
* libieee1284 - IEEE 1284 library
|
|
Packit |
d36e9b |
* Copyright (C) 2000-2001 Hewlett-Packard Company
|
|
Packit |
d36e9b |
* Integrated into libieee1284:
|
|
Packit |
d36e9b |
* Copyright (C) 2001-2003 Tim Waugh <twaugh@redhat.com>
|
|
Packit |
d36e9b |
*
|
|
Packit |
d36e9b |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
d36e9b |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
d36e9b |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
d36e9b |
* (at your option) any later version.
|
|
Packit |
d36e9b |
*
|
|
Packit |
d36e9b |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
d36e9b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
d36e9b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
d36e9b |
* GNU General Public License for more details.
|
|
Packit |
d36e9b |
*
|
|
Packit |
d36e9b |
* You should have received a copy of the GNU General Public License
|
|
Packit |
d36e9b |
* along with this program; if not, write to the Free Software
|
|
Packit |
d36e9b |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
d36e9b |
*/
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#include <string.h>
|
|
Packit |
d36e9b |
#ifndef _MSC_VER
|
|
Packit |
d36e9b |
#include <sys/time.h>
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
#include <sys/types.h>
|
|
Packit |
d36e9b |
#ifdef __unix__
|
|
Packit |
d36e9b |
#include <unistd.h>
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
#if defined __MINGW32__ || defined _MSC_VER
|
|
Packit |
d36e9b |
#include <sys/timeb.h>
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#include "access.h"
|
|
Packit |
d36e9b |
#include "debug.h"
|
|
Packit |
d36e9b |
#include "delay.h"
|
|
Packit |
d36e9b |
#include "detect.h"
|
|
Packit |
d36e9b |
#include "ieee1284.h"
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static const char *no_default = "no default implementation of %s\n";
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
int
|
|
Packit |
d36e9b |
default_wait_data (struct parport_internal *port, unsigned char mask,
|
|
Packit |
d36e9b |
unsigned char val, struct timeval *timeout)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
/* Simple-minded polling. TODO: Use David Paschal's method for this. */
|
|
Packit |
d36e9b |
#if !(defined __MINGW32__ || defined _MSC_VER)
|
|
Packit |
d36e9b |
struct timeval deadline, now;
|
|
Packit |
d36e9b |
gettimeofday (&deadline, NULL);
|
|
Packit |
d36e9b |
deadline.tv_sec += timeout->tv_sec;
|
|
Packit |
d36e9b |
deadline.tv_usec += timeout->tv_usec;
|
|
Packit |
d36e9b |
deadline.tv_sec += deadline.tv_usec / 1000000;
|
|
Packit |
d36e9b |
deadline.tv_usec %= 1000000;
|
|
Packit |
d36e9b |
#else
|
|
Packit |
d36e9b |
struct timeb tb;
|
|
Packit |
d36e9b |
int deadline, now;
|
|
Packit |
d36e9b |
ftime (&tb);
|
|
Packit |
d36e9b |
deadline = tb.time * 1000 + tb.millitm +
|
|
Packit |
d36e9b |
timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
do
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
if ((port->fn->read_data (port) & mask) == val)
|
|
Packit |
d36e9b |
return E1284_OK;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
delay (IO_POLL_DELAY);
|
|
Packit |
d36e9b |
#if !(defined __MINGW32__ || defined _MSC_VER)
|
|
Packit |
d36e9b |
gettimeofday (&now, NULL);
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
while (now.tv_sec < deadline.tv_sec ||
|
|
Packit |
d36e9b |
(now.tv_sec == deadline.tv_sec &&
|
|
Packit |
d36e9b |
now.tv_usec < deadline.tv_usec));
|
|
Packit |
d36e9b |
#else
|
|
Packit |
d36e9b |
ftime (&tb);
|
|
Packit |
d36e9b |
now = tb.time * 1000 + tb.millitm;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
while (now < deadline);
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
return E1284_TIMEDOUT;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
int
|
|
Packit |
d36e9b |
default_do_nack_handshake (struct parport_internal *port,
|
|
Packit |
d36e9b |
unsigned char ct_before,
|
|
Packit |
d36e9b |
unsigned char ct_after,
|
|
Packit |
d36e9b |
struct timeval *timeout)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
/* There is a possible implementation using /proc/interrupts on Linux.. */
|
|
Packit |
d36e9b |
debugprintf (no_default, "no_nack_handshake");
|
|
Packit |
d36e9b |
return E1284_NOTIMPL;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
int
|
|
Packit |
d36e9b |
default_negotiate (struct parport_internal *port, int mode)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
int ret = E1284_NEGFAILED;
|
|
Packit |
d36e9b |
struct timeval tv;
|
|
Packit |
d36e9b |
int m = mode;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("==> default_negotiate (to %#02x)\n", mode);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (mode == port->current_mode)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
debugprintf ("<== E1284_OK (nothing to do!)\n");
|
|
Packit |
d36e9b |
return E1284_OK;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (mode == M1284_COMPAT)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
ret = E1284_OK;
|
|
Packit |
d36e9b |
goto abort;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
switch (mode)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
case M1284_ECPSWE:
|
|
Packit |
d36e9b |
m = M1284_ECP;
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
case M1284_EPPSL:
|
|
Packit |
d36e9b |
case M1284_EPPSWE:
|
|
Packit |
d36e9b |
m = M1284_EPP;
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
case M1284_BECP:
|
|
Packit |
d36e9b |
m = 0x18;
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (mode & M1284_FLAG_EXT_LINK)
|
|
Packit |
d36e9b |
m = 1<<7; /* Request extensibility link */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 0: Write extensibility request to data lines. */
|
|
Packit |
d36e9b |
fn->write_data (port, (unsigned char)m);
|
|
Packit |
d36e9b |
debugprintf ("IEEE 1284 mode %#02x\n", m);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 1: nSelectIn=1, nAutoFd=0, nStrobe=1, nInit=1. */
|
|
Packit |
d36e9b |
fn->frob_control (port,
|
|
Packit |
d36e9b |
C1284_NSELECTIN|C1284_NSTROBE|C1284_NINIT
|
|
Packit |
d36e9b |
|C1284_NAUTOFD,
|
|
Packit |
d36e9b |
C1284_NSELECTIN|C1284_NSTROBE|C1284_NINIT);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 2: PError=1, Select=1, nFault=1, nAck=0. */
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port,
|
|
Packit |
d36e9b |
S1284_PERROR|S1284_SELECT|S1284_NFAULT
|
|
Packit |
d36e9b |
|S1284_NACK,
|
|
Packit |
d36e9b |
S1284_PERROR|S1284_SELECT|S1284_NFAULT, &tv))
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
debugprintf ("Failed at event 2\n");
|
|
Packit |
d36e9b |
goto abort;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 3: nStrobe=0. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NSTROBE, 0);
|
|
Packit |
d36e9b |
delay (TIMEVAL_STROBE_DELAY);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 4: nStrobe=1, nAutoFd=1. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NSTROBE|C1284_NAUTOFD,
|
|
Packit |
d36e9b |
C1284_NSTROBE|C1284_NAUTOFD);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 6: nAck=1. */
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_NACK, S1284_NACK, &tv))
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
debugprintf ("Failed at event 6\n");
|
|
Packit |
d36e9b |
goto abort;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 5: Select=0 for nibble-0, =1 for other modes. */
|
|
Packit |
d36e9b |
port->current_mode = !mode;
|
|
Packit |
d36e9b |
if ((fn->read_status (port) & S1284_SELECT) !=
|
|
Packit |
d36e9b |
(mode ? S1284_SELECT : 0))
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
ret = E1284_REJECTED;
|
|
Packit |
d36e9b |
debugprintf ("Mode rejected\n");
|
|
Packit |
d36e9b |
goto abort;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
port->current_mode = mode;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Extra signalling for ECP mode. */
|
|
Packit |
d36e9b |
if (m & M1284_ECP)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
/* Event 30: nAutoFd=0. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, 0);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 31: PError=1. */
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_PERROR, S1284_PERROR, &tv))
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
debugprintf ("Failed at event 31\n");
|
|
Packit |
d36e9b |
goto abort;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
port->current_channel=0;
|
|
Packit |
d36e9b |
port->current_phase = PH1284_FWD_IDLE;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("<== E1284_OK\n");
|
|
Packit |
d36e9b |
return E1284_OK;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
abort:
|
|
Packit |
d36e9b |
fn->terminate(port);
|
|
Packit |
d36e9b |
debugprintf ("<== %d\n", ret);
|
|
Packit |
d36e9b |
return ret;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
void
|
|
Packit |
d36e9b |
default_terminate (struct parport_internal *port)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
struct timeval tv;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Termination may only be accomplished from the forward phase */
|
|
Packit |
d36e9b |
if (port->current_phase == PH1284_REV_IDLE)
|
|
Packit |
d36e9b |
/* even if this fails we're trucking on */
|
|
Packit |
d36e9b |
fn->ecp_rev_to_fwd(port);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->write_control (port, C1284_NINIT | C1284_NAUTOFD | C1284_NSTROBE);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Even if this fails we are now implicitly back in compat mode because we
|
|
Packit |
d36e9b |
* have dropped nSelectIn */
|
|
Packit |
d36e9b |
port->current_mode = M1284_COMPAT;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_NACK, 0, &tv) != E1284_OK)
|
|
Packit |
d36e9b |
return;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->write_control (port, C1284_NINIT | C1284_NSTROBE);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_NACK, S1284_NACK,
|
|
Packit |
d36e9b |
&tv) != E1284_OK)
|
|
Packit |
d36e9b |
return;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->write_control (port, C1284_NINIT | C1284_NAUTOFD | C1284_NSTROBE);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
return;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
int
|
|
Packit |
d36e9b |
default_ecp_fwd_to_rev (struct parport_internal *port)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
int retval;
|
|
Packit |
d36e9b |
struct timeval tv;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("==> default_ecp_fwd_to_rev\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 38: Set nAutoFd low */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, 0);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* This will always work. If it won't then this method isn't available */
|
|
Packit |
d36e9b |
fn->data_dir (port, 1);
|
|
Packit |
d36e9b |
udelay (5);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 39: Set nInit low to initiate bus reversal */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NINIT, 0);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 40: PError goes low */
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
retval = fn->wait_status (port, S1284_PERROR, 0, &tv;;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (retval) {
|
|
Packit |
d36e9b |
debugprintf ("ECP direction: failed to reverse\n");
|
|
Packit |
d36e9b |
port->current_phase = PH1284_ECP_DIR_UNKNOWN;
|
|
Packit |
d36e9b |
} else {
|
|
Packit |
d36e9b |
port->current_phase = PH1284_REV_IDLE;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("<== %d default_ecp_fwd_to_rev\n", retval);
|
|
Packit |
d36e9b |
return retval;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
int
|
|
Packit |
d36e9b |
default_ecp_rev_to_fwd (struct parport_internal *port)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
int retval;
|
|
Packit |
d36e9b |
struct timeval tv;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("==> default_ecp_rev_to_fwd\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 47: Set nInit high */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NINIT | C1284_NAUTOFD,
|
|
Packit |
d36e9b |
C1284_NINIT | C1284_NAUTOFD);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 49: PError goes high */
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
retval = fn->wait_status (port, S1284_PERROR, S1284_PERROR, &tv;;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (!retval) {
|
|
Packit |
d36e9b |
fn->data_dir (port, 0);
|
|
Packit |
d36e9b |
port->current_phase = PH1284_FWD_IDLE;
|
|
Packit |
d36e9b |
} else {
|
|
Packit |
d36e9b |
debugprintf ("ECP direction: failed to switch forward\n");
|
|
Packit |
d36e9b |
port->current_phase = PH1284_ECP_DIR_UNKNOWN;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("<== %d default_ecp_rev_to_fwd\n", retval);
|
|
Packit |
d36e9b |
return retval;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ssize_t
|
|
Packit |
d36e9b |
default_nibble_read (struct parport_internal *port, int flags,
|
|
Packit |
d36e9b |
char *buffer, size_t len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
size_t count = 0;
|
|
Packit |
d36e9b |
int datain;
|
|
Packit |
d36e9b |
int low, high;
|
|
Packit |
d36e9b |
struct timeval tv;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("==> default_nibble_read\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* start of reading data from the scanner */
|
|
Packit |
d36e9b |
while (count < len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
/* More data? */
|
|
Packit |
d36e9b |
if ((count & 1) == 0 &&
|
|
Packit |
d36e9b |
(fn->read_status (port) & S1284_NFAULT))
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
debugprintf ("No more data\n");
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, 0);
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->write_control (port, C1284_NSTROBE | C1284_NINIT | C1284_NSELECTIN);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_NACK, 0, &tv)
|
|
Packit |
d36e9b |
!= E1284_OK)
|
|
Packit |
d36e9b |
goto error;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
low = fn->read_status (port) >> 3;
|
|
Packit |
d36e9b |
low = (low & 0x07) + ((low & 0x10) >> 1);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->write_control (port, C1284_NSTROBE | C1284_NINIT | C1284_NSELECTIN
|
|
Packit |
d36e9b |
| C1284_NAUTOFD);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_NACK, S1284_NACK, &tv)
|
|
Packit |
d36e9b |
!= E1284_OK)
|
|
Packit |
d36e9b |
goto error;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->write_control (port, C1284_NSTROBE | C1284_NINIT | C1284_NSELECTIN);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_NACK, 0, &tv)
|
|
Packit |
d36e9b |
!= E1284_OK)
|
|
Packit |
d36e9b |
goto error;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
high = fn->read_status (port) >> 3;
|
|
Packit |
d36e9b |
high = (high & 0x07) | ((high & 0x10) >> 1);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->write_control (port, C1284_NSTROBE | C1284_NINIT | C1284_NSELECTIN
|
|
Packit |
d36e9b |
| C1284_NAUTOFD);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_NACK, S1284_NACK, &tv)
|
|
Packit |
d36e9b |
!= E1284_OK)
|
|
Packit |
d36e9b |
goto error;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
datain = (high << 4) + low;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
buffer[count] = datain & 0xff;
|
|
Packit |
d36e9b |
count++;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("<== %d\n", len);
|
|
Packit |
d36e9b |
return len;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
error:
|
|
Packit |
d36e9b |
fn->terminate (port);
|
|
Packit |
d36e9b |
debugprintf ("<== %d (terminated on error)\n", count);
|
|
Packit |
d36e9b |
return count;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ssize_t
|
|
Packit |
d36e9b |
default_compat_write (struct parport_internal *port, int flags,
|
|
Packit |
d36e9b |
const char *buffer, size_t len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
size_t count = 0;
|
|
Packit |
d36e9b |
struct timeval tv;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("==> default_compat_write\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
while (count < len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_BUSY, 0, &tv) != E1284_OK)
|
|
Packit |
d36e9b |
goto error;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Tsetup: 750ns min. */
|
|
Packit |
d36e9b |
delay (TIMEVAL_STROBE_DELAY);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Get the data byte ready */
|
|
Packit |
d36e9b |
fn->write_data (port, buffer[count]);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Pulse nStrobe low */
|
|
Packit |
d36e9b |
fn->write_control (port, C1284_NINIT | C1284_NAUTOFD);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Tstrobe: 750ns - 500us */
|
|
Packit |
d36e9b |
delay (TIMEVAL_STROBE_DELAY);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* And raise it */
|
|
Packit |
d36e9b |
fn->write_control (port, C1284_NINIT | C1284_NAUTOFD | C1284_NSTROBE);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Thold: 750ns min. */
|
|
Packit |
d36e9b |
delay (TIMEVAL_STROBE_DELAY);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
count++;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("<== %d\n", len);
|
|
Packit |
d36e9b |
return len;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
error:
|
|
Packit |
d36e9b |
fn->terminate (port);
|
|
Packit |
d36e9b |
debugprintf ("<== %d (terminated on error)\n", count);
|
|
Packit |
d36e9b |
return count;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ssize_t
|
|
Packit |
d36e9b |
default_byte_read (struct parport_internal *port, int flags,
|
|
Packit |
d36e9b |
char *buffer, size_t len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
unsigned char *buf = buffer;
|
|
Packit |
d36e9b |
size_t count = 0;
|
|
Packit |
d36e9b |
struct timeval tv;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* FIXME: Untested as yet, copied from ieee1284_op.c,
|
|
Packit |
d36e9b |
* inverted appropriate signals */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("==> default_byte_read\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
for (count = 0; count < len; count++) {
|
|
Packit |
d36e9b |
unsigned char byte;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Data available? */
|
|
Packit |
d36e9b |
if (fn->read_status (port) & S1284_PERROR) {
|
|
Packit |
d36e9b |
/* Go to reverse idle phase. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, C1284_NAUTOFD);
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 14: Place data bus in high impedance state. */
|
|
Packit |
d36e9b |
fn->data_dir (port, 1);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 7: Set nAutoFd low. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, 0);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 9: nAck goes low. */
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_NACK, 0, &tv)) {
|
|
Packit |
d36e9b |
/* Timeout -- no more data? */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, C1284_NAUTOFD);
|
|
Packit |
d36e9b |
debugprintf ("Byte timeout at event 9\n");
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
byte = fn->read_data (port);
|
|
Packit |
d36e9b |
*buf++ = byte;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 10: Set nAutoFd high */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, C1284_NAUTOFD);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 11: nAck goes high. */
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_NACK, S1284_NACK, &tv)) {
|
|
Packit |
d36e9b |
/* Timeout -- no more data? */
|
|
Packit |
d36e9b |
debugprintf ("Byte timeout at event 11\n");
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 16: Set nStrobe low. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NSTROBE, 0);
|
|
Packit |
d36e9b |
udelay (5);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 17: Set nStrobe high. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NSTROBE, C1284_NSTROBE);
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("<== %d default_byte_read\n", count);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
return count;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ssize_t
|
|
Packit |
d36e9b |
default_epp_read_data (struct parport_internal *port, int flags,
|
|
Packit |
d36e9b |
char *buffer, size_t len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
unsigned char *buf = buffer;
|
|
Packit |
d36e9b |
ssize_t count = 0;
|
|
Packit |
d36e9b |
struct timeval tv;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* FIXME: Untested as yet, copied from ieee1284_op.c,
|
|
Packit |
d36e9b |
* inverted appropriate signals */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("==> default_epp_read_data\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* set EPP idle state (just to make sure) with strobe high */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NSTROBE | C1284_NAUTOFD |
|
|
Packit |
d36e9b |
C1284_NSELECTIN | C1284_NINIT,
|
|
Packit |
d36e9b |
C1284_NSTROBE | C1284_NINIT);
|
|
Packit |
d36e9b |
fn->data_dir (port, 1);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
for (; len > 0; len--, buf++) {
|
|
Packit |
d36e9b |
/* Event 67: set nAutoFd (nDStrb) low */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, 0);
|
|
Packit |
d36e9b |
/* Event 58: wait for Busy to go high */
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_BUSY, S1284_BUSY, &tv)) {
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
*buf = fn->read_data (port);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 63: set nAutoFd (nDStrb) high */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, C1284_NAUTOFD);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 60: wait for Busy to go low */
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_BUSY, 0, &tv)) {
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
count++;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
fn->data_dir (port, 0);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("<== default_epp_read_data\n");
|
|
Packit |
d36e9b |
return count;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static int poll_port (struct parport_internal *port, unsigned char mask,
|
|
Packit |
d36e9b |
unsigned char result, int usec)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
int count = usec / 5 + 2;
|
|
Packit |
d36e9b |
int i;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
for (i = 0; i < count; i++)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
unsigned char status = fn->read_status (port);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if ((status & mask) == result)
|
|
Packit |
d36e9b |
return E1284_OK;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (i >= 2)
|
|
Packit |
d36e9b |
udelay (5);
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
return E1284_TIMEDOUT;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ssize_t
|
|
Packit |
d36e9b |
default_epp_write_data (struct parport_internal *port, int flags,
|
|
Packit |
d36e9b |
const char *buffer, size_t len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
ssize_t ret = 0;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("==> default_epp_write_data\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Set EPP idle state (just to make sure). Also set nStrobe low. */
|
|
Packit |
d36e9b |
fn->frob_control (port,
|
|
Packit |
d36e9b |
C1284_NSTROBE | C1284_NAUTOFD
|
|
Packit |
d36e9b |
| C1284_NSELECTIN | C1284_NINIT,
|
|
Packit |
d36e9b |
C1284_NAUTOFD | C1284_NSELECTIN | C1284_NINIT);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->data_dir (port, 0);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
for (; len > 0; len--, buffer++)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
/* Event 62: Write data and set nAutoFd low */
|
|
Packit |
d36e9b |
fn->write_data (port, *buffer);
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, 0);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 58: wait for busy (nWait) to go high */
|
|
Packit |
d36e9b |
if (poll_port (port, S1284_BUSY, S1284_BUSY, 10) != E1284_OK)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
debugprintf ("Failed at event 58\n");
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 63: set nAutoFd (nDStrb) high */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, C1284_NAUTOFD);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 60: wait for busy (nWait) to go low */
|
|
Packit |
d36e9b |
if (poll_port (port, S1284_BUSY, 0, 5) != E1284_OK)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
debugprintf ("Failed at event 60\n");
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ret++;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("<== %d\n", ret);
|
|
Packit |
d36e9b |
return ret;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ssize_t
|
|
Packit |
d36e9b |
default_epp_read_addr (struct parport_internal *port, int flags,
|
|
Packit |
d36e9b |
char *buffer, size_t len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
return E1284_NOTIMPL;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ssize_t
|
|
Packit |
d36e9b |
default_epp_write_addr (struct parport_internal *port, int flags,
|
|
Packit |
d36e9b |
const char *buffer, size_t len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
return E1284_NOTIMPL;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ssize_t
|
|
Packit |
d36e9b |
default_ecp_read_data (struct parport_internal *port, int flags,
|
|
Packit |
d36e9b |
char *buffer, size_t len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
/* FIXME: RLE Not tested yet because it's not reported as being available
|
|
Packit |
d36e9b |
* by the upper layers */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
unsigned char *buf = buffer;
|
|
Packit |
d36e9b |
size_t rle_count = 0; /* shut gcc up */
|
|
Packit |
d36e9b |
int rle = 0;
|
|
Packit |
d36e9b |
size_t count = 0;
|
|
Packit |
d36e9b |
struct timeval tv;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("==> default_ecp_read_data\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (port->current_phase != PH1284_REV_IDLE)
|
|
Packit |
d36e9b |
if (fn->ecp_fwd_to_rev(port))
|
|
Packit |
d36e9b |
return 0;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
port->current_phase = PH1284_REV_DATA;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 46: Set HostAck (nAutoFd) low to start accepting data. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD | C1284_NSTROBE | C1284_NINIT,
|
|
Packit |
d36e9b |
C1284_NSTROBE);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
while (count < len) {
|
|
Packit |
d36e9b |
unsigned char byte;
|
|
Packit |
d36e9b |
int command;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 43: Peripheral sets nAck low. It can take as long as it wants.. */
|
|
Packit |
d36e9b |
/* FIXME: Should we impose some sensible limit here? */
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
while(fn->wait_status (port, S1284_NACK, 0, &tv)) { }
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Is this a command? */
|
|
Packit |
d36e9b |
if (rle)
|
|
Packit |
d36e9b |
/* The last byte was a run-length count, so this can't be as well. */
|
|
Packit |
d36e9b |
command = 0;
|
|
Packit |
d36e9b |
else
|
|
Packit |
d36e9b |
/* note: test reversed from kernel because BUSY pin is inverted */
|
|
Packit |
d36e9b |
command = (fn->read_status (port) & S1284_BUSY) ? 0 : 1;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Read the data. */
|
|
Packit |
d36e9b |
byte = fn->read_data (port);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* If this is a channel command, rather than an RLE
|
|
Packit |
d36e9b |
* command or a normal data byte, don't accept it. */
|
|
Packit |
d36e9b |
if (command) {
|
|
Packit |
d36e9b |
if (byte & 0x80) {
|
|
Packit |
d36e9b |
debugprintf ("Stopping short at channel command (%02x)\n", byte);
|
|
Packit |
d36e9b |
port->current_phase = PH1284_REV_IDLE;
|
|
Packit |
d36e9b |
return count;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
else if (!(flags & F1284_RLE))
|
|
Packit |
d36e9b |
debugprintf ("Device illegally using RLE; accepting anyway\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
rle_count = byte + 1;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Are we allowed to read that many bytes? */
|
|
Packit |
d36e9b |
if (rle_count > (len - count)) {
|
|
Packit |
d36e9b |
debugprintf ("Leaving %d RLE bytes for next time\n",
|
|
Packit |
d36e9b |
rle_count);
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
rle = 1;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 44: Set HostAck high, acknowledging handshake. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, C1284_NAUTOFD);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 45: The peripheral has 35ms to set nAck high. */
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_NACK, S1284_NACK, &tv)) {
|
|
Packit |
d36e9b |
/* It's gone wrong. Return what data we have to the caller. */
|
|
Packit |
d36e9b |
debugprintf ("ECP read timed out at 45\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (command)
|
|
Packit |
d36e9b |
debugprintf ("Command ignored (%02x)\n", byte);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Event 46: Set HostAck low and accept the data. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD, 0);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* If we just read a run-length count, fetch the data. */
|
|
Packit |
d36e9b |
if (command)
|
|
Packit |
d36e9b |
continue;
|
|
Packit |
d36e9b |
/* If this is the byte after a run-length count, decompress. */
|
|
Packit |
d36e9b |
if (rle) {
|
|
Packit |
d36e9b |
rle = 0;
|
|
Packit |
d36e9b |
memset (buf, byte, rle_count);
|
|
Packit |
d36e9b |
buf += rle_count;
|
|
Packit |
d36e9b |
count += rle_count;
|
|
Packit |
d36e9b |
debugprintf ("Decompressed to %d bytes\n", rle_count);
|
|
Packit |
d36e9b |
} else {
|
|
Packit |
d36e9b |
/* Normal data byte. */
|
|
Packit |
d36e9b |
*buf = byte;
|
|
Packit |
d36e9b |
buf++, count++;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
port->current_phase = PH1284_REV_IDLE;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("<== default_ecp_read_data\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
return count;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ssize_t
|
|
Packit |
d36e9b |
default_ecp_write_data (struct parport_internal *port, int flags,
|
|
Packit |
d36e9b |
const char *buffer, size_t len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
const unsigned char *buf = buffer;
|
|
Packit |
d36e9b |
size_t written;
|
|
Packit |
d36e9b |
int retry;
|
|
Packit |
d36e9b |
struct timeval tv;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("==> default_ecp_write_data\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (port->current_phase != PH1284_FWD_IDLE)
|
|
Packit |
d36e9b |
if (fn->ecp_rev_to_fwd(port))
|
|
Packit |
d36e9b |
return 0;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
port->current_phase = PH1284_FWD_DATA;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* HostAck high (data, not command) */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD | C1284_NINIT,
|
|
Packit |
d36e9b |
C1284_NAUTOFD | C1284_NINIT);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
for (written = 0; written < len; written++, buf++) {
|
|
Packit |
d36e9b |
unsigned char byte;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
byte = *buf;
|
|
Packit |
d36e9b |
try_again:
|
|
Packit |
d36e9b |
fn->write_data (port, byte);
|
|
Packit |
d36e9b |
/* Event 35: Set NSTROBE low */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NSTROBE, 0);
|
|
Packit |
d36e9b |
udelay (5);
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
for (retry = 0; retry < 100; retry++) {
|
|
Packit |
d36e9b |
/* Event 36: peripheral sets BUSY high */
|
|
Packit |
d36e9b |
if (!fn->wait_status (port, S1284_BUSY, S1284_BUSY, &tv))
|
|
Packit |
d36e9b |
goto success;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Time for Host Transfer Recovery (page 41 of IEEE1284) */
|
|
Packit |
d36e9b |
debugprintf ("ECP transfer stalled!\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NINIT, C1284_NINIT);
|
|
Packit |
d36e9b |
udelay (50);
|
|
Packit |
d36e9b |
if (fn->read_status (port) & S1284_PERROR) {
|
|
Packit |
d36e9b |
/* It's buggered. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NINIT, 0);
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NINIT, 0);
|
|
Packit |
d36e9b |
udelay (50);
|
|
Packit |
d36e9b |
if (!(fn->read_status (port) & S1284_PERROR))
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("Host transfer recovered\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* FIXME: Check for timeout here ? */
|
|
Packit |
d36e9b |
goto try_again;
|
|
Packit |
d36e9b |
success:
|
|
Packit |
d36e9b |
/* Event 37: HostClk (nStrobe) high */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NSTROBE, C1284_NSTROBE);
|
|
Packit |
d36e9b |
udelay (5);
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_BUSY, 0, &tv))
|
|
Packit |
d36e9b |
/* Peripheral hasn't accepted the data. */
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("<== default_ecp_write_data\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
port->current_phase = PH1284_FWD_IDLE;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
return written;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ssize_t
|
|
Packit |
d36e9b |
default_ecp_read_addr (struct parport_internal *port, int flags,
|
|
Packit |
d36e9b |
char *buffer, size_t len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
return E1284_NOTIMPL;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
ssize_t
|
|
Packit |
d36e9b |
default_ecp_write_addr (struct parport_internal *port, int flags,
|
|
Packit |
d36e9b |
const char *buffer, size_t len)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const struct parport_access_methods *fn = port->fn;
|
|
Packit |
d36e9b |
const unsigned char *buf = buffer;
|
|
Packit |
d36e9b |
size_t written;
|
|
Packit |
d36e9b |
int retry;
|
|
Packit |
d36e9b |
struct timeval tv;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("==> default_ecp_write_addr\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (port->current_phase != PH1284_FWD_IDLE)
|
|
Packit |
d36e9b |
if (fn->ecp_rev_to_fwd(port))
|
|
Packit |
d36e9b |
return 0;
|
|
Packit |
d36e9b |
port->current_phase = PH1284_FWD_DATA;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* HostAck (nAutoFd) low (command mode) */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NAUTOFD | C1284_NINIT,
|
|
Packit |
d36e9b |
C1284_NINIT);
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
for (written = 0; written < len; written++, buf++)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
unsigned char byte;
|
|
Packit |
d36e9b |
byte = *buf;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* FIXME: should we do RLE here? */
|
|
Packit |
d36e9b |
try_again:
|
|
Packit |
d36e9b |
fn->write_data (port, byte);
|
|
Packit |
d36e9b |
/* Event 35: Set NSTROBE low */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NSTROBE, 0);
|
|
Packit |
d36e9b |
udelay (5);
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
for (retry = 0; retry < 100; retry++)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
/* Event 36: peripheral sets BUSY high */
|
|
Packit |
d36e9b |
if (!fn->wait_status (port, S1284_BUSY, S1284_BUSY, &tv))
|
|
Packit |
d36e9b |
goto success;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Time for Host Transfer Recovery (page 41 of IEEE1284) */
|
|
Packit |
d36e9b |
debugprintf ("ECP address transfer stalled!\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NINIT, C1284_NINIT);
|
|
Packit |
d36e9b |
udelay (50);
|
|
Packit |
d36e9b |
if (fn->read_status (port) & S1284_PERROR)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
/* It's buggered. */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NINIT, 0);
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NINIT, 0);
|
|
Packit |
d36e9b |
udelay (50);
|
|
Packit |
d36e9b |
if (!(fn->read_status (port) & S1284_PERROR))
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("Host address transfer recovered\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* FIXME: Check for timeout here ? */
|
|
Packit |
d36e9b |
goto try_again;
|
|
Packit |
d36e9b |
success:
|
|
Packit |
d36e9b |
/* Event 37: HostClk (nStrobe) high */
|
|
Packit |
d36e9b |
fn->frob_control (port, C1284_NSTROBE, C1284_NSTROBE);
|
|
Packit |
d36e9b |
udelay (5);
|
|
Packit |
d36e9b |
lookup_delay (TIMEVAL_SIGNAL_TIMEOUT, &tv;;
|
|
Packit |
d36e9b |
if (fn->wait_status (port, S1284_BUSY, 0, &tv))
|
|
Packit |
d36e9b |
/* Peripheral hasn't accepted the data. */
|
|
Packit |
d36e9b |
break;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
debugprintf ("<== default_ecp_write_addr\n");
|
|
Packit |
d36e9b |
port->current_phase = PH1284_FWD_IDLE;
|
|
Packit |
d36e9b |
return written;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
struct timeval *
|
|
Packit |
d36e9b |
default_set_timeout (struct parport_internal *port, struct timeval *timeout)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
static struct timeval to;
|
|
Packit |
d36e9b |
to.tv_sec = 9999;
|
|
Packit |
d36e9b |
to.tv_usec = 0;
|
|
Packit |
d36e9b |
return &to;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/*
|
|
Packit |
d36e9b |
* Local Variables:
|
|
Packit |
d36e9b |
* eval: (c-set-style "gnu")
|
|
Packit |
d36e9b |
* End:
|
|
Packit |
d36e9b |
*/
|