/******************************************************************************\
*  This is a part of the Advantech Source Code.
*  Copyright (C) 1997 Advantech Corporation.
*  All rights reserved.
*
*  PROGRAM: CAN1680.C -> PCI-1680 dos driver
*  PURPOSE: Device Functions subroutines.
*  FEXPORT FUNCTION:
*    canInitHW, can_reset, can0w, can1w, can0r, can1r, canReset,
*	 canConfig, canEnableRxInt, canNormalRun, canSendMsg,
*	 canSendMsgEx, canReceiveMsg, canReceiveMsgEx, find_1680,
*	 InitInterrupt, RestoreOldIsr, IrqHandler, canExitHW, canSetProtocolType

*  HISTORY:
*    2003/12/15 Created by jinzhong
\******************************************************************************/

#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <bios.h>
#include <process.h>

#include "amcc.h"
#include "CAN1680.h"
//#include "cant.h"
//#include "canp.c"
#include "amcclib.c"
//#include "fklib1.c"

#define IRQ_POLLING     0
#define IRQ_ENABLE		1
#define NULL            0
/*--------------------------------------------------------------------------*/
int RxIrq0=IRQ_POLLING, RxIrq1=IRQ_POLLING;
//BYTE old_irq0=IRQ_POLLING;
//BYTE old_irq1=IRQ_POLLING;
//UI   gSeg;
int hw_ok=0;
BYTE protocol1=CANBUS_PROTOCOL_20A;/*add by jinzhong*/
BYTE protocol2=CANBUS_PROTOCOL_20A;/*add by jinzhong*/
void   find_1680( word dev_id0, word index0 );
//dword  base_addr0;
//dword  base_addr1;
dword  module;
//dword  giIrqNum;

/***************************
 *For PCI interrupt initial*
 **************************/
void	interrupt IrqHandler(void);
byte	InitInterrupt( int iIrqNum,void	interrupt (*pIsrHandler)(),void	interrupt (**pOldIsr)() );
void	RestoreOldIsr(int iIrqNum, byte ucIrqMask, void interrupt (*pOldIsr)() );


//void interrupt (*old_isr)();

void	interrupt (*pOldIsr)(void);
//void interrupt can_isr0();
//void interrupt can_isr1();

int can_err_no;
        /*------------------------------------------------
        0: no error
        0x01 : hardware not release.
        0x10: seg_addr set error
        0x11: hardware not set successful
        0x12: irq_no set error
        0x20: bus off
        ------------------------------------------------*/
/*--------------------------------------------------------------------------*/
//void interrupt can_isr0();
//void interrupt can_isr1();
void can0w(BYTE addr, BYTE v);
void can1w(BYTE addr, BYTE v);
BYTE can0r( BYTE addr);
BYTE can1r( BYTE addr);
void  can_reset( BYTE port );
/*--------------------------------------------------------------------------*/
/*void getIntNo(BYTE irq_no, BYTE * int_no)
{
  BYTE int_tbl[16]={
  0xff,0xff,0xff,0x0b,0x0c,0x0d,0x0e,0x0f,
  0xff,0x71,0x72,0x73,0x74,0xff,0xff,0x77
  };
  *int_no = int_tbl[irq_no];
}
*/
  byte	ucIrqMask;
  CAN_RD_FIFO_T READ_FIFO0,READ_FIFO1;
  CAN_RD_FIFO_EX_T  READ_FIFO_EX0,READ_FIFO_EX1;
/*--------------------------------------------------------------------------*/
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  // Function    :int canInitHW(void);
  //
  // Parameter          Description
  // ----------------------------------------------------------------------------
  // none
  //
  // Function Description
  //    * find 1680 card
  //	* reset the card
  //    * connect interrupt
  // 
  // Returns
  //    Returns 1 if successful. If unsuccessful, returns 0.
/*-------------------------------------------------------------*/ 
int canInitHW(void)
{
  BYTE data;

  find_1680(0x1680,0);
  clrscr();
  if( module!=0x1680 )
  {
  
      printf("Can not found PCI-1680UP found PCI-%lx",module);
      //IfError=1;
      getch();
      exit(1);
  }
 printf("Module PCI-%lx\n",module);
 printf("base_addr0=can1=%lx\n",base_addr0);
 printf("base_addr1=can2=%lx\n",base_addr1);
 printf("Interrupt =%d\n",giIrqNum);
  data=can0r(0);
  if( data &0x01)
  {
    can0w(0,0x20);
    if(can0r(0) &0x01)
    {
      can_err_no=0x10;
      return(0);
    }
  }
  can_reset(0);
  if(!(can0r(0) &0x01))
  {
      can_err_no=0x10;
      return(0);
  }
  //can0w(0,0x21);
  
  data=can1r(0);
  if( data &0x01)
  {
    can1w(0,0x20);
    if(can1r(0) &0x01)
    {
      can_err_no=0x10;
      return(0);
    }
  }
  //can1w(0,0x21);
  can_reset(1);
  if(!(can0r(1) &0x01))
  {
      can_err_no=0x10;
      return(0);
  }

  ucIrqMask = InitInterrupt(giIrqNum, IrqHandler, &pOldIsr);
  hw_ok=1;
  return(1);
}

