Logo Search packages:      
Sourcecode: baycomepp version File versions  Download package

ppwin.c

/*****************************************************************************/

/*
 *      ppnt.c  -- Parport direct access with eppflex.sys/vxd.
 *
 *      Copyright (C) 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Please note that the GPL allows you to use the driver, NOT the radio.
 *  In order to use the radio, you need a license from the communications
 *  authority of your country.
 *
 */

/*****************************************************************************/

#include <windows.h>

#include "parport.h"
#include "fpga.h"

/* ---------------------------------------------------------------------- */

#define DEVICE_TYPE DWORD

#include "w9xdrv/eppflex.h"

/* ---------------------------------------------------------------------- */

/* LPT registers */
/* ECP specific registers */
#define LPTREG_ECONTROL       0x402
#define LPTREG_CONFIGB        0x401
#define LPTREG_CONFIGA        0x400
#define LPTREG_TFIFO          0x400
#define LPTREG_DFIFO          0x400
#define LPTREG_AFIFO          0x000
#define LPTREG_DSR            0x001
#define LPTREG_DCR            0x002
/* EPP specific registers */
#define LPTREG_EPPDATA        0x004
#define LPTREG_EPPADDR        0x003
/* standard registers */
#define LPTREG_CONTROL        0x002
#define LPTREG_STATUS         0x001
#define LPTREG_DATA           0x000

/* ECP config A */
#define LPTCFGA_INTRISALEVEL  0x80
#define LPTCFGA_IMPIDMASK     0x70
#define LPTCFGA_IMPID16BIT    0x00
#define LPTCFGA_IMPID8BIT     0x10
#define LPTCFGA_IMPID32BIT    0x20
#define LPTCFGA_NOPIPELINE    0x04
#define LPTCFGA_PWORDCOUNT    0x03

/* ECP config B */
#define LPTCFGB_COMPRESS      0x80
#define LPTCFGB_INTRVALUE     0x40
#define LPTCFGB_IRQMASK       0x38
#define LPTCFGB_IRQ5          0x38
#define LPTCFGB_IRQ15         0x30
#define LPTCFGB_IRQ14         0x28
#define LPTCFGB_IRQ11         0x20
#define LPTCFGB_IRQ10         0x18
#define LPTCFGB_IRQ9          0x10
#define LPTCFGB_IRQ7          0x08
#define LPTCFGB_IRQJUMPER     0x00
#define LPTCFGB_DMAMASK       0x07
#define LPTCFGB_DMA7          0x07
#define LPTCFGB_DMA6          0x06
#define LPTCFGB_DMA5          0x05
#define LPTCFGB_DMAJUMPER16   0x04
#define LPTCFGB_DMA3          0x03
#define LPTCFGB_DMA2          0x02
#define LPTCFGB_DMA1          0x01
#define LPTCFGB_DMAJUMPER8    0x00

/* ECP ECR */
#define LPTECR_MODEMASK       0xe0
#define LPTECR_MODESPP        0x00
#define LPTECR_MODEPS2        0x20
#define LPTECR_MODESPPFIFO    0x40
#define LPTECR_MODEECP        0x60
#define LPTECR_MODEECPEPP     0x80
#define LPTECR_MODETEST       0xc0
#define LPTECR_MODECFG        0xe0
#define LPTECR_NERRINTRDIS    0x10
#define LPTECR_DMAEN          0x08
#define LPTECR_SERVICEINTR    0x04
#define LPTECR_FIFOFULL       0x02
#define LPTECR_FIFOEMPTY      0x01

/* ---------------------------------------------------------------------- */

HANDLE pp_win_handle = INVALID_HANDLE_VALUE;
unsigned int pp_win_flags = 0;

#define FLAGS_PCSPP              (1<<0)
#define FLAGS_PCPS2              (1<<1)
#define FLAGS_PCEPP              (1<<2)
#define FLAGS_PCECR              (1<<3)  /* ECR Register Exists */
#define FLAGS_PCECP              (1<<4)
#define FLAGS_PCECPEPP           (1<<5)
#define FLAGS_PCECPPS2           (1<<6)

