|
Packit |
d36e9b |
/*
|
|
Packit |
d36e9b |
* libieee1284 - IEEE 1284 library
|
|
Packit |
d36e9b |
* Copyright (C) 2001, 2002 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 |
* This file defines access for VDMLPT on NT kernels. Basically a copy of
|
|
Packit |
d36e9b |
* access_io.c with some slight differences.
|
|
Packit |
d36e9b |
*/
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#include "config.h"
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#include <fcntl.h>
|
|
Packit |
d36e9b |
#include <stdio.h>
|
|
Packit |
d36e9b |
#include <string.h>
|
|
Packit |
d36e9b |
#if !(defined __MINGW32__ || defined _MSC_VER)
|
|
Packit |
d36e9b |
#include <sys/ioctl.h>
|
|
Packit |
d36e9b |
#else
|
|
Packit |
d36e9b |
#include <sys/timeb.h> /* ftime() */
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
#include <sys/stat.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 |
|
|
Packit |
d36e9b |
#include "access.h"
|
|
Packit |
d36e9b |
#include "debug.h"
|
|
Packit |
d36e9b |
#include "default.h"
|
|
Packit |
d36e9b |
#include "delay.h"
|
|
Packit |
d36e9b |
#include "ieee1284.h"
|
|
Packit |
d36e9b |
#include "detect.h"
|
|
Packit |
d36e9b |
#include "parport.h"
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#ifdef HAVE_CYGWIN_NT
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#ifdef __CYGWIN__
|
|
Packit |
d36e9b |
#include <w32api/windows.h>
|
|
Packit |
d36e9b |
#else
|
|
Packit |
d36e9b |
#include <windows.h>
|
|
Packit |
d36e9b |
#endif
|
|
Packit |
d36e9b |
#include "par_nt.h"
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static int
|
|
Packit |
d36e9b |
init (struct parport *pport, int flags, int *capabilities)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
struct parport_internal *port = pport->priv;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Note: We can only ever provide exclusive access on NT. */
|
|
Packit |
d36e9b |
if (flags & ~F1284_EXCL) /* silently ignore F1284_EXCL - dbjh */
|
|
Packit |
d36e9b |
return E1284_NOTAVAIL;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
port->fd = (int)CreateFile(port->device, GENERIC_READ | GENERIC_WRITE,
|
|
Packit |
d36e9b |
0, NULL, OPEN_EXISTING, 0, NULL);
|
|
Packit |
d36e9b |
if (port->fd == (int)INVALID_HANDLE_VALUE)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
if (port->device != NULL)
|
|
Packit |
d36e9b |
debugprintf("Failed opening %s\n", port->device);
|
|
Packit |
d36e9b |
return E1284_SYS;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (capabilities)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
*capabilities |= CAP1284_RAW;
|
|
Packit |
d36e9b |
/* Can't do bidir mode with this port */
|
|
Packit |
d36e9b |
*capabilities &= ~(CAP1284_ECPSWE | CAP1284_BYTE);
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Need to write this.
|
|
Packit |
d36e9b |
* If we find an ECP port, we can adjust some of the access function
|
|
Packit |
d36e9b |
* pointers in io_access_functions to point to functions that use
|
|
Packit |
d36e9b |
* hardware assistance. */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
return E1284_OK;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static void
|
|
Packit |
d36e9b |
cleanup (struct parport_internal *port)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
CloseHandle((HANDLE)(port->fd));
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static void
|
|
Packit |
d36e9b |
write_data (struct parport_internal *port, unsigned char reg)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
unsigned int dummy;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (!(DeviceIoControl((HANDLE)(port->fd), NT_IOCTL_DATA, ®, sizeof(reg),
|
|
Packit |
d36e9b |
NULL, 0, (LPDWORD)&dummy, NULL)))
|
|
Packit |
d36e9b |
debugprintf("raw_outb: DeviceIoControl failed!\n");
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static int
|
|
Packit |
d36e9b |
read_status (struct parport_internal *port)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
char ret;
|
|
Packit |
d36e9b |
unsigned int dummy;
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
if (!(DeviceIoControl((HANDLE)(port->fd), NT_IOCTL_STATUS, NULL, 0, &ret,
|
|
Packit |
d36e9b |
sizeof(ret), (LPDWORD)&dummy, NULL)))
|
|
Packit |
d36e9b |
debugprintf("read_status: DeviceIoControl failed!\n");
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
return debug_display_status ((unsigned char)(ret ^ S1284_INVERTED));
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static void
|
|
Packit |
d36e9b |
raw_frob_control (struct parport_internal *port,
|
|
Packit |
d36e9b |
unsigned char mask,
|
|
Packit |
d36e9b |
unsigned char val)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
unsigned char ctr = port->ctr;
|
|
Packit |
d36e9b |
unsigned char dummyc;
|
|
Packit |
d36e9b |
unsigned int dummy;
|
|
Packit |
d36e9b |
/* Deal with inversion issues. */
|
|
Packit |
d36e9b |
val ^= mask & C1284_INVERTED;
|
|
Packit |
d36e9b |
ctr = (ctr & ~mask) ^ val;
|
|
Packit |
d36e9b |
if (!(DeviceIoControl((HANDLE)(port->fd), NT_IOCTL_CONTROL, &ctr,
|
|
Packit |
d36e9b |
sizeof(ctr), &dummyc, sizeof(dummyc), (LPDWORD)&dummy, NULL)))
|
|
Packit |
d36e9b |
debugprintf("frob_control: DeviceIoControl failed!\n");
|
|
Packit |
d36e9b |
port->ctr = ctr;
|
|
Packit |
d36e9b |
debug_frob_control (mask, val);
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static int
|
|
Packit |
d36e9b |
read_control (struct parport_internal *port)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const unsigned char rm = (C1284_NSTROBE |
|
|
Packit |
d36e9b |
C1284_NAUTOFD |
|
|
Packit |
d36e9b |
C1284_NINIT |
|
|
Packit |
d36e9b |
C1284_NSELECTIN);
|
|
Packit |
d36e9b |
return (port->ctr ^ C1284_INVERTED) & rm;
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static void
|
|
Packit |
d36e9b |
write_control (struct parport_internal *port, unsigned char reg)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const unsigned char wm = (C1284_NSTROBE |
|
|
Packit |
d36e9b |
C1284_NAUTOFD |
|
|
Packit |
d36e9b |
C1284_NINIT |
|
|
Packit |
d36e9b |
C1284_NSELECTIN);
|
|
Packit |
d36e9b |
if (reg & 0x20)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
/* Note: data direction not supported by LPT driver */
|
|
Packit |
d36e9b |
printf ("error: setting data dir is invalid in this mode!\n");
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
raw_frob_control (port, wm, (unsigned char)(reg & wm));
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static void
|
|
Packit |
d36e9b |
frob_control (struct parport_internal *port,
|
|
Packit |
d36e9b |
unsigned char mask,
|
|
Packit |
d36e9b |
unsigned char val)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
const unsigned char wm = (C1284_NSTROBE |
|
|
Packit |
d36e9b |
C1284_NAUTOFD |
|
|
Packit |
d36e9b |
C1284_NINIT |
|
|
Packit |
d36e9b |
C1284_NSELECTIN);
|
|
Packit |
d36e9b |
if (mask & 0x20)
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
/* Note: data direction not supported by LPT driver */
|
|
Packit |
d36e9b |
printf ("error: setting data dir is invalid in this mode!\n");
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
mask &= wm;
|
|
Packit |
d36e9b |
val &= wm;
|
|
Packit |
d36e9b |
raw_frob_control (port, mask, val);
|
|
Packit |
d36e9b |
}
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
static int
|
|
Packit |
d36e9b |
wait_status (struct parport_internal *port,
|
|
Packit |
d36e9b |
unsigned char mask, unsigned char val,
|
|
Packit |
d36e9b |
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 ((debug_display_status ((unsigned char)(read_status (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 |
const struct parport_access_methods lpt_access_methods =
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
init,
|
|
Packit |
d36e9b |
cleanup,
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL, /* claim */
|
|
Packit |
d36e9b |
NULL, /* release */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL, /* raw_inb */
|
|
Packit |
d36e9b |
NULL, /* raw_outb */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL, /* get_irq_fd */
|
|
Packit |
d36e9b |
NULL, /* clear_irq */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL, /* read_data */
|
|
Packit |
d36e9b |
write_data,
|
|
Packit |
d36e9b |
default_wait_data,
|
|
Packit |
d36e9b |
NULL, /* data_dir */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
read_status,
|
|
Packit |
d36e9b |
wait_status,
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
read_control,
|
|
Packit |
d36e9b |
write_control,
|
|
Packit |
d36e9b |
frob_control,
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
default_do_nack_handshake,
|
|
Packit |
d36e9b |
default_negotiate,
|
|
Packit |
d36e9b |
default_terminate,
|
|
Packit |
d36e9b |
default_ecp_fwd_to_rev,
|
|
Packit |
d36e9b |
default_ecp_rev_to_fwd,
|
|
Packit |
d36e9b |
default_nibble_read,
|
|
Packit |
d36e9b |
default_compat_write,
|
|
Packit |
d36e9b |
default_byte_read,
|
|
Packit |
d36e9b |
default_epp_read_data,
|
|
Packit |
d36e9b |
default_epp_write_data,
|
|
Packit |
d36e9b |
default_epp_read_addr,
|
|
Packit |
d36e9b |
default_epp_write_addr,
|
|
Packit |
d36e9b |
default_ecp_read_data,
|
|
Packit |
d36e9b |
default_ecp_write_data,
|
|
Packit |
d36e9b |
default_ecp_read_addr,
|
|
Packit |
d36e9b |
default_ecp_write_addr,
|
|
Packit |
d36e9b |
default_set_timeout
|
|
Packit |
d36e9b |
};
|
|
Packit |
d36e9b |
#else
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/* Null struct to keep the compiler happy */
|
|
Packit |
d36e9b |
const struct parport_access_methods lpt_access_methods =
|
|
Packit |
d36e9b |
{
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL, /* inb */
|
|
Packit |
d36e9b |
NULL, /* outb */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL,
|
|
Packit |
d36e9b |
NULL
|
|
Packit |
d36e9b |
};
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
#endif /* HAVE_CYGWIN_NT */
|
|
Packit |
d36e9b |
|
|
Packit |
d36e9b |
/*
|
|
Packit |
d36e9b |
* Local Variables:
|
|
Packit |
d36e9b |
* eval: (c-set-style "gnu")
|
|
Packit |
d36e9b |
* End:
|
|
Packit |
d36e9b |
*/
|