/*--------------------------------------------------------------------------*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function    :void  can_reset( BYTE port );
//
// Parameter          Description
// ----------------------------------------------------------------------------
// Port   (IN)       Port Index
//
// Function Description
//    * reset the card 
//    * initiate the receive FIFO
// 
// Returns
//   none
/*--------------------------------------------------------*/
void  can_reset( BYTE port )
{
        if (port==0)
        outportb(base_addr2+0,0x00);
        if (port==1)
        outportb(base_addr2+1,0x00);
		if(port==0)
		{
			READ_FIFO0.head = READ_FIFO0.tail = 0;
			READ_FIFO0.status = FIFO_OK;
			READ_FIFO_EX0.head=READ_FIFO_EX0.tail = 0;
			READ_FIFO_EX0.status = FIFO_OK;
		}
		else
		{
			READ_FIFO1.head = READ_FIFO1.tail = 0;
			READ_FIFO1.status = FIFO_OK;
			READ_FIFO_EX1.head=READ_FIFO_EX1.tail = 0;
			READ_FIFO_EX1.status = FIFO_OK;
		}
//		delay(100);
	delay(100);
}
/*--------------------------------------------------------------------------*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function    :can0w; can1w; can0r; can1r;
//
// Parameter          Description
// ----------------------------------------------------------------------------
// port   (IN)       Port Index
//
// Function Description
//    * read or write a byte from the card offset address 

// 
// Returns
//    none
/*-----------------------------------------------------------------*/
void can0w(BYTE addr, BYTE v)
{
	outportb(base_addr0+addr,v);
}
/*--------------------------------------------------------------------------*/
void can1w(BYTE addr, BYTE v)
{
	outportb(base_addr1+addr,v);
}
/*--------------------------------------------------------------------------*/
BYTE can0r( BYTE addr)
{
  BYTE v;
	v=inportb(base_addr0+addr);
	return(v);
}
/*--------------------------------------------------------------------------*/
BYTE can1r( BYTE addr)
{
  BYTE v;
	v=inportb(base_addr1+addr);
	return(v);
}
/*--------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------*/
//function purpose: reset the card
int  canReset( BYTE port )
{
  can_reset( port );
  return 1;
}
/*--------------------------------------------------------------------------*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function    :int  canConfig( BYTE port, CAN_STRUCT can);
//
// Parameter          Description
// ----------------------------------------------------------------------------
// port   (IN)       Port Index
// can				 can port attribute
//	typedef struct {
//	BYTE acc_code;
//	BYTE acc_mask;
//	BYTE bt0;
//	BYTE bt1;
//	BYTE protocoltype;/*add by jinzhong*/
//	PT_FilterSetting  ssFilterSetting;
//	}CAN_STRUCT;
// Function Description
//    * initiate the Port  
// Returns
//    Returns 1 if successful. If unsuccessful, returns 0.
/*-------------------------------------------------------------*/
int  canConfig( BYTE port, CAN_STRUCT can)
{
  BYTE temp,v;
 // canReset( port );
  if( port ==0)
	  can.protocoltype=protocol1;
  else can.protocoltype=protocol2;
  if(can.protocoltype==CANBUS_PROTOCOL_20A)
  {
	  if( port==0)
	  {
		  //set protocol 2.0A
		  can0w(0,1);
		  v=can0r(0x100);
		  can0w(0x100,v);
		  can0w(0,1);
		  delay(100);
		  v=can0r(31);
		  v &=0x7f;
		  can0w(31,v);
		  delay(100);
	  }
	  else
	  {
		  can1w(0,1);
		  v=can1r(0x100);
		  can1w(0x100,v);
		  can1w(0,1);
		  delay(100);
		  v=can1r(31);
		  v &=0x7f;
		  can1w(31,v);
		  delay(100);
	  }
	if( port ==0)
	{
     can0w(0,1);/* reset mode and disable receive irq */
	}
	else
	{
     can1w(0,1);/* reset mode and disable receive irq */
	}
	if( port ==0)
	{
     can0w(6,can.bt0); /* BT0 */
     can0w(7,can.bt1); /* BT1 */
     temp=can0r(6);
     if( temp !=can.bt0)
       return(0);
     temp=can0r(7);
     if( temp !=can.bt1)
       return(0);
	}
	else
	{
     can1w(6,can.bt0); /* BT0 */
     can1w(7,can.bt1); /* BT1 */
     temp=can1r(6);
     if( temp !=can.bt0)
       return(0);
     temp=can1r(7);
     if( temp !=can.bt1)
       return(0);
	}
	if( port ==0)
	{
     can0w(4,can.acc_code);/* accept code */
     can0w(5,can.acc_mask);/* accept code */
	}
	else
	{
     can1w(4,can.acc_code);/* accept code */
     can1w(5,can.acc_mask);/* accept code */
	}
	if( port ==0)
	{
     can0w(8,0xfa);
	}
	else
	{
     can1w(8,0xfa);
	}
	return(1);
  }
  if(can.protocoltype==CANBUS_PROTOCOL_20B)
  {
	  if (port==0)
	  {
		  //set protocol 2.0B
		  can0w(0,1);
		  v=can0r(0x100);
		  can0w(0x100,v);
		  delay(100);
		  can0w(0,1);
		  delay(100);/*important! wait for the card to change protocol  */
		  v=can0r(31);
		  v |=0x80;
		  can0w(31,v);


	  }
	  else
	  {
		  can1w(0,1);
		  v=can1r(0x100);
		  can1w(0x100,v);
		  delay(100);
		  can1w(0,1);
		  delay(100);
		  v=can1r(31);
		  v |=0x80;
		  can1w(31,v);



	  }

	  if( port ==0)
	  {
		  //mask receive interrupt
		  v=can0r(4);
		  v &=0xfe;
		  can0w(4,v);
	  }
	  else
	  {
		  v=can1r(4);
		  v &=0xfe;
		  can1w(4,v);
	  }
	  if( port ==0)
	  {
		  can0w(6,can.bt0); /* BT0 */
		  can0w(7,can.bt1); /* BT1 */
		  temp=can0r(6);
		  if( temp !=can.bt0)
			  return(0);
		  temp=can0r(7);
		  if( temp !=can.bt1)
			  return(0);
	  }
	  else
	  {
		  can1w(6,can.bt0); /* BT0 */
		  can1w(7,can.bt1); /* BT1 */
		  temp=can1r(6);
		  if( temp !=can.bt0)
			  return(0);
		  temp=can1r(7);
		  if( temp !=can.bt1)
			  return(0);
	  }

	  if( port ==0)
	  {
		  v       = can0r( 0 );
		  if ( can.ssFilterSetting.dwFilterType == 0 )
		  {
			 v |= 0x08;
		  }
		  else
		  {
			  v &= 0xf7;
		  }
		  can0w(0, v);
		 // delay(200);
		  can0w(16,can.ssFilterSetting.uchAcceptCode0);/* accept code */
		  can0w(17,can.ssFilterSetting.uchAcceptCode1);/* accept code */
		  can0w(18,can.ssFilterSetting.uchAcceptCode2);/* accept code */
		  can0w(19,can.ssFilterSetting.uchAcceptCode3);/* accept code */
		  can0w(20,can.ssFilterSetting.uchAcceptMask0);/* accept mask */
		  can0w(21,can.ssFilterSetting.uchAcceptMask1);/* accept mask */
		  can0w(22,can.ssFilterSetting.uchAcceptMask2);/* accept mask */
		  can0w(23,can.ssFilterSetting.uchAcceptMask3);/* accept mask */

	  }
	  else
	  {
		  v       = can1r( 0 );
		  if ( can.ssFilterSetting.dwFilterType == 0 )
		  {
			  v |= 0x08;
		  }
		  else
		  {
			  v &= 0xf7;
		  }
		  can1w(0, v);
		  //delay(200);
		  //tag=can1r(0);
		  can1w(16,can.ssFilterSetting.uchAcceptCode0);/* accept code */
		  //tag=can1r(16);
		  can1w(17,can.ssFilterSetting.uchAcceptCode1);/* accept code */
		  //tag=can1r(17);
		  can1w(18,can.ssFilterSetting.uchAcceptCode2);/* accept code */
		  can1w(19,can.ssFilterSetting.uchAcceptCode3);/* accept code */
		  can1w(20,can.ssFilterSetting.uchAcceptMask0);/* accept mask */
		  can1w(21,can.ssFilterSetting.uchAcceptMask1);/* accept mask */
		  can1w(22,can.ssFilterSetting.uchAcceptMask2);/* accept mask */
		  can1w(23,can.ssFilterSetting.uchAcceptMask3);/* accept mask */

	  }
	  if( port ==0)
	  {
		  can0w(8,0xfa);
	  }
	  else
	  {
		  can1w(8,0xfa);
	  }
	  return(1);
  }
}
/*-------------------------------------------------------------*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function    :int canEnableRxInt(BYTE port);
//
// Parameter          Description
// ----------------------------------------------------------------------------
// port   (IN)       Port Index
//
// Function Description
//    * enable receive interrupt
// 
// Returns
//    Returns 1 if successful. If unsuccessful, returns 0.
// 
int canEnableRxInt(BYTE port)
{
	BYTE v;
	if(port==0)
	{
		if(protocol1==CANBUS_PROTOCOL_20A)
		{
			v=can0r(0);
			v |=0x02;
			can0w(0,v);/* reset mode and receive irq */
			RxIrq0=IRQ_ENABLE;
			return 1;
		}
		else
		{
			v=can0r(4);
			v |=0x09;
			can0w(4,v);/* reset mode and receive irq */
			RxIrq0=IRQ_ENABLE;
			return 1;
		}
	}
	if(port==1)
	{
		if(protocol2==CANBUS_PROTOCOL_20A)
		{
			v=can1r(0);
			v |=0x02;
			can1w(0,v);/* reset mode and receive irq */
			RxIrq1=IRQ_ENABLE;
			return 1;
		}
		else 
		{
			v=can1r(4);
			v |=0x09;
			can1w(4,v);/* reset mode and receive irq */
			RxIrq1=IRQ_ENABLE;
			return 1;
		}
	}
	return 0;
}
/*--------------------------------------------------------------------------*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function    :int  canNormalRun( BYTE port );
//
// Parameter          Description
// ----------------------------------------------------------------------------
// port   (IN)       Port Index
//
// Function Description
//    * make the card run in normal mode 
// 
// Returns
//    Returns 1 if successful. If unsuccessful, returns 0.
// 
int  canNormalRun( BYTE port )
{
BYTE v;
  if( port ==0)
  {
        v=can0r(0);
        if( v & 1)
          can0w(0,v&0xfe);
		return 1;
  }
  else
  {
        v=can1r(0);
        if( v & 1)
          can1w(0,v&0xfe);
		return 1;
  }
  return 0;
}
/*--------------------------------------------------------------------------*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function    :int canSendMsg( BYTE  port, MSG_STRUCT msg);
//
// Parameter          Description
// ----------------------------------------------------------------------------
// port   (IN)       Port Index
// msg	  (IN)       sending data
// Function Description
//    * send 20a message to can bus 
// 
// Returns
//    Returns 1 if successful. If unsuccessful, returns 0.
// 
int canSendMsg( BYTE  port, MSG_STRUCT msg)
{
  BYTE v;
  BYTE i;

  if( port==0)
  {
    v=msg.id>>3;
    can0w(10,v);
    v=msg.id &7;
    v<<=5;
    if( msg.rtr ==1)
      v|=0x10;
      v+=msg.dlen;
    can0w(11,v);
    for(i=0;i<msg.dlen; i++)
    {
      can0w(12+i,msg.data[i]);
    }
    can0w(1,1);
    while(1)
    {
      v=can0r(2);
      if( v & 0x40)
      {
        return( 0);
      }
      if( v &0x08)
        return( 1);
    }
  }
  else
  {
    v=msg.id>>3;
    can1w(10,v);
    v=msg.id &7;
    v<<=5;
    if( msg.rtr ==1)
      v|=0x10;
      v+=msg.dlen;
    can1w(11,v);
    for(i=0;i<msg.dlen; i++)
    {
      can1w(12+i,msg.data[i]);
    }
    can1w(1,1);
    while(1)
    {
      v=can1r(2);
      if( v & 0x40)
      {
        return( 0);
      }
      if( v &0x08)
        return( 1);
    }
  }
}
/*---------------------------------------------*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function    :int canSendMsgEx( BYTE  port, CAN_MSG_T_EX msgex);
//
// Parameter          Description
// ----------------------------------------------------------------------------
// port   (IN)       Port Index
// msgex  (IN)		 sending data
// Function Description
//    send 20b message to the can bus
// Returns
//    Returns 1 if successful. If unsuccessful, returns 0.
// 
int canSendMsgEx( BYTE  port, CAN_MSG_T_EX msgex)
{
	UL v,temp1,temp2;
	BYTE i;
	
	if( port==0)
	{
		temp1=can0r(2);
		if(temp1 & 0x04)
		{
			if( msgex.ff==PELICAN_SFF)
			{
				temp1=0;
				temp1 |=msgex.dlen;
				if ( msgex.rtr == 1 )
				{
					temp1 |= 1<<6;
				}
				can0w(16,temp1);
				temp1 = 0;
				temp1 = msgex.id>>3;
				can0w(17,temp1);
				temp1 = 0;
				temp1 =  msgex.id & 0x07 ;
				temp1 <<= 5;
				can0w(18,temp1);
				for(i=0;i<msgex.dlen; i++)
				{
					can0w(19+i,msgex.data[i]);
				}
			}
			else
			{
				temp1 = 0;
				temp1 |= msgex.dlen;
				if ( msgex.rtr == 1 )
				{
					temp1 |= 1<<6;
				}
				temp1 |= 1<<7;
				can0w(16,temp1);
				temp1 = msgex.id>>21;
				can0w(17,temp1);
				temp1 =  msgex.id & 0x1fffff ;
				temp1 >>= 13;
				can0w(18,temp1);
				temp1 =  msgex.id & 0x1fff ;
				temp1 >>= 5;
				can0w(19,temp1);
				temp1 =  msgex.id & 0x1f ;
				temp1 <<= 3;
				can0w(20,temp1);
				for(i=0;i<msgex.dlen; i++)
				{
					can0w(21+i,msgex.data[i]);
				}
			}
			can0w(1,1);
			while(1)
			{
				temp1=can0r(2);
				if( temp1 & 0x40)
				{
					return( 0);
				}
				if( temp1 &0x08)
					return( 1);
			}
		}
		else return(0);
	}
	else
	{
		temp2=can1r(2);
		if(temp2 & 0x04)
		{
			if( msgex.ff==PELICAN_SFF)
			{
				temp2=0;
				temp2 |=msgex.dlen;
				if ( msgex.rtr == 1 )
				{
					temp2 |= 1<<6;
				}
				can1w(16,temp2);
				temp2 = 0;
				temp2 = msgex.id>>3;
				can1w(17,temp2);
				temp2 = 0;
				temp2 =  msgex.id & 0x07 ;
				temp2 <<= 5;
				can1w(18,temp2);
				for(i=0;i<msgex.dlen; i++)
				{
					can1w(19+i,msgex.data[i]);
				}
			}
			else
			{
				temp2 = 0;
				temp2 |= msgex.dlen;
				if ( msgex.rtr == 1 )
				{
					temp2 |= 1<<6;
				}
				temp2 |= 1<<7;
				can1w(16,temp2);
				temp2 = msgex.id>>21;
				can1w(17,temp2);
				temp2 =  msgex.id & 0x1fffff ;
				temp2 >>= 13;
				can1w(18,temp2);
				temp2 =  msgex.id & 0x1fff ;
				temp2 >>= 5;
				can1w(19,temp2);
				temp2 =  msgex.id & 0x1f ;
				temp2 <<= 3;
				can1w(20,temp2);
				for(i=0;i<msgex.dlen; i++)
				{
					can1w(21+i,msgex.data[i]);
				}
			}
			can1w(1,1);
			while(1)
			{
				temp2=can1r(2);
				if( temp2 & 0x40)
				{
					return( 0);
				}
				if( temp2 &0x08)
					return( 1);
			}
		}
		else return(0);
	}
}
/*--------------------------------------------------------------------------*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function    :int  canReceiveMsg( BYTE port, MSG_STRUCT *msg_ptr,BYTE * IsEmpty);
//
// Parameter          Description
// ----------------------------------------------------------------------------
// port   (IN)       Port Index
// msg_ptr (OUT)	 point to receive buffer
// IsEmpty (OUT)	 notify whether there are data in receive buffer.
// Function Description
//    * receive 20a data
// Returns
//    Returns 1 if successful. If unsuccessful, returns 0.
/*-----------------------------------------------------------------*/
int  canReceiveMsg( BYTE port, MSG_STRUCT *msg_ptr,BYTE * IsEmpty)
{
  BYTE i;
  MSG_STRUCT * pcan_msg;
  MSG_STRUCT msg;
  ULONG head,tail;
  *IsEmpty = 0;
   if( port ==0)
   {
	   if(RxIrq0==IRQ_POLLING)
	   {
		   if( can0r(2)&1)
		   {
			   rBuf0[0]=can0r(20);
			   rBuf0[1]=can0r(21);
			   for(i=0; i< (rBuf0[1]&0x0f); i++)
				   rBuf0[i+2]=can0r(22+i);
			   /* release receive buffer*/
			   can0w(1,4);
			   msg_ptr->id=rBuf0[0];
			   msg_ptr->id <<=3;
			   msg_ptr->id |=(rBuf0[1] >>5);
			   msg_ptr->rtr =(rBuf0[1]>>4)&1;
			   msg_ptr->dlen =rBuf0[1]&0x0f;
			   for(i=0;i< msg_ptr->dlen; i++)
				   msg_ptr->data[i]=rBuf0[2+i];
			   *IsEmpty = 1;
			   return(1);
		   }
		   else
			   return(0);
	   }
	   else if(RxIrq0==IRQ_ENABLE)
	   {
		  if( gRecFlag0 == 1)
		  {
			  head = READ_FIFO0.head;
			  tail = READ_FIFO0.tail;
			  if(head == tail)
				  return(0);
			  pcan_msg= (MSG_STRUCT *)&READ_FIFO0.buffer[tail];
			  READ_FIFO0.tail += CAN_MSG_LEN;
			  if(READ_FIFO0.tail == RD_FIFO_LEN )
			  {
				  READ_FIFO0.tail %= RD_FIFO_LEN;
				  READ_FIFO0.status = FIFO_OK;
			  }
			  if(READ_FIFO0.tail == head )
				  *IsEmpty = 1;
			  else
				  *IsEmpty = 0;
			  msg = *pcan_msg;
			  *((MSG_STRUCT *)msg_ptr) = msg;
			  return(1);
		  }
	   }
      else
	  {
		  *IsEmpty = 0;
		  return( 0);
      }

   }
   else if(port ==1)
   {
	   if( RxIrq1 == IRQ_POLLING)
	   {
		   if( can1r(2)&1)
		   {
			   rBuf1[0]=can1r(20);
			   rBuf1[1]=can1r(21);
			   for(i=0; i< ( rBuf1[1]&0x0f); i++)
				   rBuf1[i+2]=can1r(22+i);
			   can1w(1,4);
			   msg_ptr->id=rBuf1[0];
			   msg_ptr->id <<=3;
			   msg_ptr->id |=(rBuf1[1] >>5);
			   msg_ptr->rtr =(rBuf1[1]>>4)&1;
			   msg_ptr->dlen =rBuf1[1]&0x0f;
			   for(i=0;i< msg_ptr->dlen; i++)
				   msg_ptr->data[i]=rBuf1[2+i];
			   *IsEmpty = 1;
			   return(1);
		   }
		   else
			   return(0);
	   }
	   else if(RxIrq1 == IRQ_ENABLE)
	   {
		  if( gRecFlag1 == 1)
		  {
			  head = READ_FIFO1.head;
			  tail = READ_FIFO1.tail;
			  if(head == tail)
				  return(0);
			  pcan_msg= (MSG_STRUCT *)&READ_FIFO1.buffer[tail];
			  READ_FIFO1.tail += CAN_MSG_LEN;
			  if(READ_FIFO1.tail == RD_FIFO_LEN )
			  {
				  READ_FIFO1.tail %= RD_FIFO_LEN;
				  READ_FIFO1.status = FIFO_OK;
			  }
			  if(READ_FIFO1.tail == head )
				  *IsEmpty = 1;
			  else
				  *IsEmpty = 0;
			  msg = *pcan_msg;
			  *((MSG_STRUCT *)msg_ptr) = msg;
			  return(1);
		  }
	   }
	  else{
		  *IsEmpty = 0;
		  return( 0);
      }
   }
   else
     return( 0);
}
/*---------------------------------------------*/
/*--------------------------------------------------------------------------*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function    :int  canReceiveMsg( BYTE port, CAN_MSG_T_EX *msg_ptrex,BYTE * IsEmpty);
//
// Parameter          Description
// ----------------------------------------------------------------------------
// port   (IN)       Port Index
// msg_ptrex (OUT)	 point to receive buffer
// IsEmpty (OUT)	 notify whether there are data in receive buffer.
// Function Description
//    * receive 20b data
// Returns
//    Returns 1 if successful. If unsuccessful, returns 0.
/*-----------------------------------------------------------------*/
int  canReceiveMsgEx( BYTE port, CAN_MSG_T_EX *msg_ptrex, BYTE * IsEmpty)
{
   BYTE i;
   PCAN_MSG_T_EX pcan_msgex;
   CAN_MSG_T_EX msgex;
   ULONG head,tail;
   ULONG temp1,temp2;
   unsigned int tag1;
   *IsEmpty = 1;
   if( port == 0)
   {
	   if( RxIrq0 == IRQ_POLLING)
	   {
		   if( can0r(2)&1)
		   {

			   temp1=can0r(16);
			   msg_ptrex->ff   =  temp1 & 0x80 ;
			   msg_ptrex->dlen =  temp1 & 0x0f ;
			   msg_ptrex->rtr  = ( temp1>> 6) & 1;
			   if ( msg_ptrex->ff == PELICAN_SFF )
			   {
				   temp1 = can0r(17);
				   msg_ptrex->id = temp1 << 3;
				   temp1 = can0r(18);
				   msg_ptrex->id |= temp1 >> 5;
				   for ( i = 0; i < msg_ptrex->dlen; i++ )
					   msg_ptrex->data[i] =  can0r(19+i);

			   }
			   else
			   {
				   temp1 = can0r(17);
				   msg_ptrex->id = temp1 << 21;
				   temp1 = can0r(18);
				   msg_ptrex->id |= temp1 << 13;
				   temp1 = can0r(19);
				   msg_ptrex->id |= temp1 << 5;
				   temp1 = can0r(20);
				   msg_ptrex->id |= temp1 >> 3;
				   for ( i = 0; i < msg_ptrex->dlen; i++ )
					   msg_ptrex->data[i] =  can0r(21+i);
			   }

			   /* release receive buffer*/
			   can0w(1,4);
			   return(1);
		   }
		   else
			   return(0);
	   }
	   else
	   {
         head = READ_FIFO_EX0.head;
         tail = READ_FIFO_EX0.tail;
         if(head == tail)
         return(0);
         pcan_msgex= (CAN_MSG_T_EX *)&READ_FIFO_EX0.buffer[tail];
         READ_FIFO_EX0.tail += CAN_MSG_EX_LEN;
         if(READ_FIFO_EX0.tail == RD_FIFO_EX_LEN )
         {
            READ_FIFO_EX0.tail %= RD_FIFO_EX_LEN;
            READ_FIFO_EX0.status = FIFO_OK;
         }
         if(READ_FIFO_EX0.tail == head )
            *IsEmpty = 1;
         else
            *IsEmpty = 0;
         msgex = *pcan_msgex;
         *((CAN_MSG_T_EX *)msg_ptrex) = msgex;
         return(1);
	   }
      
   }
   else if(port == 1)
   {
	   if( RxIrq1 == IRQ_POLLING)
	   {
		   tag1 = can1r(0);
		   if(tag1&1)
			   return 0;
		   tag1 = can1r(2);
		   if( can1r(2)&1)
		   {
			   temp2=can1r(16);
			   msg_ptrex->ff   =  temp2 & 0x80 ;
			   msg_ptrex->dlen =  temp2 & 0x0f ;
			   msg_ptrex->rtr  = ( temp2 >> 6) & 1;
			   if ( msg_ptrex->ff == PELICAN_SFF )
			   {
				   temp2 = can1r(17);
				   msg_ptrex->id = temp2 << 3;
				   temp2 = can1r(18);
				   msg_ptrex->id |= temp2 >> 5;
				   for ( i = 0; i < msg_ptrex->dlen; i++ )
					   msg_ptrex->data[i] =  can1r(19+i);
				   
			   }
			   else
			   {
				   temp2 = can1r(17);
				   msg_ptrex->id = temp2 << 21;
				   temp2 = can1r(18);
				   msg_ptrex->id |= temp2 << 13;
				   temp2 = can1r(19);
				   msg_ptrex->id |= temp2 << 5;
				   temp2 = can1r(20);
				   msg_ptrex->id |= temp2 >> 3;
				   for ( i = 0; i < msg_ptrex->dlen; i++ )
					   msg_ptrex->data[i] =  can1r(21+i);
			   }
			   
			   /* release receive buffer*/
			   can1w(1,4);
			   return(1);
		   }
		   else
			   return(0);
	   }
	   else
	   {
         head = READ_FIFO_EX1.head;
         tail = READ_FIFO_EX1.tail;
         if(head == tail)
         return(0);
		 pcan_msgex= (CAN_MSG_T_EX *)&READ_FIFO_EX1.buffer[tail];
         READ_FIFO_EX1.tail += CAN_MSG_EX_LEN;
         if(READ_FIFO_EX1.tail == RD_FIFO_EX_LEN )
         {
            READ_FIFO_EX1.tail %= RD_FIFO_EX_LEN;
            READ_FIFO_EX1.status = FIFO_OK;
         }
         if(READ_FIFO_EX1.tail == head )
            *IsEmpty = 1;
         else
            *IsEmpty = 0;
         msgex = *pcan_msgex;
         *((CAN_MSG_T_EX *)msg_ptrex) = msgex;
         return(1);
	   }
    
   }
   else
     return( 0);
}
/*---------------------------------------------*/