/* ---------------------------------------------------------------------- */

unsigned char parport_win_read_data(void)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return 0xff;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_READ_DATA, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res) {
            lprintf(0, "Parport: parport_win_read_data failed, error 0x%08lx\n", GetLastError());
            return 0xff;
      }
      if (retl != sizeof(rw)) {
            lprintf(0, "Parport: ioctl returned invalid length, %lu\n", retl);
            return 0xff;
      }
        return rw.data;
}

void parport_win_write_data(unsigned char d)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return;
        rw.data = d;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_WRITE_DATA, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res)
            lprintf(0, "Parport: parport_win_write_data failed, error 0x%08lx\n", GetLastError());
}

unsigned char parport_win_read_status(void)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return 0xff;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_READ_STATUS, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res) {
            lprintf(0, "Parport: parport_win_read_status failed, error 0x%08lx\n", GetLastError());
            return 0xff;
      }
      if (retl != sizeof(rw)) {
            lprintf(0, "Parport: ioctl returned invalid length, %lu\n", retl);
            return 0xff;
      }
        return rw.data;
}

void parport_win_write_status(unsigned char d)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return;
        rw.data = d;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_WRITE_STATUS, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res)
            lprintf(0, "Parport: parport_win_write_status failed, error 0x%08lx\n", GetLastError());
}

unsigned char parport_win_read_control(void)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
       
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return 0xff;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_READ_CONTROL, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res) {
            lprintf(0, "Parport: parport_win_read_control failed, error 0x%08lx\n", GetLastError());
            return 0xff;
      }
      if (retl != sizeof(rw)) {
            lprintf(0, "Parport: ioctl returned invalid length, %lu\n", retl);
            return 0xff;
      }
        return rw.data;
}

void parport_win_write_control(unsigned char d)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return;
        rw.data = d;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_WRITE_CONTROL, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res)
            lprintf(0, "Parport: parport_win_write_control failed, error 0x%08lx\n", GetLastError());
}

void parport_win_frob_control(unsigned char mask, unsigned char val)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return;
        rw.data = val;
        rw.mask = mask;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_FROB_CONTROL, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res) {
            lprintf(0, "Parport: parport_win_frob_control failed, error 0x%08lx\n", GetLastError());
            return;
      }
      if (retl != sizeof(rw)) {
            lprintf(0, "Parport: ioctl returned invalid length, %lu\n", retl);
            return;
      }
}

unsigned char parport_win_read_configa(void)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return 0xff;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_READ_CONFIGA, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res) {
            lprintf(0, "Parport: parport_win_read_configa failed, error 0x%08lx\n", GetLastError());
            return 0xff;
      }
      if (retl != sizeof(rw)) {
            lprintf(0, "Parport: ioctl returned invalid length, %lu\n", retl);
            return 0xff;
      }
        return rw.data;
}

void parport_win_write_configa(unsigned char d)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return;
        rw.data = d;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_WRITE_CONFIGA, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res)
            lprintf(0, "Parport: parport_win_write_configa failed, error 0x%08lx\n", GetLastError());
}

unsigned char parport_win_read_configb(void)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return 0xff;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_READ_CONFIGB, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res) {
            lprintf(0, "Parport: parport_win_read_configb failed, error 0x%08lx\n", GetLastError());
            return 0xff;
      }
      if (retl != sizeof(rw)) {
            lprintf(0, "Parport: ioctl returned invalid length, %lu\n", retl);
            return 0xff;
      }
        return rw.data;
}

void parport_win_write_configb(unsigned char d)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return;
        rw.data = d;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_WRITE_CONFIGB, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res)
            lprintf(0, "Parport: parport_win_write_configb failed, error 0x%08lx\n", GetLastError());
}

