#include <stdio.h>
#include <dos.h>
#include <ctype.h>
#include <string.h>
#include "pcicall.h"

BYTE	*PCIname = "RAYONPCIOP";

#define	PACKPORT(card,port)	(WORD) ( ( card << 8 ) + port )

/* ************************************ */
/*        INT 14H PCI FUNATION          */
/* ************************************ */
      
INT	PciIopGetc(card, port) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Read a character from PCI port
*/
WORD    card;
WORD	port;
{       
 	union REGS regs;
        BYTE    c;

 	regs.h.ah = F_GETC;
 	regs.x.dx = PACKPORT(card, port);
 	int86(PCINT,&regs,&regs);
	c = regs.h.al;
	return (c);
}


INT	PciIopOpen(card, port, cflag, iflag) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Open a PCI port, and initialize some of its parameters.
*/
WORD	card;
WORD	port;
WORD	cflag;
WORD	iflag;
{
 	union REGS regs;

 	regs.h.ah = F_OPEN;
 	regs.x.bx = cflag;
 	regs.x.cx = iflag;
 	regs.x.dx = PACKPORT(card, port);
 	int86(PCINT,&regs,&regs);
	return(regs.x.ax);
}

   
INT	PciIopPutc(card, port, c) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Send one character to PCI port.
*/
WORD    card;
WORD	port;
BYTE	c;

{
 	union REGS regs;
        
 	regs.h.ah = F_PUTC;
 	regs.h.al = c;
 	regs.x.dx = PACKPORT(card, port);
 	int86(PCINT,&regs,&regs);
	return(regs.x.ax);
}

INT	PciIopRead(card, port, buffer, count) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Read characters from a PCI port to user buffer.
*	Returns Actually read byte count.
*/
WORD	card;
WORD    port;
BYTE	far *buffer;
INT	count;
{
 	union REGS regs;
	struct SREGS sregs;

        
	segread(&sregs);
 	regs.h.ah = F_READ;
 	regs.x.dx = PACKPORT(card, port);
 	regs.x.cx = count;
	sregs.es = FP_SEG(buffer);
	regs.x.bx = FP_OFF(buffer);
	int86x(PCINT, &regs, &regs, &sregs);
	return ( regs.x.ax );
}

INT	PciIopWrite(card, port, buffer, count) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Write characters in buffer to a specified serial port.
*	Returns Actually write byte count.
*/
WORD	card;
WORD	port;
BYTE	far *buffer;
INT	count;
{
 	union REGS regs;
	struct SREGS sregs;

	segread(&sregs);
 	regs.h.ah = F_WRITE;
 	regs.x.dx = PACKPORT(card, port);
	regs.x.cx = count;
	sregs.es = FP_SEG(buffer);
	regs.x.bx = FP_OFF(buffer);
	int86x(PCINT, &regs, &regs, &sregs);
	return ( regs.x.ax );
}




INT	PciIopDoqSpace(card, port) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Get available output queue space of PCI port.
*/
WORD	card;
WORD	port;
{
 	union REGS regs;

 	regs.h.ah = F_DOQSPC;
 	
 	regs.x.dx = PACKPORT(card, port);
 	int86(PCINT,&regs,&regs);
	return (regs.x.ax);
}

INT	PciIopDiqCount(card, port) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Get how many bytes in input queue of PCI port.
*/
WORD	card;
WORD	port;
{
 	union REGS regs;

 	regs.h.ah = F_DIQCNT;
 	regs.x.dx = PACKPORT(card, port);
 	int86(PCINT,&regs,&regs);
	return (regs.x.ax);
}

WORD	PciIopStatus(card, port) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Get port status
*/
WORD	card;
WORD	port;
{
 	union REGS regs;

 	regs.h.ah = F_STATUS;
 	regs.x.dx = PACKPORT(card, port);
 	int86(PCINT,&regs,&regs);
	return(regs.x.ax);
}

WORD	PciIopGetStatus(card, port) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Get LSR,MSR status
*/
WORD	card;
WORD	port;
{
 	union REGS regs;

 	regs.h.ah = F_GETSTATUS;
 	regs.x.dx = PACKPORT(card, port);
 	int86(PCINT,&regs,&regs);
	return(regs.x.ax);
}

INT	PciIopMaxCard() /*
~~~~~~~~~~~~~~~~~~~~~
*
*	Get how many cards on the main board.
*/
{
 	union REGS regs;

 	regs.h.ah = F_MAXCARD;
 	int86(PCINT,&regs,&regs);
	return(regs.x.ax);
}

INT	PciIopMaxPort(card) /*
~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Get the maximum ports of a PCI port.
*/
WORD	card;
{
 	union REGS regs;

 	regs.h.ah = F_MAXPORT;
 	regs.h.al = card & 0xFF;
 	int86(PCINT,&regs,&regs);
	return(regs.x.ax);
}

INT	PciIopResetDoq(card, port) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Reset the output queue of a specified port.
*/
WORD	card;
WORD	port;
{
 	union REGS regs;

 	regs.h.ah = F_RESETDOQ;
 	regs.x.dx = PACKPORT(card, port);
 	int86(PCINT,&regs,&regs);
	return(regs.x.ax);
}

INT	PciIopResetDiq(card, port) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Reset the input queue of a specified port.
*/
WORD	card;
WORD	port;
{
 	union REGS regs;

 	regs.h.ah = F_RESETDIQ;
 	regs.x.dx = PACKPORT(card, port);
 	int86(PCINT,&regs,&regs);
	return(regs.x.ax);
}

VOID	PciIopReset() /*
~~~~~~~~~~~~~~~~~~~~~
*
*	Restart PCI.
*/
{
 	union REGS regs;

 	regs.h.ah = F_RESETPCI;
 	int86(PCINT,&regs,&regs);
}

INT	PciIopSetDTR(card, port, flag) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Turn the DTR of a specified port ON or OFF.
*/
WORD	card;
WORD	port;
INT	flag;	/* 0 : turn off,  1 : turn on */
{
	union	REGS regs;

	regs.h.ah = F_DTR;
	regs.x.dx = PACKPORT(card, port);
	regs.h.al = (BYTE) flag;
	int86(PCINT, &regs, &regs);
	return(regs.x.ax);
}

INT	PciIopSetRTS(card, port, flag) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Turn the RTS of a specified port ON or OFF.
*/
WORD	card;
WORD	port;
INT	flag;	/* 0 : turn off,  1 : turn on */
{
	union	REGS regs;

	regs.h.ah = F_RTS;
	regs.x.dx = PACKPORT(card, port);
	regs.h.al = (BYTE) flag;
	int86(PCINT, &regs, &regs);
	return(regs.x.ax);
}


   
INT	PciIopClose(card,port) /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Close a specified serial port.
*/
WORD	card;
WORD	port;
{
 	union REGS regs;

 	regs.h.ah = F_CLOSE;
 	regs.x.dx = PACKPORT(card, port);
 	int86(PCINT,&regs,&regs);
	return(regs.x.ax);
}


INT	PciIopInstall() /*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*	Check to see if driver was installed.
*/
{
	union REGS regs;
	struct SREGS sregs;
	BYTE far *p;
	BYTE far *q;
	register INT	i;

	segread(&sregs);
	q = (BYTE far *) PCIname;
	regs.h.ah = 0x35;
	regs.h.al = F_INSTALL;
	int86x(DOSINT, &regs, &regs, &sregs);
	p = MK_FP(sregs.es, regs.x.bx);
	p -= 10;
	for (i = 0; i < 10; i++)
	{
		if ( *p++ != *q++ )
			return(FALSE);
	}
	return(TRUE);
}