void find_1680( word dev_id0, word index0 )
{
	byte bus_num, dev_fun_num, reg_num, pci_register[64];
	word ven_id, dev_id, index;
	unsigned long config_data[32], PLX_reg[16];
	unsigned long ad_data[512],ch_range[15],mux;
	unsigned int  dh, dl, itemp , channel;
	int err_code, i,x,y ;

	ven_id = 0x13fe;
    	dev_id = dev_id0;
    	index = index0;

	clrscr();
	err_code = find_pci_device(dev_id, ven_id, index, &bus_num, &dev_fun_num);
	if ( !err_code )
	     	printf("Find PCI-1680UP at Bus No.= %d Device No.= %d Function No. = %d\n",
				       bus_num,dev_fun_num>>3,dev_fun_num&0x07);
	else {
		printf("Can not find any PCI-1680UP ! \n");
		getch();
		exit(0);
	}
	for ( i=0;i<16;i++ ) {
	  err_code = read_configuration_dword(bus_num, dev_fun_num, i*4, &config_data[i]);
	  printf("PCI control register %02X = %08lx\n",i*4,config_data[i]);
	}
	printf("\nPress any key to continue !");
	clrscr();
	err_code = read_configuration_dword(bus_num, dev_fun_num, PCI_CS_BASE_ADDRESS_2, &base_addr0);
 /************************** Get Base address **********************/
	if ( !err_code ) {
			if( base_addr0 & 0x01 ) {
				base_addr0 &= 0xfffffffc;
				printf("\nPCI-1680UP I/O base_addr0=%lx  ",base_addr0);
			}
			else    {
				base_addr0 &= 0xfffffff0;
				printf("\nPCI-1680UP MEMORY base_addr0=%lx  ",base_addr0);
			}
	}
        err_code = read_configuration_dword(bus_num, dev_fun_num, PCI_CS_BASE_ADDRESS_3, &base_addr1);
 /************************** Get Base address **********************/
	if ( !err_code ) {
			if( base_addr1 & 0x01 ) {
				base_addr1 &= 0xfffffffc;
				printf("\nPCI-1680UP I/O base_addr1=%lx  ",base_addr1);
			}
			else    {
				base_addr1 &= 0xfffffff0;
				printf("\nPCI-1680UP MEMORY base_addr1=%lx  ",base_addr1);
			}
	}

        err_code = read_configuration_dword(bus_num, dev_fun_num, PCI_CS_BASE_ADDRESS_4, &base_addr2);
 /************************** Get Base address **********************/
	if ( !err_code ) {
			if( base_addr2 & 0x01 ) {
				base_addr2 &= 0xfffffffc;
				printf("\nPCI-1680UP I/O base_addr2=%lx  ",base_addr2);
			}
			else    {
				base_addr2 &= 0xfffffff0;
				printf("\nPCI-1680UP MEMORY base_addr2=%lx  ",base_addr2);
			}
	}

        err_code = read_configuration_dword(bus_num, dev_fun_num, PCI_CS_INTERRUPT_LINE , &giIrqNum );
 /************************** Get Base address **********************/
				giIrqNum &= 0x000000ff;
 			        printf("\nPCI INTERRUPT %d  ",giIrqNum);

	err_code = read_configuration_word(bus_num, dev_fun_num, 0x02 , &module );
 /************************** Get Base address **********************/
				module &= 0x0000ffff;
 			        printf("\nModule Name PCI-%lx  ",module);
        clrscr();
}