unsigned char parport_win_read_econtrol(void)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return 0xff;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_READ_ECONTROL, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res) {
            lprintf(0, "Parport: parport_win_read_econtrol failed, error 0x%08lx\n", GetLastError());
            return 0xff;
      }
      if (retl != sizeof(rw)) {
            lprintf(0, "Parport: ioctl returned invalid length, %lu\n", retl);
            return 0xff;
      }
        return rw.data;
}

void parport_win_write_econtrol(unsigned char d)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return;
        rw.data = d;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_WRITE_ECONTROL, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res)
            lprintf(0, "Parport: parport_win_write_econtrol failed, error 0x%08lx\n", GetLastError());
}

void parport_win_frob_econtrol(unsigned char mask, unsigned char val)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return;
        rw.data = val;
        rw.mask = mask;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_FROB_ECONTROL, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res) {
            lprintf(0, "Parport: parport_win_frob_econtrol failed, error 0x%08lx\n", GetLastError());
            return;
      }
      if (retl != sizeof(rw)) {
            lprintf(0, "Parport: ioctl returned invalid length, %lu\n", retl);
            return;
      }
}

unsigned char parport_win_read_eppaddr(void)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return 0xff;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_READ_EPPADDR, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res) {
            lprintf(0, "Parport: parport_win_read_eppaddr failed, error 0x%08lx\n", GetLastError());
            return 0xff;
      }
      if (retl != sizeof(rw)) {
            lprintf(0, "Parport: ioctl returned invalid length, %lu\n", retl);
            return 0xff;
      }
        return rw.data;
}

void parport_win_write_eppaddr(unsigned char d)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return;
        rw.data = d;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_WRITE_EPPADDR, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res)
            lprintf(0, "Parport: parport_win_write_eppaddr failed, error 0x%08lx\n", GetLastError());
}

unsigned char parport_win_read_eppdata(void)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return 0xff;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_READ_EPPDATA, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res) {
            lprintf(0, "Parport: parport_win_read_eppdata failed, error 0x%08lx\n", GetLastError());
            return 0xff;
      }
      if (retl != sizeof(rw)) {
            lprintf(0, "Parport: ioctl returned invalid length, %lu\n", retl);
            return 0xff;
      }
        return rw.data;
}

void parport_win_write_eppdata(unsigned char d)
{
        struct eppflex_rwdata rw;
        BOOL res;
        DWORD retl;
        
      if (pp_win_handle == INVALID_HANDLE_VALUE)
            return;
        rw.data = d;
      res = DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_WRITE_EPPDATA, &rw, sizeof(rw), &rw, sizeof(rw), &retl, NULL);
      if (!res)
            lprintf(0, "Parport: parport_win_write_eppdata failed, error 0x%08lx\n", GetLastError());
}

/* ---------------------------------------------------------------------- */

extern inline void setecr(unsigned char ecr)
{
      if (pp_win_flags & FLAGS_PCECR)
            parport_win_write_econtrol(ecr);
}

int pp_win_epp_clear_timeout(void)
{
        unsigned char r;

        if (!(parport_win_read_status() & LPTSTAT_EPPTIMEOUT))
                return 1;
        /* To clear timeout some chips require double read */
      parport_win_read_status();
      r = parport_win_read_status();
      parport_win_write_status(r | 0x01); /* Some reset by writing 1 */
      parport_win_write_status(r & 0xfe); /* Others by writing 0 */
        r = parport_win_read_status();
        return !(r & 0x01);
}

/* ---------------------------------------------------------------------- */

unsigned parport_win_epp_write_data(const void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret = 0;

      setecr(0x90); /* EPP mode */
      for (; sz > 0; sz--, bp++) {
            parport_win_write_eppdata(*bp);
            if (parport_win_read_status() & LPTSTAT_EPPTIMEOUT) {
                  pp_win_epp_clear_timeout();
                  goto rt;
            }
            ret++;
      }
 rt:
      setecr(0x30); /* PS/2 mode */
      return ret;
}

