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

eppflex.c

/*
 * Thomas Sailer, (C) 2000
 */

#include <basedef.h>
#include <vmm.h>
#include <vmmreg.h>
#include <debug.h>
#include <vwin32.h>
#include <vcomm.h>        /* must be included before VXDWRAPS.H */
#include <vxdwraps.h>
#include <winerror.h>
#include <configmg.h>
#include "eppflex.h"

#pragma VxD_LOCKED_CODE_SEG
#pragma VxD_LOCKED_DATA_SEG

#define printk(x) Out_Debug_String(x)

#define MAXPORTS 4

static struct portconfig {
      unsigned int addr0, addr0end;
      unsigned int addr1, addr1end;
      int irq;
      int dma;
} portconfig[MAXPORTS];

static DWORD porthandle = 0;
static PFN conthandler = NULL;
static unsigned int portnr;

static DWORD StealNotifyHandler( void *RefData, DWORD dwNotification )
{
        /* steal handler: we do not allow anyone to steal our port */
        return FALSE;
}

static UCHAR inb(WORD port)
{
        _asm {
                mov dx,[port]
                in al,dx
                jmp del1
del1:           jmp del2
del2:           xor ah,ah
        }
}

static void outb(UCHAR data, WORD port)
{
        _asm {
                mov dx,[port]
                mov al,byte ptr data
                out dx,al
                jmp del1
del1:           jmp del2
del2:
        }
}

static void releaseport(void)
{
        if (!conthandler)
                return;
        (*conthandler)(RELEASE_RESOURCE, porthandle, StealNotifyHandler);
        porthandle = 0;
}

static int acquireport(unsigned int port)
{
        char lptname[] = "LPTx";
        int ret;
        
        if (porthandle)
                releaseport();
        porthandle = 0;
        if (port >= MAXPORTS)
                return ERROR_BAD_DEVICE;
      if (!portconfig[port].addr0)
            return ERROR_BAD_DEVICE;
      portnr = port;
      lptname[3] = '1' + port;
        conthandler = VCOMM_Get_Contention_Handler(lptname);
        if (!conthandler)
                return ERROR_BAD_DEVICE;
        porthandle = VCOMM_Map_Name_To_Resource(lptname);
        if (!porthandle)
                return ERROR_BAD_DEVICE;
        ret = (*conthandler)(ACQUIRE_RESOURCE, porthandle, StealNotifyHandler, porthandle, TRUE);
        if (!ret)
                return ERROR_BAD_DEVICE;
        return NO_ERROR;
}

/*
 * LPT find configuration stuff
 */

static void printknum(DWORD num)
{
      char buf[16];
      char *cp = &buf[16];

      *--cp = 0;
      do {
            *--cp = '0' + (num % 10);
            num /= 10;
      } while (num);
      printk(cp);
}

static void printkhex(DWORD num, DWORD digits)
{
      char buf[9];
      char *cp = &buf[9];

      *--cp = 0;
      if (digits > 8)
            digits = 8;
      if (!digits)
            return;
      do {
            if ((num & 15) >= 10)
                  *--cp = 'A' - 10 + (num & 15);
            else
                  *--cp = '0' + (num & 15);
            num >>= 4;
            digits--;
      } while (digits);
      printk(cp);
}

static void printdevid(DEVNODE dn)
{
      char buf[MAX_DEVICE_ID_LEN];

      if (CM_Get_Device_ID(dn, buf, sizeof(buf), 0) != CR_SUCCESS)
            return;
      printk("Device ID: ");
      printk(buf);
      printk("\n");
}

static void nodefoundport(DEVNODE dn, unsigned int portnr)
{
      LOG_CONF lc;
      RES_DES rd;
      IO_DES iod;
      IRQ_DES irqd;
      DMA_DES dmad;
      struct portconfig cfg;

      if (portnr >= MAXPORTS) {
            printk("Port number overflow\n");
            return;
      }
      cfg.addr0 = cfg.addr0end = cfg.addr1 = cfg.addr1end = 0;
      cfg.irq = cfg.dma = -1;
      if (CM_Get_First_Log_Conf(&lc, dn, ALLOC_LOG_CONF) == CR_SUCCESS) {
            rd = (RES_DES)lc;
            while (CM_Get_Next_Res_Des(&rd, rd, ResType_IO, NULL, 0) == CR_SUCCESS) {
                  if (CM_Get_Res_Des_Data(rd, &iod, sizeof(iod), 0) == CR_SUCCESS) {
                        if (iod.IOD_Alloc_Base >= 0x400) {
                              cfg.addr1 = iod.IOD_Alloc_Base;
                              cfg.addr1end = iod.IOD_Alloc_End;
                        } else {
                              cfg.addr0 = iod.IOD_Alloc_Base;
                              cfg.addr0end = iod.IOD_Alloc_End;
                        }
                  }
            }
            rd = (RES_DES)lc;
            while (CM_Get_Next_Res_Des(&rd, rd, ResType_IRQ, NULL, 0) == CR_SUCCESS) {
                  if (CM_Get_Res_Des_Data(rd, &irqd, sizeof(irqd), 0) == CR_SUCCESS) {
                        cfg.irq = irqd.IRQD_Alloc_Num;
                  }
            }
            rd = (RES_DES)lc;
            while (CM_Get_Next_Res_Des(&rd, rd, ResType_DMA, NULL, 0) == CR_SUCCESS) {
                  if (CM_Get_Res_Des_Data(rd, &dmad, sizeof(dmad), 0) == CR_SUCCESS) {
                        cfg.dma = dmad.DD_Alloc_Chan;
                  }
            }
      }
      if (cfg.addr0)
            portconfig[portnr] = cfg;
      printk("LPT");
      printknum(portnr+1);
      printk(": IO Ranges: ");
      printkhex(cfg.addr0, 4);
      printk("-");
      printkhex(cfg.addr0end, 4);
      printk(" ");
      printkhex(cfg.addr1, 4);
      printk("-");
      printkhex(cfg.addr1end, 4);
      if (cfg.irq != -1) {
            printk("  IRQ ");
            printknum(cfg.irq);
      }
      if (cfg.dma != -1) {
            printk("  DMA ");
            printknum(cfg.dma);
      }
      printk("\n");
}