/************************************************************************
 * Function:  Init ISR to handle device generated IRQ
 * Paramater: iIrqNum, IN, IRQ number.
 *            pIsrHandler,IN, ISR handler for installation.
 *            pOldIsr, OUT, Old ISR routine.
 * return:    IRQ mask
 ************************************************************************/
byte InitInterrupt( int iIrqNum,
                    void interrupt (*pIsrHandler)(),
                    void interrupt (**pOldIsr)() )
{
   byte ucIrqMask, ucTotalMask;

	//
   // 1. DISABLE PC INTERRUPT
   //
   disable();

   //
   // 2. STORE OLD INT. HANDLER */
	//
   if ( iIrqNum < 8 )
		*pOldIsr = getvect(iIrqNum+8);
	else
		*pOldIsr = getvect(iIrqNum-8+0x70);

	//
   // 3. SET INTERRUPT  VECTOR
   //
   if(iIrqNum < 8)
      setvect(iIrqNum+8, pIsrHandler);
   else
      setvect(iIrqNum-8+0x70, pIsrHandler);

   //
   // 4. ENABLE 8259 INT. MASK
	//
   if(iIrqNum < 8)
   {
		ucTotalMask = inportb(0x21);	//Interrupt controller
		ucIrqMask = ucTotalMask & (0x01<<iIrqNum);
      outportb(0x21, ucTotalMask & ~(0x01<<iIrqNum) );
   }
   else
   {
      ucTotalMask = inportb(0xa1);
      ucIrqMask = ucTotalMask & ~(0x01 << (iIrqNum-8));
      outportb(0xa1, ucTotalMask & ~(0x01<<(iIrqNum-8)));
   }

	//
   // 5. ENABLE  PC INTERRUPT
   //
   enable();
   return(ucIrqMask);
}//InitInterrupt