unsigned parport_win_epp_read_data(void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret = 0;

      setecr(0x90); /* EPP mode */
      for (; sz > 0; sz--, bp++) {
            *bp = parport_win_read_eppdata();
            if (parport_win_read_status() & LPTSTAT_EPPTIMEOUT) {
                  pp_win_epp_clear_timeout();
                  goto rt;
            }
            ret++;
      }
 rt:
      setecr(0x30); /* PS/2 mode */
      return ret;
}

unsigned parport_win_epp_write_addr(const void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret = 0;

      setecr(0x90); /* EPP mode */
      for (; sz > 0; sz--, bp++) {
            parport_win_write_eppaddr(*bp);
            if (parport_win_read_status() & LPTSTAT_EPPTIMEOUT) {
                  pp_win_epp_clear_timeout();
                  goto rt;
            }
            ret++;
      }
 rt:
      setecr(0x30); /* PS/2 mode */
      return ret;
}

unsigned parport_win_epp_read_addr(void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret = 0;

      setecr(0x90); /* EPP mode */
      for (; sz > 0; sz--, bp++) {
            *bp = parport_win_read_eppaddr();
            if (parport_win_read_status() & LPTSTAT_EPPTIMEOUT) {
                  pp_win_epp_clear_timeout();
                  goto rt;
            }
            ret++;
      }
 rt:
      setecr(0x30); /* PS/2 mode */
      return ret;
}

/* ---------------------------------------------------------------------- */

unsigned parport_win_emul_epp_write_data(const void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret = 0;
      unsigned tmo;

      parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_WRITE);
      for (; sz > 0; sz--, bp++) {
            parport_win_write_data(*bp);
            for (tmo = 0; ; tmo++) {
                  if (parport_win_read_status() & LPTSTAT_WAIT)
                        break;
                  if (tmo > 1000)
                        return ret;
            }
            parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_WRITE | LPTCTRL_DATASTB);
            for (tmo = 0; ; tmo++) {
                  if (!(parport_win_read_status() & LPTSTAT_WAIT))
                        break;
                  if (tmo > 1000)
                        return ret;
            }
            parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_WRITE);
            ret++;
      }
      return ret;
}

unsigned parport_win_emul_epp_read_data(void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret = 0;
      unsigned tmo;

      parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION);
      for (; sz > 0; sz--, bp++) {
            for (tmo = 0; ; tmo++) {
                  if (parport_win_read_status() & LPTSTAT_WAIT)
                        break;
                  if (tmo > 1000)
                        return ret;
            }
            parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION | LPTCTRL_DATASTB);
            for (tmo = 0; ; tmo++) {
                  if (!(parport_win_read_status() & LPTSTAT_WAIT))
                        break;
                  if (tmo > 1000)
                        return ret;
            }
            *bp = parport_win_read_data();
            parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION);
            ret++;
      }
      return ret;
}

unsigned parport_win_emul_epp_write_addr(const void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret = 0;
      unsigned tmo;

      parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_WRITE);
      for (; sz > 0; sz--, bp++) {
            parport_win_write_data(*bp);
            for (tmo = 0; ; tmo++) {
                  if (parport_win_read_status() & LPTSTAT_WAIT)
                        break;
                  if (tmo > 1000)
                        return ret;
            }
            parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_WRITE | LPTCTRL_ADDRSTB);
            for (tmo = 0; ; tmo++) {
                  if (!(parport_win_read_status() & LPTSTAT_WAIT))
                        break;
                  if (tmo > 1000)
                        return ret;
            }
            parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_WRITE);
            ret++;
      }
      return ret;
}

unsigned parport_win_emul_epp_read_addr(void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret = 0;
      unsigned tmo;

      parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION);
      for (; sz > 0; sz--, bp++) {
            for (tmo = 0; ; tmo++) {
                  if (parport_win_read_status() & LPTSTAT_WAIT)
                        break;
                  if (tmo > 1000)
                        return ret;
            }
            parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION | LPTCTRL_ADDRSTB);
            for (tmo = 0; ; tmo++) {
                  if (!(parport_win_read_status() & LPTSTAT_WAIT))
                        break;
                  if (tmo > 1000)
                        return ret;
            }
            *bp = parport_win_read_data();
            parport_win_write_control(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION);
            ret++;
      }
      return ret;
}