static void nodeconfig(DEVNODE dn)
{
      char key[MAX_VMM_REG_KEY_LEN];
      char portname[64];
      ULONG portsz;
      VMMHKEY hkey;

      if (CM_Get_DevNode_Key(dn, NULL, &key, sizeof(key), CM_REGISTRY_HARDWARE) == CR_SUCCESS) {
            portsz = sizeof(portname);
            if (_RegOpenKey(HKEY_LOCAL_MACHINE, key, &hkey) == ERROR_SUCCESS) {
                  if (_RegQueryValueEx(hkey, "PORTNAME", NULL, NULL, portname, &portsz) == ERROR_SUCCESS) {
                        printdevid(dn);
                        printk("Port name: ");
                        printk(portname);
                        printk("\n");
                        if (portname[0] = 'L' && portname[1] == 'P' && portname[2] == 'T' && portname[4] == 0)
                              nodefoundport(dn, portname[3] - '1');
                  }
                  _RegCloseKey(hkey);
            }
      }
}

static void nodesubtree(DEVNODE dn)
{
      DWORD dnch;

      do {
            nodeconfig(dn);
            if (CM_Get_Child(&dnch, dn, 0) == CR_SUCCESS)
                  nodesubtree(dnch);
      } while (CM_Get_Sibling(&dn, dn, 0) == CR_SUCCESS);
}

static void retrieveconfig(void)
{
      DEVNODE dn;
      CONFIGRET ret;

      ret = CM_Locate_DevNode(&dn, NULL, 0);
      if (ret != CR_SUCCESS) {
            printk("Locate_DevNode error: ");
            printknum(ret);
            printk("\n");
            return;
      }
      nodesubtree(dn);
}

BOOL OnSysDynamicDeviceInit(void)
{
      printk("eppflex: dynamic init\n");

      memset(portconfig, 0, sizeof(portconfig));
      retrieveconfig();

        return TRUE;
}

BOOL OnSysDynamicDeviceExit(void)
{
      printk("eppflex: dynamic exit\n");
        if (porthandle)
                releaseport();
        return TRUE;
}

static DWORD read_port(PDIOCPARAMETERS p, WORD port)
{
        struct eppflex_rwdata *rwout = (struct eppflex_rwdata *)p->lpvOutBuffer;

        if (!porthandle)
                return ERROR_INVALID_PARAMETER;
        if (p->cbOutBuffer < sizeof(struct eppflex_rwdata))
                return ERROR_INVALID_PARAMETER;
      if (!port)
            return ERROR_INVALID_PARAMETER;
      if ((port < portconfig[portnr].addr0 || port > portconfig[portnr].addr0end) &&
          (port < portconfig[portnr].addr1 || port > portconfig[portnr].addr1end))
            return ERROR_INVALID_PARAMETER;
        rwout->data = inb(port);
      if (p->lpcbBytesReturned)
            *((DWORD *)p->lpcbBytesReturned) = sizeof(struct eppflex_rwdata);
        return NO_ERROR;
}

static DWORD write_port(PDIOCPARAMETERS p, WORD port)
{
        struct eppflex_rwdata *rwin = (struct eppflex_rwdata *)p->lpvInBuffer;

        if (!porthandle)
                return ERROR_INVALID_PARAMETER;
        if (p->cbInBuffer < sizeof(struct eppflex_rwdata))
                return ERROR_INVALID_PARAMETER;
      if (!port)
            return ERROR_INVALID_PARAMETER;
      if ((port < portconfig[portnr].addr0 || port > portconfig[portnr].addr0end) &&
          (port < portconfig[portnr].addr1 || port > portconfig[portnr].addr1end))
            return ERROR_INVALID_PARAMETER;
        outb(rwin->data, port);
      if (p->lpcbBytesReturned)
            *((DWORD *)p->lpcbBytesReturned) = 0;
        return NO_ERROR;
}