/**************************************************************
 * Function:  Restore system ISR.
 * Paramater: iIrqNum, IN, IRQ number
 *            ucIrqMask, IN, IRQ mask before install ISR
 *            pOldIsr, IN, Old ISR. restore it as service routine.
 *
 **************************************************************/
void RestoreOldIsr( int iIrqNum,byte ucIrqMask,void interrupt (*pOldIsr)() )
{
    byte ucTotalMask;
    disable();
    if ( iIrqNum < 8 )
    {
        ucTotalMask = (inportb(0x21) & ~(0x01<<iIrqNum)) | ucIrqMask;
        outportb(0x21, ucTotalMask);
        setvect(iIrqNum+8, pOldIsr);
    }
    else
    {
        ucTotalMask = (inportb(0xa0) & ~(0x01<<(iIrqNum-8))) | ucIrqMask;
        outportb(0xa1, ucTotalMask);
		  setvect(iIrqNum-8+0x70, pOldIsr);
	 }
	 enable();
}

/**************************************************************
 * Function : IrqHandler
 *            Interrupt service routine for PCI-1753 DI interrupt.
 *            fucntion.
 **************************************************************/
void interrupt IrqHandler(void)
{
	unsigned char flag;
	ULONG head,temp1,temp2;
	int i;
	MSG_STRUCT  * pcan_msg;
	PCAN_MSG_T_EX pcan_msgex;

    disable();
    flag=can0r(3); /* port0 interrupt */
    if( flag & 1) /* RIF */
    {
	  if(protocol1==CANBUS_PROTOCOL_20A)
	  {
	  	head = READ_FIFO0.head;
		pcan_msg= (MSG_STRUCT *)&READ_FIFO0.buffer[head];
		temp1=can0r(20);
		temp2=can0r(21);
		pcan_msg->id = temp1;
		pcan_msg->id <<= 3;
		pcan_msg->id |= temp2>>5;
		pcan_msg->rtr = (temp2>>4)&1;
		pcan_msg->dlen = temp2&0x0f;
		for(i=0; i< pcan_msg->dlen; i++)
			pcan_msg->data[i]=can0r(22+i);
		for(i=pcan_msg->dlen; i < 8; i++ )
			pcan_msg->data[i] = 0;
		READ_FIFO0.head += CAN_MSG_LEN;
		if(READ_FIFO0.head == RD_FIFO_LEN )
		{
			READ_FIFO0.status = FIFO_FULL;
			READ_FIFO0.head %= RD_FIFO_LEN;
		}
		if(READ_FIFO0.status == FIFO_FULL )
		{
			if(READ_FIFO0.head == READ_FIFO0.tail )
			{
				READ_FIFO0.tail += CAN_MSG_LEN;
				if(READ_FIFO0.tail == RD_FIFO_LEN)
				{
					READ_FIFO0.status = FIFO_OK;
					READ_FIFO0.tail %= RD_FIFO_LEN;
				}
			}
		}
		/* release receive buffer*/
		can0w(1,4);
        gRecFlag0=1;
	  }
	  if(protocol1==CANBUS_PROTOCOL_20B) 
	  {			 
		 head = READ_FIFO_EX0.head;
		 pcan_msgex= (CAN_MSG_T_EX *)&READ_FIFO_EX0.buffer[head];
		 temp1=can0r(16);
		 pcan_msgex->ff   = ( temp1 & 0x80 );
		 pcan_msgex->dlen = ( temp1 & 0x0f );
		 pcan_msgex->rtr  = ( temp1 >> 6) & 1;
		 if ( pcan_msgex->ff == PELICAN_SFF )
		 {
			 temp2 = can0r(17);
			 pcan_msgex->id = temp2 << 3;
			 temp2 = can0r(18);
			 pcan_msgex->id |= temp2 >> 5;
			 for ( i = 0; i < pcan_msgex->dlen; i++ )
				 pcan_msgex->data[i] =  can0r(19+i);
		 }
		 else
		 {
			 temp2 = can0r(17);
			 pcan_msgex->id = temp2 << 21;
			 temp2 = can0r(18);
			 pcan_msgex->id |= temp2 << 13;
			 temp2 = can0r(19);
			 pcan_msgex->id |= temp2 << 5;
			 temp2 = can0r(20);
			 pcan_msgex->id |= temp2 >> 3;
			 for ( i = 0; i < pcan_msgex->dlen; i++ )
				 pcan_msgex->data[i] =  can0r(21+i);
		 }
				 
		 READ_FIFO_EX0.head += CAN_MSG_EX_LEN;
		 if(READ_FIFO_EX0.head == RD_FIFO_EX_LEN )
		 {
			 READ_FIFO_EX0.status = FIFO_FULL;
			 READ_FIFO_EX0.head %= RD_FIFO_EX_LEN;
		 }
		 if(READ_FIFO_EX0.status == FIFO_FULL )
		 {
			 if(READ_FIFO_EX0.head == READ_FIFO_EX0.tail )
			 {
				 READ_FIFO_EX0.tail += CAN_MSG_EX_LEN;
				 if(READ_FIFO_EX0.tail == RD_FIFO_EX_LEN)
				 {
					 READ_FIFO_EX0.status = FIFO_OK;
					 READ_FIFO_EX0.tail %= RD_FIFO_EX_LEN;
				 }
			 }
		 }
		 /* release receive buffer*/
		 can0w(1,4);
		 gRecFlag0=1;
	 }
    }
    if( flag & 2) /* TIF */
    {
        gSendFlag0=1;
    }

    flag=can1r(3); /* port1 interrupt */
    if( flag & 1) /* RIF */
    {
      if(protocol2==CANBUS_PROTOCOL_20A)
	  {
		head = READ_FIFO1.head;
		pcan_msg= (MSG_STRUCT *)&READ_FIFO1.buffer[head];
		temp1=can1r(20);
		temp2=can1r(21);
		pcan_msg->id = temp1;
		pcan_msg->id <<= 3;
		pcan_msg->id |= temp2>>5;
		pcan_msg->rtr = (temp2>>4)&1;
		pcan_msg->dlen = temp2&0x0f;
		for(i=0; i< pcan_msg->dlen; i++)
			pcan_msg->data[i]=can1r(22+i);
		for(i=pcan_msg->dlen; i < 8; i++ )
			pcan_msg->data[i] = 0;
		READ_FIFO1.head += CAN_MSG_LEN;
		if(READ_FIFO1.head == RD_FIFO_LEN )
		{
			READ_FIFO1.status = FIFO_FULL;
			READ_FIFO1.head %= RD_FIFO_LEN;
		}
		if(READ_FIFO1.status == FIFO_FULL )
		{
			if(READ_FIFO1.head == READ_FIFO1.tail )
			{
				READ_FIFO1.tail += CAN_MSG_LEN;
				if(READ_FIFO1.tail == RD_FIFO_LEN)
				{
					READ_FIFO1.status = FIFO_OK;
					READ_FIFO1.tail %= RD_FIFO_LEN;
				}
			}
		}
    /* release receive buffer*/
    	can1w(1,4);
    	gRecFlag1=1;
	  }
	  if(protocol2==CANBUS_PROTOCOL_20B) 
	  {
		 head = READ_FIFO_EX1.head;
		  pcan_msgex= (CAN_MSG_T_EX *)&READ_FIFO_EX1.buffer[head];
		  temp1=can1r(16);
		  pcan_msgex->ff   = ( temp1 & 0x80 );
		  pcan_msgex->dlen = ( temp1 & 0x0f );
		  pcan_msgex->rtr  = ( temp1 >> 6) & 1;
		  if ( pcan_msgex->ff == PELICAN_SFF )
		  {
			  temp2 = can1r(17);
			  pcan_msgex->id = temp2 << 3;
			  temp2 = can1r(18);
			  pcan_msgex->id |= temp2 >> 5;
			  for ( i = 0; i < pcan_msgex->dlen; i++ )
				  pcan_msgex->data[i] =  can1r(19+i); 
		  }
		  else
		  {
			  temp2 = can1r(17);
			  pcan_msgex->id = temp2 << 21;
			  temp2 = can1r(18);
			  pcan_msgex->id |= temp2 << 13;
			  temp2 = can1r(19);
			  pcan_msgex->id |= temp2 << 5;
			  temp2 = can1r(20);
			  pcan_msgex->id |= temp2 >> 3;
			  for ( i = 0; i < pcan_msgex->dlen; i++ )
				  pcan_msgex->data[i] =  can1r(21+i);
		  }
			  
		  READ_FIFO_EX1.head += CAN_MSG_EX_LEN;
		  if(READ_FIFO_EX1.head == RD_FIFO_EX_LEN )
		  {
			  READ_FIFO_EX1.status = FIFO_FULL;
			  READ_FIFO_EX1.head %= RD_FIFO_EX_LEN;
		  }
		  if(READ_FIFO_EX1.status == FIFO_FULL )
		  {
			  if(READ_FIFO_EX1.head == READ_FIFO_EX1.tail )
			  {
				  READ_FIFO_EX1.tail += CAN_MSG_EX_LEN;
				  if(READ_FIFO_EX1.tail == RD_FIFO_EX_LEN)
				  {
					  READ_FIFO_EX1.status = FIFO_OK;
					  READ_FIFO_EX1.tail %= RD_FIFO_EX_LEN;
				  }
			  }
		  }
			  /* release receive buffer*/
		  can1w(1,4);
		  gRecFlag1=1;
	  }
    }
    if( flag & 2) /* TIF */
    {
    	gSendFlag1=1;
    }

    //Enable system to accept next interrupt
    outportb(0x20,0x20);
    if ( giIrqNum > 7 )
        outportb(0xa0,0x20);
    enable();
}//IrqHandler