/* ---------------------------------------------------------------------- */

static int ecp_forward(void)
{
      unsigned tmo = 0x10000;

      if (parport_win_read_status() & 0x20)
            return 0;
      /* Event 47: Set nInit high */
      parport_win_write_control(0x26);
      /* Event 49: PError goes high */
      while (!(parport_win_read_status() & 0x20)) {
            if (!(--tmo))
                  return -1;
      }
      /* start driving the bus */
      parport_win_write_control(0x04);
      return 0;
}

static int ecp_reverse(void)
{
      unsigned tmo = 0x10000;

      if (!(parport_win_read_status() & 0x20))
            return 0;
      parport_win_write_control(0x24);
      /* Event 39: Set nInit low to initiate bus reversal */
      parport_win_write_control(0x20);
      while (parport_win_read_status() & 0x20) {
            if (!(--tmo))
                  return -1;
      }
      return 0;
}

static unsigned emptyfifo(unsigned cnt)
{
      unsigned fcnt = 0;

      parport_win_write_econtrol(0xd0); /* FIFOtest mode */
      while ((parport_win_read_econtrol() & 0x01) && fcnt < 32 && fcnt < cnt) {
            parport_win_read_configa();
            fcnt++;
      }
      lprintf(10, "emptyfifo: FIFO contained %d bytes\n", fcnt);
      parport_win_write_econtrol(0x30); /* PS/2 mode */
      return cnt - fcnt;
}

unsigned parport_win_ecp_write_data(const void *buf, unsigned sz)
{
      const unsigned char *bp = (const unsigned char *)buf;
      unsigned ret = 0;
      unsigned tmo = 0x10000;
      unsigned char stat;
        unsigned int i;
        
      if (ecp_forward())
            return 0;
      parport_win_write_econtrol(0x70); /* ECP mode */
      while (sz > 0) {
            while ((stat = parport_win_read_econtrol()) & 0x02) {
                  if (!(--tmo))
                        return emptyfifo(ret);
            }
            if (stat & 0x01 && sz >= 8) {
                        for (i = 0; i < 8; i++)
                                parport_win_write_configa(bp[i]);
                  bp += 8;
                  sz -= 8;
                  ret += 8;
            } else {
                  parport_win_write_configa(*bp++);
                  sz--;
                  ret++;
            }
            tmo = 0x10000;
      }
      while (!(parport_win_read_econtrol() & 0x01) || !(parport_win_read_status() & 0x80)) {
            if (!(--tmo))
                  return emptyfifo(ret);
      }
      parport_win_write_econtrol(0x30); /* PS/2 mode */
      return ret;
}

unsigned parport_win_ecp_read_data(void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret = 0;
      unsigned tmo = 0x10000;
      unsigned char stat;
      unsigned int i;
        
      if (ecp_reverse())
            return 0;
      parport_win_write_econtrol(0x70); /* ECP mode */
      while (sz > 0) {
            while ((stat = parport_win_read_econtrol()) & 0x01)
                  if (!(--tmo)) {
                        parport_win_write_econtrol(0xd0); /* FIFOTEST mode */
                        while (!(parport_win_read_econtrol() & 0x01) && sz > 0) {
                              *bp++ = parport_win_read_configa();
                              sz--;
                              ret++;
                        }
                        parport_win_write_econtrol(0x30); /* PS/2 mode */
                        return ret;
                  }
            if (stat & 0x02 && sz >= 8) {
                        for (i = 0; i < 8; i++)
                                bp[i] = parport_win_read_configa();
                  bp += 8;
                  sz -= 8;
                  ret += 8;
            } else {
                  *bp++ = parport_win_read_configa();
                  sz--;
                  ret++;
            }
            tmo = 0x10000;
      }
      parport_win_write_econtrol(0x30); /* PS/2 mode */
      return ret;
}