static DWORD frob_port(PDIOCPARAMETERS p, WORD port)
{
        struct eppflex_rwdata *rwin = (struct eppflex_rwdata *)p->lpvInBuffer;
        struct eppflex_rwdata *rwout = (struct eppflex_rwdata *)p->lpvOutBuffer;
        unsigned char data;
        
        if (!porthandle)
                return ERROR_INVALID_PARAMETER;
        if (p->cbInBuffer < sizeof(struct eppflex_rwdata) ||
            p->cbOutBuffer < sizeof(struct eppflex_rwdata))
                return ERROR_INVALID_PARAMETER;
      if (!port)
            return ERROR_INVALID_PARAMETER;
      if ((port < portconfig[portnr].addr0 || port > portconfig[portnr].addr0end) &&
          (port < portconfig[portnr].addr1 || port > portconfig[portnr].addr1end))
            return ERROR_INVALID_PARAMETER;
        data = inb(port);
        data = (data & ~rwin->mask) ^ rwin->data;
        outb(data, port);
        rwout->data = data;
        rwout->mask = rwin->mask;
      if (p->lpcbBytesReturned)
            *((DWORD *)p->lpcbBytesReturned) = sizeof(struct eppflex_rwdata);
        return NO_ERROR;
}

DWORD OnW32DeviceIoControl(PDIOCPARAMETERS p)
{
      if (p->lpcbBytesReturned)
            *((DWORD *)p->lpcbBytesReturned) = 0;
        switch (p->dwIoControlCode) {
        case DIOC_OPEN:
                return NO_ERROR;
                
        case DIOC_CLOSEHANDLE:
                return NO_ERROR;

        case IOCTL_EPPFLEX_READ_DATA:
                return read_port(p, (WORD)(portconfig[portnr].addr0));

        case IOCTL_EPPFLEX_WRITE_DATA:
                return write_port(p, (WORD)(portconfig[portnr].addr0));

        case IOCTL_EPPFLEX_READ_STATUS:
                return read_port(p, (WORD)(portconfig[portnr].addr0 + 1));

        case IOCTL_EPPFLEX_WRITE_STATUS:
                return write_port(p, (WORD)(portconfig[portnr].addr0 + 1));

        case IOCTL_EPPFLEX_READ_CONTROL:
                return read_port(p, (WORD)(portconfig[portnr].addr0 + 2));

        case IOCTL_EPPFLEX_WRITE_CONTROL:
                return write_port(p, (WORD)(portconfig[portnr].addr0 + 2));

        case IOCTL_EPPFLEX_FROB_CONTROL:
                return frob_port(p, (WORD)(portconfig[portnr].addr0 + 2));

        case IOCTL_EPPFLEX_READ_ECONTROL:
                return read_port(p, (WORD)(portconfig[portnr].addr1 + 2));

        case IOCTL_EPPFLEX_WRITE_ECONTROL:
                return write_port(p, (WORD)(portconfig[portnr].addr1 + 2));

        case IOCTL_EPPFLEX_FROB_ECONTROL:
                return frob_port(p, (WORD)(portconfig[portnr].addr1 + 2));

        case IOCTL_EPPFLEX_READ_CONFIGA:
                return read_port(p, (WORD)(portconfig[portnr].addr1));

        case IOCTL_EPPFLEX_WRITE_CONFIGA:
                return write_port(p, (WORD)(portconfig[portnr].addr1));

        case IOCTL_EPPFLEX_READ_CONFIGB:
                return read_port(p, (WORD)(portconfig[portnr].addr1 + 1));

        case IOCTL_EPPFLEX_WRITE_CONFIGB:
                return write_port(p, (WORD)(portconfig[portnr].addr1 + 1));

        case IOCTL_EPPFLEX_READ_EPPADDR:
                return read_port(p, (WORD)(portconfig[portnr].addr0 + 3));

        case IOCTL_EPPFLEX_WRITE_EPPADDR:
                return write_port(p, (WORD)(portconfig[portnr].addr0 + 3));

        case IOCTL_EPPFLEX_READ_EPPDATA:
                return read_port(p, (WORD)(portconfig[portnr].addr0 + 4));

        case IOCTL_EPPFLEX_WRITE_EPPDATA:
                return write_port(p, (WORD)(portconfig[portnr].addr0 + 4));

        case IOCTL_EPPFLEX_ACQUIREPORT:
                if (p->cbInBuffer < sizeof(unsigned int))
                        return ERROR_INVALID_PARAMETER;
                return acquireport(*((unsigned int *)p->lpvInBuffer));
                
        case IOCTL_EPPFLEX_RELEASEPORT:
                releaseport();
                return NO_ERROR;
     
        default:
                return ERROR_NOT_SUPPORTED;
        }
}

Generated by  Doxygen 1.6.0   Back to index