BYTE canExitHW()
{
   RestoreOldIsr(giIrqNum,ucIrqMask,pOldIsr);
   return 1;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function    :int  canSetProtocolType( BYTE port,BYTE protocoltype );
//
// Parameter          Description
// ----------------------------------------------------------------------------
// port   (IN)       Port Index
//
// Function Description
//    * set the can protocol type
// Returns
//    Returns 1 if successful. If unsuccessful, returns 0.
/*---------------------------------------------------------------*/ 
int  canSetProtocolType( BYTE port,BYTE protocoltype )
{
	BYTE v;
	if (port==0)
	{
		if(protocoltype==CANBUS_PROTOCOL_20A)
		{
			
			protocol1=CANBUS_PROTOCOL_20A;
			return(1);
		}
		if(protocoltype==CANBUS_PROTOCOL_20B)
		{
			
			protocol1=CANBUS_PROTOCOL_20B;
			return(1);
		}
		else return(0);
	}
	if (port==1)
	{
		if(protocoltype==CANBUS_PROTOCOL_20A)
		{
			
			protocol2=CANBUS_PROTOCOL_20A;
			return(1);
		}
		if(protocoltype==CANBUS_PROTOCOL_20B)
		{
			
			protocol2=CANBUS_PROTOCOL_20B;
			return(1);
		}
		else return(0);
	}
	return(0);
}

/*--------------------------------------------------------------------------*/
