Blame src/access_lpt.c

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, &reg, 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
 */