unsigned parport_win_ecp_write_addr(const void *buf, unsigned sz)
{
      const unsigned char *bp = (const unsigned char *)buf;
      unsigned ret = 0;
      unsigned tmo = 0x10000;
      unsigned char stat;
        unsigned int i;
        
      if (ecp_forward())
            return 0;
      parport_win_write_econtrol(0x70); /* ECP mode */
      while (sz > 0) {
            while ((stat = parport_win_read_econtrol()) & 0x02) {
                  if (!(--tmo))
                        return emptyfifo(ret);
            }
            if (stat & 0x01 && sz >= 8) {
                        for (i = 0; i < 8; i++)
                        parport_win_write_data(bp[i]);
                  bp += 8;
                  sz -= 8;
                  ret += 8;
            } else {
                  parport_win_write_data(*bp++);
                  sz--;
                  ret++;
            }
            tmo = 0x10000;
      }
      while (!(parport_win_read_econtrol() & 0x01) || !(parport_win_read_status() & 0x80)) {
            if (!(--tmo))
                  return emptyfifo(ret);
      }
      parport_win_write_econtrol(0x30); /* PS/2 mode */
      return ret;
}

/* ---------------------------------------------------------------------- */

unsigned parport_win_emul_ecp_write_data(const void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret;
      unsigned char ctl;
      unsigned tmo;

      if (ecp_forward())
            return 0;
      ctl = parport_win_read_control() & ~PARPORT_CONTROL_AUTOFD;
      /* HostAck high (data, not command) */
      parport_win_write_control(ctl);
      for (ret = 0; ret < sz; ret++, bp++) {
            parport_win_write_data(*bp);
            parport_win_write_control(ctl | PARPORT_CONTROL_STROBE);
            for (tmo = 0; parport_win_read_status() & PARPORT_STATUS_BUSY; tmo++)
                  if (tmo > 0x1000)
                        return ret;
            parport_win_write_control(ctl);
            for (tmo = 0; !(parport_win_read_status() & PARPORT_STATUS_BUSY); tmo++)
                  if (tmo > 0x1000)
                        return ret;
      }
      return ret;
}

unsigned parport_win_emul_ecp_write_addr(const void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret;
      unsigned char ctl;
      unsigned tmo;

      if (ecp_forward())
            return 0;
      ctl = parport_win_read_control() | PARPORT_CONTROL_AUTOFD;
      /* HostAck low (command, not data) */
      parport_win_write_control(ctl);
      for (ret = 0; ret < sz; ret++, bp++) {
            parport_win_write_data(*bp);
            parport_win_write_control(ctl | PARPORT_CONTROL_STROBE);
            for (tmo = 0; parport_win_read_status() & PARPORT_STATUS_BUSY; tmo++)
                  if (tmo > 0x1000)
                        return ret;
            parport_win_write_control(ctl);
            for (tmo = 0; !(parport_win_read_status() & PARPORT_STATUS_BUSY); tmo++)
                  if (tmo > 0x1000)
                        return ret;
      }
      return ret;
}

unsigned parport_win_emul_ecp_read_data(void *buf, unsigned sz)
{
      unsigned char *bp = (unsigned char *)buf;
      unsigned ret = 0;
      unsigned char ctl, stat;
      int command;
      unsigned tmo;

      if (ecp_reverse())
            return 0;   
      ctl = parport_win_read_control();
      /* Set HostAck low to start accepting data. */
      parport_win_write_control(ctl | PARPORT_CONTROL_AUTOFD);
      while (ret < sz) {
            /* Event 43: Peripheral sets nAck low. It can take as
                   long as it wants. */
            tmo = 0;
            do {
                  stat = parport_win_read_status();
                  if ((++tmo) > 0x10000)
                        goto out;
            } while (stat & PARPORT_STATUS_ACK);
            /* Is this a command? */
            command = stat & PARPORT_STATUS_BUSY;
            if (command) {
                  //lprintf(3, "ECP: warning: emulation does not support RLE\n");
                  goto out;
            }
            /* Read the data. */
            *bp = parport_win_read_data();
            /* Event 44: Set HostAck high, acknowledging handshake. */
            parport_win_write_control(ctl & ~PARPORT_CONTROL_AUTOFD);
            /* Event 45: The peripheral has 35ms to set nAck high. */
            tmo = 0;
            do {
                  stat = parport_win_read_status();
                  if ((++tmo) > 0x10000)
                        goto out;
            } while (!(stat & PARPORT_STATUS_ACK));
            /* Event 46: Set HostAck low and accept the data. */
            parport_win_write_control(ctl | PARPORT_CONTROL_AUTOFD);
            /* Normal data byte. */
            bp++;
            ret++;
      }

 out:
      return ret;
}
 
/* ---------------------------------------------------------------------- */

#if 1
unsigned parport_win_fpgaconfig_write(const void *buf, unsigned sz)
{
      const unsigned char *bp = buf;
      unsigned u;

      for (u = 0; u < sz; u++, bp++)
            parport_win_write_data(*bp);
      return sz;
}
#else

unsigned parport_win_fpgaconfig_write(const void *buf, unsigned sz)
{
      const unsigned char *bp = buf;
      unsigned ret = 0;
      unsigned tmo = 0x10000;
      unsigned char stat;
        unsigned int i;

      if (pp_win_modes & PARPORT_MODE_PCECR) {
            parport_win_write_econtrol(0x50); /* COMPAT FIFO mode */
            while (sz > 0) {
                  while ((stat = parport_win_read_econtrol()) & 0x02) {
                        if (!(--tmo))
                              return emptyfifo(ret);
                  }
                  if (stat & 0x01 && sz >= 8) {
                                for (i = 0; i < 8; i++)
                                        parport_win_write_configa(bp[i]);
                        bp += 8;
                        sz -= 8;
                        ret += 8;
                  } else {
                        parport_win_write_configa(*bp++);
                        sz--;
                        ret++;
                  }
                  tmo = 0x10000;
            }
            while (!(parport_win_read_econtrol() & 0x01) || !(parport_win_read_status() & 0x80)) {
                  if (!(--tmo))
                        return emptyfifo(ret);
            }
            parport_win_write_econtrol(0x30); /* PS/2 mode */
            return ret;
      }
      for (ret = 0; ret < sz; ret++, bp++)
            parport_win_write_data(*bp);
      return sz;
}
#endif

/* ---------------------------------------------------------------------- */

const struct parport_ops parport_win_ops = {
      parport_win_read_data,
      parport_win_write_data,
      parport_win_read_status,
      parport_win_read_control,
      parport_win_write_control,
      parport_win_frob_control,
      parport_win_epp_write_data,
      parport_win_epp_read_data,
      parport_win_epp_write_addr,
      parport_win_epp_read_addr,
      parport_win_ecp_write_data,
      parport_win_ecp_read_data,
      parport_win_ecp_write_addr,
      parport_win_fpgaconfig_write
};

const struct parport_ops parport_win_emul_ops = {
      parport_win_read_data,
      parport_win_write_data,
      parport_win_read_status,
      parport_win_read_control,
      parport_win_write_control,
      parport_win_frob_control,
      parport_win_emul_epp_write_data,
      parport_win_emul_epp_read_data,
      parport_win_emul_epp_write_addr,
      parport_win_emul_epp_read_addr,
      parport_win_emul_ecp_write_data,
      parport_win_emul_ecp_read_data,
      parport_win_emul_ecp_write_addr,
      parport_win_fpgaconfig_write
};

/* ---------------------------------------------------------------------- */

Generated by  Doxygen 1.6.0   Back to index