/*

  FlashPoint.c -- FlashPoint SCCB Manager for Linux

  This file contains the FlashPoint SCCB Manager from BusLogic's FlashPoint
  Driver Developer's Kit, with minor modifications by Leonard N. Zubkoff for
  Linux compatibility.  It was provided by BusLogic in the form of 16 separate
  source files, which would have unnecessarily cluttered the scsi directory, so
  the individual files have been combined into this single file.

  Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved

  This file is available under both the GNU General Public License
  and a BSD-style copyright; see LICENSE.FlashPoint for details.

*/


#include <linux/config.h>


#ifndef CONFIG_SCSI_OMIT_FLASHPOINT


#define UNIX
#define FW_TYPE		_SCCB_MGR_
#define MAX_CARDS	8
#undef BUSTYPE_PCI


#define OS_InPortByte(port)		inb(port)
#define OS_InPortWord(port)		inw(port)
#define OS_InPortLong(port)		inl(port)
#define OS_OutPortByte(port, value)	outb(value, port)
#define OS_OutPortWord(port, value)	outw(value, port)
#define OS_OutPortLong(port, value)	outl(value, port)
#define OS_Lock(x)
#define OS_UnLock(x)


/*
  Define name replacements for compatibility with the Linux BusLogic Driver.
*/

#define SccbMgr_sense_adapter		FlashPoint_ProbeHostAdapter
#define SccbMgr_config_adapter		FlashPoint_HardwareResetHostAdapter
#define SccbMgr_unload_card		FlashPoint_ReleaseHostAdapter
#define SccbMgr_start_sccb		FlashPoint_StartCCB
#define SccbMgr_abort_sccb		FlashPoint_AbortCCB
#define SccbMgr_my_int			FlashPoint_InterruptPending
#define SccbMgr_isr			FlashPoint_HandleInterrupt


/*
  Define name replacements to avoid kernel namespace pollution.
*/

#define BL_Card				FPT_BL_Card
#define BusMasterInit			FPT_BusMasterInit
#define CalcCrc16			FPT_CalcCrc16
#define CalcLrc				FPT_CalcLrc
#define ChkIfChipInitialized		FPT_ChkIfChipInitialized
#define DiagBusMaster			FPT_DiagBusMaster
#define DiagEEPROM			FPT_DiagEEPROM
#define DiagXbow			FPT_DiagXbow
#define GetTarLun			FPT_GetTarLun
#define RNVRamData			FPT_RNVRamData
#define RdStack				FPT_RdStack
#define SccbMgrTableInitAll		FPT_SccbMgrTableInitAll
#define SccbMgrTableInitCard		FPT_SccbMgrTableInitCard
#define SccbMgrTableInitTarget		FPT_SccbMgrTableInitTarget
#define SccbMgr_bad_isr			FPT_SccbMgr_bad_isr
#define SccbMgr_scsi_reset		FPT_SccbMgr_scsi_reset
#define SccbMgr_timer_expired		FPT_SccbMgr_timer_expired
#define SendMsg				FPT_SendMsg
#define Wait				FPT_Wait
#define Wait1Second			FPT_Wait1Second
#define WrStack				FPT_WrStack
#define XbowInit			FPT_XbowInit
#define autoCmdCmplt			FPT_autoCmdCmplt
#define autoLoadDefaultMap		FPT_autoLoadDefaultMap
#define busMstrDataXferStart		FPT_busMstrDataXferStart
#define busMstrSGDataXferStart		FPT_busMstrSGDataXferStart
#define busMstrTimeOut			FPT_busMstrTimeOut
#define dataXferProcessor		FPT_dataXferProcessor
#define default_intena			FPT_default_intena
#define hostDataXferAbort		FPT_hostDataXferAbort
#define hostDataXferRestart		FPT_hostDataXferRestart
#define inisci				FPT_inisci
#define mbCards				FPT_mbCards
#define nvRamInfo			FPT_nvRamInfo
#define phaseBusFree			FPT_phaseBusFree
#define phaseChkFifo			FPT_phaseChkFifo
#define phaseCommand			FPT_phaseCommand
#define phaseDataIn			FPT_phaseDataIn
#define phaseDataOut			FPT_phaseDataOut
#define phaseDecode			FPT_phaseDecode
#define phaseIllegal			FPT_phaseIllegal
#define phaseMsgIn			FPT_phaseMsgIn
#define phaseMsgOut			FPT_phaseMsgOut
#define phaseStatus			FPT_phaseStatus
#define queueAddSccb			FPT_queueAddSccb
#define queueCmdComplete		FPT_queueCmdComplete
#define queueDisconnect			FPT_queueDisconnect
#define queueFindSccb			FPT_queueFindSccb
#define queueFlushSccb			FPT_queueFlushSccb
#define queueFlushTargSccb		FPT_queueFlushTargSccb
#define queueSearchSelect		FPT_queueSearchSelect
#define queueSelectFail			FPT_queueSelectFail
#define s_PhaseTbl			FPT_s_PhaseTbl
#define scamHAString			FPT_scamHAString
#define scamInfo			FPT_scamInfo
#define scarb				FPT_scarb
#define scasid				FPT_scasid
#define scbusf				FPT_scbusf
#define sccbMgrTbl			FPT_sccbMgrTbl
#define schkdd				FPT_schkdd
#define scini				FPT_scini
#define sciso				FPT_sciso
#define scmachid			FPT_scmachid
#define scsavdi				FPT_scsavdi
#define scsel				FPT_scsel
#define scsell				FPT_scsell
#define scsendi				FPT_scsendi
#define scvalq				FPT_scvalq
#define scwirod				FPT_scwirod
#define scwiros				FPT_scwiros
#define scwtsel				FPT_scwtsel
#define scxferc				FPT_scxferc
#define sdecm				FPT_sdecm
#define sfm				FPT_sfm
#define shandem				FPT_shandem
#define sinits				FPT_sinits
#define sisyncn				FPT_sisyncn
#define sisyncr				FPT_sisyncr
#define siwidn				FPT_siwidn
#define siwidr				FPT_siwidr
#define sres				FPT_sres
#define sresb				FPT_sresb
#define ssel				FPT_ssel
#define ssenss				FPT_ssenss
#define sssyncv				FPT_sssyncv
#define stsyncn				FPT_stsyncn
#define stwidn				FPT_stwidn
#define sxfrp				FPT_sxfrp
#define utilEERead			FPT_utilEERead
#define utilEEReadOrg			FPT_utilEEReadOrg
#define utilEESendCmdAddr		FPT_utilEESendCmdAddr
#define utilEEWrite			FPT_utilEEWrite
#define utilEEWriteOnOff		FPT_utilEEWriteOnOff
#define utilUpdateResidual		FPT_utilUpdateResidual


/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   globals.h  $
 *
 *   Description:  Common shared global defines.
 *
 *   $Date: 1996/09/04 01:26:13 $
 *
 *   $Revision: 1.11 $
 *
 *----------------------------------------------------------------------*/
#ifndef __GLOBALS_H__
#define __GLOBALS_H__

#define _UCB_MGR_  1
#define _SCCB_MGR_ 2

/*#include <osflags.h>*/

#define MAX_CDBLEN  12

#define SCAM_LEV_2	1

#define CRCMASK	0xA001

/*  In your osflags.h file, please ENSURE that only ONE OS FLAG 
    is on at a time !!! Also, please make sure you turn set the 
 	 variable FW_TYPE to either _UCB_MGR_ or _SCCB_MGR_  !!! */

#if defined(DOS) || defined(WIN95_16) || defined(OS2) || defined(OTHER_16)
   #define       COMPILER_16_BIT 1
#elif defined(NETWARE) || defined(NT) || defined(WIN95_32) || defined(UNIX) || defined(OTHER_32) || defined(SOLARIS_REAL_MODE)
   #define       COMPILER_32_BIT 1
#endif


#define     BL_VENDOR_ID      0x104B
#define     FP_DEVICE_ID      0x8130
#define     MM_DEVICE_ID      0x1040


#ifndef FALSE
#define FALSE           0
#endif
#ifndef TRUE
#define TRUE            (!(FALSE))
#endif

#ifndef NULL
#define NULL            0
#endif

#define FAILURE         0xFFFFFFFFL


typedef unsigned char   UCHAR;
typedef unsigned short  USHORT;
typedef unsigned int    UINT;
typedef unsigned long   ULONG;
typedef unsigned char * PUCHAR;
typedef unsigned short* PUSHORT;
typedef unsigned long * PULONG;
typedef void *          PVOID;


#if defined(COMPILER_16_BIT)
typedef unsigned char far       * uchar_ptr;
typedef unsigned short far      * ushort_ptr;
typedef unsigned long far       * ulong_ptr;
#endif  /* 16_BIT_COMPILER */

#if defined(COMPILER_32_BIT)
typedef unsigned char           * uchar_ptr;
typedef unsigned short          * ushort_ptr;
typedef unsigned long           * ulong_ptr;
#endif  /* 32_BIT_COMPILER */


/*	 			NEW TYPE DEFINITIONS (shared with Mylex North)

**  Use following type defines to avoid confusion in 16 and 32-bit
**  environments.  Avoid using 'int' as it denotes 16 bits in 16-bit
**  environment and 32 in 32-bit environments.

*/

#define s08bits	char
#define s16bits 	short
#define s32bits	long

#define u08bits	unsigned s08bits
#define u16bits	unsigned s16bits
#define u32bits	unsigned s32bits

#if defined(COMPILER_16_BIT)

typedef u08bits far 	* pu08bits;
typedef u16bits far 	* pu16bits;
typedef u32bits far	* pu32bits;

#endif	/* COMPILER_16_BIT */

#if defined(COMPILER_32_BIT)

typedef u08bits 	* pu08bits;
typedef u16bits 	* pu16bits;
typedef u32bits 	* pu32bits;

#endif	/* COMPILER_32_BIT */


#define BIT(x)          ((UCHAR)(1<<(x)))    /* single-bit mask in bit position x */
#define BITW(x)          ((USHORT)(1<<(x)))  /* single-bit mask in bit position x */



#if defined(DOS)
/*#include <dos.h>*/
	#undef inportb          /* undefine for Borland Lib */
	#undef inport           /* they may have define I/O function in LIB */
	#undef outportb
	#undef outport

	#define OS_InPortByte(ioport) 		inportb(ioport)
	#define OS_InPortWord(ioport) 		inport(ioport)
	#define OS_InPortLong(ioport)			inportq(ioport, val)
	#define OS_OutPortByte(ioport, val) outportb(ioport, val)
	#define OS_OutPortWord(ioport, val)	outport(ioport, val)
	#define OS_OutPortLong(ioport)		outportq(ioport, val)
#endif	/* DOS */

#if defined(NETWARE) || defined(OTHER_32) ||  defined(OTHER_16)
	extern u08bits	OS_InPortByte(u32bits ioport);
	extern u16bits	OS_InPortWord(u32bits ioport);
	extern u32bits	OS_InPortLong(u32bits ioport);

	extern OS_InPortByteBuffer(u32bits ioport, pu08bits buffer, u32bits count);
	extern OS_InPortWordBuffer(u32bits ioport, pu16bits buffer, u32bits count);
	extern OS_OutPortByte(u32bits ioport, u08bits val);
	extern OS_OutPortWord(u32bits ioport, u16bits val);
	extern OS_OutPortLong(u32bits ioport, u32bits val);
	extern OS_OutPortByteBuffer(u32bits ioport, pu08bits buffer, u32bits count);
	extern OS_OutPortWordBuffer(u32bits ioport, pu16bits buffer, u32bits count);
#endif	/* NETWARE || OTHER_32 || OTHER_16 */

#if defined (NT) || defined(WIN95_32) || defined(WIN95_16)
	#if defined(NT)

		extern __declspec(dllimport) u08bits ScsiPortReadPortUchar(pu08bits ioport);
		extern __declspec(dllimport) u16bits ScsiPortReadPortUshort(pu16bits ioport);
		extern __declspec(dllimport) u32bits ScsiPortReadPortUlong(pu32bits ioport);
		extern __declspec(dllimport) void ScsiPortWritePortUchar(pu08bits ioport, u08bits val);
		extern __declspec(dllimport) void ScsiPortWritePortUshort(pu16bits port, u16bits val);
		extern __declspec(dllimport) void ScsiPortWritePortUlong(pu32bits port, u32bits val);

	#else

		extern u08bits ScsiPortReadPortUchar(pu08bits ioport);
		extern u16bits ScsiPortReadPortUshort(pu16bits ioport);
		extern u32bits ScsiPortReadPortUlong(pu32bits ioport);
		extern void ScsiPortWritePortUchar(pu08bits ioport, u08bits val);
		extern void ScsiPortWritePortUshort(pu16bits port, u16bits val);
		extern void ScsiPortWritePortUlong(pu32bits port, u32bits val);
	#endif


	#define OS_InPortByte(ioport) ScsiPortReadPortUchar((pu08bits) ioport)
	#define OS_InPortWord(ioport) ScsiPortReadPortUshort((pu16bits) ioport)
	#define OS_InPortLong(ioport) ScsiPortReadPortUlong((pu32bits) ioport)

	#define OS_OutPortByte(ioport, val) ScsiPortWritePortUchar((pu08bits) ioport, (u08bits) val)
	#define OS_OutPortWord(ioport, val) ScsiPortWritePortUshort((pu16bits) ioport, (u16bits) val)
	#define OS_OutPortLong(ioport, val) ScsiPortWritePortUlong((pu32bits) ioport, (u32bits) val)
	#define OS_OutPortByteBuffer(ioport, buffer, count) \
		ScsiPortWritePortBufferUchar((pu08bits)&port, (pu08bits) buffer, (u32bits) count)
	#define OS_OutPortWordBuffer(ioport, buffer, count) \
		ScsiPortWritePortBufferUshort((pu16bits)&port, (pu16bits) buffer, (u32bits) count)

	#define OS_Lock(x)
	#define OS_UnLock(x)
#endif /* NT || WIN95_32 || WIN95_16 */

#if defined (UNIX) && !defined(OS_InPortByte)
	#define OS_InPortByte(ioport)    inb((u16bits)ioport)
	#define OS_InPortWord(ioport)    inw((u16bits)ioport)
	#define OS_InPortLong(ioport)    inl((u16bits)ioport)
	#define OS_OutPortByte(ioport,val)  outb((u16bits)ioport, (u08bits)val)
	#define OS_OutPortWord(ioport,val)  outw((u16bits)ioport, (u16bits)val)
	#define OS_OutPortLong(ioport,val)  outl((u16bits)ioport, (u32bits)val)

	#define OS_Lock(x)
	#define OS_UnLock(x)
#endif /* UNIX */


#if defined(OS2)
	extern u08bits	inb(u32bits ioport);
	extern u16bits	inw(u32bits ioport);
	extern void	outb(u32bits ioport, u08bits val);
	extern void	outw(u32bits ioport, u16bits val);

	#define OS_InPortByte(ioport)			inb(ioport)
	#define OS_InPortWord(ioport)			inw(ioport)
	#define OS_OutPortByte(ioport, val)	outb(ioport, val)
	#define OS_OutPortWord(ioport, val)	outw(ioport, val)
	extern u32bits	OS_InPortLong(u32bits ioport);
	extern void	OS_OutPortLong(u32bits ioport, u32bits val);

	#define OS_Lock(x)
	#define OS_UnLock(x)
#endif /* OS2 */

#if defined(SOLARIS_REAL_MODE)

extern unsigned char    inb(unsigned long ioport);
extern unsigned short   inw(unsigned long ioport);

#define OS_InPortByte(ioport)    inb(ioport)
#define OS_InPortWord(ioport)    inw(ioport)

extern void OS_OutPortByte(unsigned long ioport, unsigned char val);
extern void OS_OutPortWord(unsigned long ioport, unsigned short val);
extern unsigned long  OS_InPortLong(unsigned long ioport);
extern void     OS_OutPortLong(unsigned long ioport, unsigned long val);

#define OS_Lock(x)
#define OS_UnLock(x)

#endif  /* SOLARIS_REAL_MODE */

#endif  /* __GLOBALS_H__ */

/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   sccbmgr.h  $
 *
 *   Description:  Common shared SCCB Interface defines and SCCB 
 *						 Manager specifics defines.
 *
 *   $Date: 1996/10/24 23:09:33 $
 *
 *   $Revision: 1.14 $
 *
 *----------------------------------------------------------------------*/

#ifndef __SCCB_H__
#define __SCCB_H__

/*#include <osflags.h>*/
/*#include <globals.h>*/

#if defined(BUGBUG)
#define debug_size 32
#endif

#if defined(DOS)

   typedef struct _SCCB near *PSCCB;
	#if (FW_TYPE == _SCCB_MGR_)
   	typedef void (*CALL_BK_FN)(PSCCB);
	#endif

#elif defined(OS2)

   typedef struct _SCCB far *PSCCB;
	#if (FW_TYPE == _SCCB_MGR_)
   	typedef void (far *CALL_BK_FN)(PSCCB);
	#endif

#else

   typedef struct _SCCB *PSCCB;
	#if (FW_TYPE == _SCCB_MGR_)
   	typedef void (*CALL_BK_FN)(PSCCB);
	#endif

#endif


typedef struct SCCBMgr_info {
   ULONG    si_baseaddr;
   UCHAR    si_present;
   UCHAR    si_intvect;
   UCHAR    si_id;
   UCHAR    si_lun;
   USHORT   si_fw_revision;
   USHORT   si_per_targ_init_sync;
   USHORT   si_per_targ_fast_nego;
   USHORT   si_per_targ_ultra_nego;
   USHORT   si_per_targ_no_disc;
   USHORT   si_per_targ_wide_nego;
   USHORT   si_flags;
   UCHAR    si_card_family;
   UCHAR    si_bustype;
   UCHAR    si_card_model[3];
   UCHAR    si_relative_cardnum;
   UCHAR    si_reserved[4];
   ULONG    si_OS_reserved;
   UCHAR    si_XlatInfo[4];
   ULONG    si_reserved2[5];
   ULONG    si_secondary_range;
} SCCBMGR_INFO;

#if defined(DOS)
   typedef SCCBMGR_INFO *      PSCCBMGR_INFO;
#else
   #if defined (COMPILER_16_BIT)
   typedef SCCBMGR_INFO far *  PSCCBMGR_INFO;
   #else
   typedef SCCBMGR_INFO *      PSCCBMGR_INFO;
   #endif
#endif // defined(DOS)




#if (FW_TYPE==_SCCB_MGR_)
	#define SCSI_PARITY_ENA		  0x0001
	#define LOW_BYTE_TERM		  0x0010
	#define HIGH_BYTE_TERM		  0x0020
	#define BUSTYPE_PCI	  0x3
#endif

#define SUPPORT_16TAR_32LUN	  0x0002
#define SOFT_RESET		  0x0004
#define EXTENDED_TRANSLATION	  0x0008
#define POST_ALL_UNDERRRUNS	  0x0040
#define FLAG_SCAM_ENABLED	  0x0080
#define FLAG_SCAM_LEVEL2	  0x0100




#define HARPOON_FAMILY        0x02


#define ISA_BUS_CARD          0x01
#define EISA_BUS_CARD         0x02
#define PCI_BUS_CARD          0x03
#define VESA_BUS_CARD         0x04

/* SCCB struc used for both SCCB and UCB manager compiles! 
 * The UCB Manager treats the SCCB as it's 'native hardware structure' 
 */


#pragma pack(1)
typedef struct _SCCB {
   UCHAR OperationCode;
   UCHAR ControlByte;
   UCHAR CdbLength;
   UCHAR RequestSenseLength;
   ULONG DataLength;
   ULONG DataPointer;
   UCHAR CcbRes[2];
   UCHAR HostStatus;
   UCHAR TargetStatus;
   UCHAR TargID;
   UCHAR Lun;
   UCHAR Cdb[12];
   UCHAR CcbRes1;
   UCHAR Reserved1;
   ULONG Reserved2;
   ULONG SensePointer;


   CALL_BK_FN SccbCallback;                  /* VOID (*SccbCallback)(); */
   ULONG  SccbIOPort;                        /* Identifies board base port */
   UCHAR  SccbStatus;
   UCHAR  SCCBRes2;
   USHORT SccbOSFlags;


   ULONG   Sccb_XferCnt;            /* actual transfer count */
   ULONG   Sccb_ATC;
   ULONG   SccbVirtDataPtr;         /* virtual addr for OS/2 */
   ULONG   Sccb_res1;
   USHORT  Sccb_MGRFlags;
   USHORT  Sccb_sgseg;
   UCHAR   Sccb_scsimsg;            /* identify msg for selection */
   UCHAR   Sccb_tag;
   UCHAR   Sccb_scsistat;
   UCHAR   Sccb_idmsg;              /* image of last msg in */
   PSCCB   Sccb_forwardlink;
   PSCCB   Sccb_backlink;
   ULONG   Sccb_savedATC;
   UCHAR   Save_Cdb[6];
   UCHAR   Save_CdbLen;
   UCHAR   Sccb_XferState;
   ULONG   Sccb_SGoffset;
#if (FW_TYPE == _UCB_MGR_)
   PUCB    Sccb_ucb_ptr;
#endif
   } SCCB;

#define SCCB_SIZE sizeof(SCCB)

#pragma pack()



#define SCSI_INITIATOR_COMMAND    0x00
#define TARGET_MODE_COMMAND       0x01
#define SCATTER_GATHER_COMMAND    0x02
#define RESIDUAL_COMMAND          0x03
#define RESIDUAL_SG_COMMAND       0x04
#define RESET_COMMAND             0x81


#define F_USE_CMD_Q              0x20     /*Inidcates TAGGED command. */
#define TAG_TYPE_MASK            0xC0     /*Type of tag msg to send. */
#define TAG_Q_MASK               0xE0
#define SCCB_DATA_XFER_OUT       0x10     /* Write */
#define SCCB_DATA_XFER_IN        0x08     /* Read */


#define FOURTEEN_BYTES           0x00     /* Request Sense Buffer size */
#define NO_AUTO_REQUEST_SENSE    0x01     /* No Request Sense Buffer */


#define BUS_FREE_ST     0       
#define SELECT_ST       1
#define SELECT_BDR_ST   2     /* Select w\ Bus Device Reset */
#define SELECT_SN_ST    3     /* Select w\ Sync Nego */
#define SELECT_WN_ST    4     /* Select w\ Wide Data Nego */
#define SELECT_Q_ST     5     /* Select w\ Tagged Q'ing */
#define COMMAND_ST      6
#define DATA_OUT_ST     7
#define DATA_IN_ST      8
#define DISCONNECT_ST   9
#define STATUS_ST       10
#define ABORT_ST        11
#define MESSAGE_ST      12


#define F_HOST_XFER_DIR                0x01
#define F_ALL_XFERRED                  0x02
#define F_SG_XFER                      0x04
#define F_AUTO_SENSE                   0x08
#define F_ODD_BALL_CNT                 0x10
#define F_NO_DATA_YET                  0x80


#define F_STATUSLOADED                 0x01
#define F_MSGLOADED                    0x02
#define F_DEV_SELECTED                 0x04


#define SCCB_COMPLETE               0x00  /* SCCB completed without error */
#define SCCB_DATA_UNDER_RUN         0x0C
#define SCCB_SELECTION_TIMEOUT      0x11  /* Set SCSI selection timed out */
#define SCCB_DATA_OVER_RUN          0x12
#define SCCB_UNEXPECTED_BUS_FREE    0x13  /* Target dropped SCSI BSY */
#define SCCB_PHASE_SEQUENCE_FAIL    0x14  /* Target bus phase sequence failure */

#define SCCB_INVALID_OP_CODE        0x16  /* SCCB invalid operation code */
#define SCCB_INVALID_SCCB           0x1A  /* Invalid SCCB - bad parameter */
#define SCCB_GROSS_FW_ERR           0x27  /* Major problem! */
#define SCCB_BM_ERR                 0x30  /* BusMaster error. */
#define SCCB_PARITY_ERR             0x34  /* SCSI parity error */



#if (FW_TYPE==_UCB_MGR_)  
   #define  HBA_AUTO_SENSE_FAIL        0x1B  
   #define  HBA_TQ_REJECTED            0x1C  
   #define  HBA_UNSUPPORTED_MSG         0x1D  
   #define  HBA_HW_ERROR               0x20  
   #define  HBA_ATN_NOT_RESPONDED      0x21  
   #define  HBA_SCSI_RESET_BY_ADAPTER  0x22
   #define  HBA_SCSI_RESET_BY_TARGET   0x23
   #define  HBA_WRONG_CONNECTION       0x24
   #define  HBA_BUS_DEVICE_RESET       0x25
   #define  HBA_ABORT_QUEUE            0x26

#else // these are not defined in BUDI/UCB

   #define SCCB_INVALID_DIRECTION      0x18  /* Invalid target direction */
   #define SCCB_DUPLICATE_SCCB         0x19  /* Duplicate SCCB */
   #define SCCB_SCSI_RST               0x35  /* SCSI RESET detected. */

#endif // (FW_TYPE==_UCB_MGR_)  


#define SCCB_IN_PROCESS            0x00
#define SCCB_SUCCESS               0x01
#define SCCB_ABORT                 0x02
#define SCCB_NOT_FOUND             0x03
#define SCCB_ERROR                 0x04
#define SCCB_INVALID               0x05

#define SCCB_SIZE sizeof(SCCB)




#if (FW_TYPE == _UCB_MGR_)
	void SccbMgr_start_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb);
	s32bits SccbMgr_abort_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb);
	u08bits SccbMgr_my_int(CARD_HANDLE pCurrCard);
	s32bits SccbMgr_isr(CARD_HANDLE pCurrCard);
	void SccbMgr_scsi_reset(CARD_HANDLE pCurrCard);
	void SccbMgr_timer_expired(CARD_HANDLE pCurrCard);
	void SccbMgr_unload_card(CARD_HANDLE pCurrCard);
	void SccbMgr_restore_foreign_state(CARD_HANDLE pCurrCard);
	void SccbMgr_restore_native_state(CARD_HANDLE pCurrCard);
	void SccbMgr_save_foreign_state(PADAPTER_INFO pAdapterInfo);

#endif


#if (FW_TYPE == _SCCB_MGR_)

 #if defined (DOS)
	int    SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo);
	USHORT SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo);
	void  SccbMgr_start_sccb(USHORT pCurrCard, PSCCB p_SCCB);
	int   SccbMgr_abort_sccb(USHORT pCurrCard, PSCCB p_SCCB);
	UCHAR SccbMgr_my_int(USHORT pCurrCard);
	int   SccbMgr_isr(USHORT pCurrCard);
	void  SccbMgr_scsi_reset(USHORT pCurrCard);
	void  SccbMgr_timer_expired(USHORT pCurrCard);
	USHORT SccbMgr_status(USHORT pCurrCard);
	void SccbMgr_unload_card(USHORT pCurrCard);

 #else    //non-DOS

	int   SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo);
	ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo);
	void  SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_SCCB);
	int   SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_SCCB);
	UCHAR SccbMgr_my_int(ULONG pCurrCard);
	int   SccbMgr_isr(ULONG pCurrCard);
	void  SccbMgr_scsi_reset(ULONG pCurrCard);
	void  SccbMgr_enable_int(ULONG pCurrCard);
	void  SccbMgr_disable_int(ULONG pCurrCard);
	void  SccbMgr_timer_expired(ULONG pCurrCard);
	void SccbMgr_unload_card(ULONG pCurrCard);

  #endif
#endif  // (FW_TYPE == _SCCB_MGR_)

#endif  /* __SCCB_H__ */

/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   blx30.h  $
 *
 *   Description: This module contains SCCB/UCB Manager implementation
 *                specific stuff.
 *
 *   $Date: 1996/11/13 18:34:22 $
 *
 *   $Revision: 1.10 $
 *
 *----------------------------------------------------------------------*/


#ifndef __blx30_H__
#define __blx30_H__

/*#include <globals.h>*/

#define  ORION_FW_REV      3110




#define HARP_REVD    1


#if defined(DOS)
#define QUEUE_DEPTH     8+1            /*1 for Normal disconnect 0 for Q'ing. */
#else
#define QUEUE_DEPTH     254+1            /*1 for Normal disconnect 32 for Q'ing. */
#endif   // defined(DOS)

#define	MAX_MB_CARDS	4					/* Max. no of cards suppoerted on Mother Board */

#define WIDE_SCSI       1

#if defined(WIDE_SCSI)
   #if defined(DOS)
      #define MAX_SCSI_TAR    16
      #define MAX_LUN         8
		#define LUN_MASK			0x07
   #else
      #define MAX_SCSI_TAR    16
      #define MAX_LUN         32
		#define LUN_MASK			0x1f
	
   #endif
#else
   #define MAX_SCSI_TAR    8
   #define MAX_LUN         8
	#define LUN_MASK			0x07
#endif 

#if defined(HARP_REVA)
#define SG_BUF_CNT      15             /*Number of prefetched elements. */
#else
#define SG_BUF_CNT      16             /*Number of prefetched elements. */
#endif

#define SG_ELEMENT_SIZE 8              /*Eight byte per element. */
#define SG_LOCAL_MASK   0x00000000L
#define SG_ELEMENT_MASK 0xFFFFFFFFL


#if (FW_TYPE == _UCB_MGR_)
	#define OPC_DECODE_NORMAL       0x0f7f
#endif   // _UCB_MGR_



#if defined(DOS)

/*#include <dos.h>*/
	#define RD_HARPOON(ioport)          (OS_InPortByte(ioport))
	#define RDW_HARPOON(ioport)         (OS_InPortWord(ioport))
	#define WR_HARPOON(ioport,val)      (OS_OutPortByte(ioport,val))
	#define WRW_HARPOON(ioport,val)     (OS_OutPortWord(ioport,val))

	#define RD_HARP32(port,offset,data)  asm{db 66h;         \
                                       push ax;             \
                                       mov dx,port;         \
                                       add dx, offset;      \
                                       db 66h;              \
                                       in ax,dx;            \
                                       db 66h;              \
                                       mov word ptr data,ax;\
                                       db 66h;              \
                                       pop ax}

	#define WR_HARP32(port,offset,data) asm{db 66h;          \
                                       push ax;             \
                                       mov dx,port;         \
                                       add dx, offset;      \
                                       db 66h;              \
                                       mov ax,word ptr data;\
                                       db 66h;              \
                                       out dx,ax;           \
                                       db 66h;              \
                                       pop ax}
#endif	/* DOS */

#if defined(NETWARE) || defined(OTHER_32) ||  defined(OTHER_16)
	#define RD_HARPOON(ioport)     OS_InPortByte((unsigned long)ioport)
	#define RDW_HARPOON(ioport)    OS_InPortWord((unsigned long)ioport)
	#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong(ioport + offset))
	#define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val)
	#define WRW_HARPOON(ioport,val)  OS_OutPortWord((ULONG)ioport,(USHORT)val)
	#define WR_HARP32(ioport,offset,data)  OS_OutPortLong((ioport + offset), data)
#endif	/* NETWARE || OTHER_32 || OTHER_16 */

#if defined(NT) || defined(WIN95_32) || defined(WIN95_16)
	#define RD_HARPOON(ioport)          OS_InPortByte((ULONG)ioport)
	#define RDW_HARPOON(ioport)         OS_InPortWord((ULONG)ioport)
	#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset)))
	#define WR_HARPOON(ioport,val)      OS_OutPortByte((ULONG)ioport,(UCHAR) val)
	#define WRW_HARPOON(ioport,val)     OS_OutPortWord((ULONG)ioport,(USHORT)val)
	#define WR_HARP32(ioport,offset,data)  OS_OutPortLong((ULONG)(ioport + offset), data)
#endif /* NT || WIN95_32 || WIN95_16 */

#if defined (UNIX)
	#define RD_HARPOON(ioport)          OS_InPortByte((u32bits)ioport)
	#define RDW_HARPOON(ioport)         OS_InPortWord((u32bits)ioport)
	#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((u32bits)(ioport + offset)))
	#define WR_HARPOON(ioport,val)      OS_OutPortByte((u32bits)ioport,(u08bits) val)
	#define WRW_HARPOON(ioport,val)       OS_OutPortWord((u32bits)ioport,(u16bits)val)
	#define WR_HARP32(ioport,offset,data)  OS_OutPortLong((u32bits)(ioport + offset), data)
#endif /* UNIX */

#if defined(OS2)
	#define RD_HARPOON(ioport)          OS_InPortByte((unsigned long)ioport)
	#define RDW_HARPOON(ioport)         OS_InPortWord((unsigned long)ioport)
	#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset)))
	#define WR_HARPOON(ioport,val)      OS_OutPortByte((ULONG)ioport,(UCHAR) val)
	#define WRW_HARPOON(ioport,val)       OS_OutPortWord((ULONG)ioport,(USHORT)val)
	#define WR_HARP32(ioport,offset,data)  OS_OutPortLong(((ULONG)(ioport + offset)), data)
#endif /* OS2 */

#if defined(SOLARIS_REAL_MODE)

	#define RD_HARPOON(ioport)          OS_InPortByte((unsigned long)ioport)
	#define RDW_HARPOON(ioport)         OS_InPortWord((unsigned long)ioport)
	#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset)))
	#define WR_HARPOON(ioport,val)      OS_OutPortByte((ULONG)ioport,(UCHAR) val)
	#define WRW_HARPOON(ioport,val)       OS_OutPortWord((ULONG)ioport,(USHORT)val)
	#define WR_HARP32(ioport,offset,data)  OS_OutPortLong((ULONG)(ioport + offset), (ULONG)data)

#endif  /* SOLARIS_REAL_MODE */

#endif  /* __BLX30_H__ */


/*----------------------------------------------------------------------
 * 
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   target.h  $
 *
 *   Description:  Definitions for Target related structures
 *
 *   $Date: 1996/12/11 22:06:20 $
 *
 *   $Revision: 1.9 $
 *
 *----------------------------------------------------------------------*/

#ifndef __TARGET__
#define __TARGET__

/*#include <globals.h>*/
/*#include <blx30.h>*/


#define  TAR_SYNC_MASK     (BIT(7)+BIT(6))
#define  SYNC_UNKNOWN      0x00
#define  SYNC_TRYING               BIT(6)
#define  SYNC_SUPPORTED    (BIT(7)+BIT(6))

#define  TAR_WIDE_MASK     (BIT(5)+BIT(4))
#define  WIDE_DISABLED     0x00
#define  WIDE_ENABLED              BIT(4)
#define  WIDE_NEGOCIATED   BIT(5)

#define  TAR_TAG_Q_MASK    (BIT(3)+BIT(2))
#define  TAG_Q_UNKNOWN     0x00
#define  TAG_Q_TRYING              BIT(2)
#define  TAG_Q_REJECT      BIT(3)
#define  TAG_Q_SUPPORTED   (BIT(3)+BIT(2))

#define  TAR_ALLOW_DISC    BIT(0)


#define  EE_SYNC_MASK      (BIT(0)+BIT(1))
#define  EE_SYNC_ASYNC     0x00
#define  EE_SYNC_5MB       BIT(0)
#define  EE_SYNC_10MB      BIT(1)
#define  EE_SYNC_20MB      (BIT(0)+BIT(1))

#define  EE_ALLOW_DISC     BIT(6)
#define  EE_WIDE_SCSI      BIT(7)


#if defined(DOS)
   typedef struct SCCBMgr_tar_info near *PSCCBMgr_tar_info;

#elif defined(OS2)
   typedef struct SCCBMgr_tar_info far *PSCCBMgr_tar_info;

#else
   typedef struct SCCBMgr_tar_info *PSCCBMgr_tar_info;

#endif


typedef struct SCCBMgr_tar_info {

   PSCCB    TarSelQ_Head;
   PSCCB    TarSelQ_Tail;
   UCHAR    TarLUN_CA;        /*Contingent Allgiance */
   UCHAR    TarTagQ_Cnt;
   UCHAR    TarSelQ_Cnt;
   UCHAR    TarStatus;
   UCHAR    TarEEValue;
   UCHAR 	TarSyncCtrl;
   UCHAR 	TarReserved[2];			/* for alignment */ 
   UCHAR 	LunDiscQ_Idx[MAX_LUN];
   UCHAR    TarLUNBusy[MAX_LUN];
} SCCBMGR_TAR_INFO;

typedef struct NVRAMInfo {
	UCHAR		niModel;								/* Model No. of card */
	UCHAR		niCardNo;							/* Card no. */
#if defined(DOS)
	USHORT	niBaseAddr;							/* Port Address of card */
#else
	ULONG		niBaseAddr;							/* Port Address of card */
#endif
	UCHAR		niSysConf;							/* Adapter Configuration byte - Byte 16 of eeprom map */
	UCHAR		niScsiConf;							/* SCSI Configuration byte - Byte 17 of eeprom map */
	UCHAR		niScamConf;							/* SCAM Configuration byte - Byte 20 of eeprom map */
	UCHAR		niAdapId;							/* Host Adapter ID - Byte 24 of eerpom map */
	UCHAR		niSyncTbl[MAX_SCSI_TAR / 2];	/* Sync/Wide byte of targets */
	UCHAR		niScamTbl[MAX_SCSI_TAR][4];	/* Compressed Scam name string of Targets */
}NVRAMINFO;

#if defined(DOS)
typedef NVRAMINFO near *PNVRamInfo;
#elif defined (OS2)
typedef NVRAMINFO far *PNVRamInfo;
#else
typedef NVRAMINFO *PNVRamInfo;
#endif

#define	MODEL_LT		1
#define	MODEL_DL		2
#define	MODEL_LW		3
#define	MODEL_DW		4


typedef struct SCCBcard {
   PSCCB currentSCCB;
#if (FW_TYPE==_SCCB_MGR_)
   PSCCBMGR_INFO cardInfo;
#else
   PADAPTER_INFO cardInfo;
#endif

#if defined(DOS)
   USHORT ioPort;
#else
   ULONG ioPort;
#endif

   USHORT cmdCounter;
   UCHAR  discQCount;
   UCHAR  tagQ_Lst; 
   UCHAR cardIndex;
   UCHAR scanIndex;
   UCHAR globalFlags;
   UCHAR ourId;
   PNVRamInfo pNvRamInfo;
   PSCCB discQ_Tbl[QUEUE_DEPTH]; 
      
}SCCBCARD;

#if defined(DOS)
typedef struct SCCBcard near *PSCCBcard;
#elif defined (OS2)
typedef struct SCCBcard far *PSCCBcard;
#else
typedef struct SCCBcard *PSCCBcard;
#endif


#define F_TAG_STARTED		0x01
#define F_CONLUN_IO			0x02
#define F_DO_RENEGO			0x04
#define F_NO_FILTER			0x08
#define F_GREEN_PC			0x10
#define F_HOST_XFER_ACT		0x20
#define F_NEW_SCCB_CMD		0x40
#define F_UPDATE_EEPROM		0x80


#define  ID_STRING_LENGTH  32
#define  TYPE_CODE0        0x63           /*Level2 Mstr (bits 7-6),  */

#define  TYPE_CODE1        00             /*No ID yet */

#define  SLV_TYPE_CODE0    0xA3           /*Priority Bit set (bits 7-6),  */

#define  ASSIGN_ID   0x00
#define  SET_P_FLAG  0x01
#define  CFG_CMPLT   0x03
#define  DOM_MSTR    0x0F
#define  SYNC_PTRN   0x1F

#define  ID_0_7      0x18
#define  ID_8_F      0x11
#define  ID_10_17    0x12
#define  ID_18_1F    0x0B
#define  MISC_CODE   0x14
#define  CLR_P_FLAG  0x18
#define  LOCATE_ON   0x12
#define  LOCATE_OFF  0x0B

#define  LVL_1_MST   0x00
#define  LVL_2_MST   0x40
#define  DOM_LVL_2   0xC0


#define  INIT_SELTD  0x01
#define  LEVEL2_TAR  0x02


enum scam_id_st { ID0,ID1,ID2,ID3,ID4,ID5,ID6,ID7,ID8,ID9,ID10,ID11,ID12,
                  ID13,ID14,ID15,ID_UNUSED,ID_UNASSIGNED,ID_ASSIGNED,LEGACY,
                  CLR_PRIORITY,NO_ID_AVAIL };

typedef struct SCCBscam_info {

   UCHAR    id_string[ID_STRING_LENGTH];
   enum scam_id_st state;
    
} SCCBSCAM_INFO, *PSCCBSCAM_INFO;

#endif
/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   scsi2.h  $
 *
 *   Description:  Register definitions for HARPOON ASIC.
 *
 *   $Date: 1996/11/13 18:32:57 $
 *
 *   $Revision: 1.4 $
 *
 *----------------------------------------------------------------------*/

#ifndef __SCSI_H__
#define __SCSI_H__



#define  SCSI_TEST_UNIT_READY    0x00
#define  SCSI_REZERO_UNIT        0x01
#define  SCSI_REQUEST_SENSE      0x03
#define  SCSI_FORMAT_UNIT        0x04
#define  SCSI_REASSIGN           0x07
#define  SCSI_READ               0x08
#define  SCSI_WRITE              0x0A
#define  SCSI_SEEK               0x0B
#define  SCSI_INQUIRY            0x12
#define  SCSI_MODE_SELECT        0x15
#define  SCSI_RESERVE_UNIT       0x16
#define  SCSI_RELEASE_UNIT       0x17
#define  SCSI_MODE_SENSE         0x1A
#define  SCSI_START_STOP_UNIT    0x1B
#define  SCSI_SEND_DIAGNOSTIC    0x1D
#define  SCSI_READ_CAPACITY      0x25
#define  SCSI_READ_EXTENDED      0x28
#define  SCSI_WRITE_EXTENDED     0x2A
#define  SCSI_SEEK_EXTENDED      0x2B
#define  SCSI_WRITE_AND_VERIFY   0x2E
#define  SCSI_VERIFY             0x2F
#define  SCSI_READ_DEFECT_DATA   0x37
#define  SCSI_WRITE_BUFFER       0x3B
#define  SCSI_READ_BUFFER        0x3C
#define  SCSI_RECV_DIAGNOSTIC    0x1C
#define  SCSI_READ_LONG          0x3E
#define  SCSI_WRITE_LONG         0x3F
#define  SCSI_LAST_SCSI_CMND     SCSI_WRITE_LONG
#define  SCSI_INVALID_CMND       0xFF



#define  SSGOOD                  0x00
#define  SSCHECK                 0x02
#define  SSCOND_MET              0x04
#define  SSBUSY                  0x08
#define  SSRESERVATION_CONFLICT  0x18
#define  SSCMD_TERM              0x22
#define  SSQ_FULL                0x28


#define  SKNO_SEN                0x00
#define  SKRECOV_ERR             0x01
#define  SKNOT_RDY               0x02
#define  SKMED_ERR               0x03
#define  SKHW_ERR                0x04
#define  SKILL_REQ               0x05
#define  SKUNIT_ATTN             0x06
#define  SKDATA_PROTECT          0x07
#define  SKBLNK_CHK              0x08
#define  SKCPY_ABORT             0x0A
#define  SKABORT_CMD             0x0B
#define  SKEQUAL                 0x0C
#define  SKVOL_OVF               0x0D
#define  SKMIS_CMP               0x0E


#define  SMCMD_COMP              0x00
#define  SMEXT                   0x01
#define  SMSAVE_DATA_PTR         0x02
#define  SMREST_DATA_PTR         0x03
#define  SMDISC                  0x04
#define  SMINIT_DETEC_ERR        0x05
#define  SMABORT                 0x06
#define  SMREJECT                0x07
#define  SMNO_OP                 0x08
#define  SMPARITY                0x09
#define  SMDEV_RESET             0x0C
#define	SMABORT_TAG					0x0D
#define	SMINIT_RECOVERY			0x0F
#define	SMREL_RECOVERY				0x10

#define  SMIDENT                 0x80
#define  DISC_PRIV               0x40


#define  SMSYNC                  0x01
#define  SM10MBS                 0x19     /* 100ns           */
#define  SM5MBS                  0x32     /* 200ns           */
#define  SMOFFSET                0x0F     /* Maxoffset value */
#define  SMWDTR                  0x03
#define  SM8BIT                  0x00
#define  SM16BIT                 0x01
#define  SM32BIT                 0x02
#define  SMIGNORWR               0x23     /* Ignore Wide Residue */


#define  ARBITRATION_DELAY       0x01     /* 2.4us using a 40Mhz clock */
#define  BUS_SETTLE_DELAY        0x01     /* 400ns */
#define  BUS_CLEAR_DELAY         0x01     /* 800ns */



#define  SPHASE_TO               0x0A  /* 10 second timeout waiting for */
#define  SCMD_TO                 0x0F  /* Overall command timeout */



#define  SIX_BYTE_CMD            0x06
#define  TEN_BYTE_CMD            0x0A
#define  TWELVE_BYTE_CMD         0x0C

#define  ASYNC                   0x00
#define  PERI25NS                0x06  /* 25/4ns to next clock for xbow. */
#define  SYNC10MBS               0x19
#define  SYNC5MBS                0x32
#define  MAX_OFFSET              0x0F  /* Maxbyteoffset for Sync Xfers */

#endif
/*----------------------------------------------------------------------
 *  
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   eeprom.h  $
 *
 *   Description:  Definitions for EEPROM related structures
 *
 *   $Date: 1996/11/13 18:28:39 $
 *
 *   $Revision: 1.4 $
 *
 *----------------------------------------------------------------------*/

#ifndef __EEPROM__
#define __EEPROM__

/*#include <globals.h>*/

#define  EEPROM_WD_CNT     256

#define  EEPROM_CHECK_SUM  0
#define  FW_SIGNATURE      2
#define  MODEL_NUMB_0      4
#define  MODEL_NUMB_1      5
#define  MODEL_NUMB_2      6
#define  MODEL_NUMB_3      7
#define  MODEL_NUMB_4      8
#define  MODEL_NUMB_5      9
#define  IO_BASE_ADDR      10
#define  IRQ_NUMBER        12
#define  PCI_INT_PIN       13
#define  BUS_DELAY         14       /*On time in byte 14 off delay in 15 */
#define  SYSTEM_CONFIG     16
#define  SCSI_CONFIG       17
#define  BIOS_CONFIG       18
#define  SPIN_UP_DELAY     19
#define  SCAM_CONFIG       20
#define  ADAPTER_SCSI_ID   24


#define  IGNORE_B_SCAN     32
#define  SEND_START_ENA    34
#define  DEVICE_ENABLE     36

#define  SYNC_RATE_TBL     38
#define  SYNC_RATE_TBL01   38
#define  SYNC_RATE_TBL23   40
#define  SYNC_RATE_TBL45   42
#define  SYNC_RATE_TBL67   44
#define  SYNC_RATE_TBL89   46
#define  SYNC_RATE_TBLab   48
#define  SYNC_RATE_TBLcd   50
#define  SYNC_RATE_TBLef   52



#define  EE_SCAMBASE      256 



   #define  DOM_MASTER     (BIT(0) + BIT(1))
   #define  SCAM_ENABLED   BIT(2)
   #define  SCAM_LEVEL2    BIT(3)


	#define	RENEGO_ENA		BITW(10)
	#define	CONNIO_ENA		BITW(11)
   #define  GREEN_PC_ENA   BITW(12)


   #define  AUTO_RATE_00   00
   #define  AUTO_RATE_05   01
   #define  AUTO_RATE_10   02
   #define  AUTO_RATE_20   03

   #define  WIDE_NEGO_BIT     BIT(7)
   #define  DISC_ENABLE_BIT   BIT(6)


#endif
/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   harpoon.h  $
 *
 *   Description:  Register definitions for HARPOON ASIC.
 *
 *   $Date: 1997/07/09 21:44:36 $
 *
 *   $Revision: 1.9 $
 *
 *----------------------------------------------------------------------*/


/*#include <globals.h>*/

#ifndef __HARPOON__
#define __HARPOON__


   #define  hp_vendor_id_0       0x00		/* LSB */
      #define  ORION_VEND_0   0x4B
 
   #define  hp_vendor_id_1       0x01		/* MSB */
      #define  ORION_VEND_1   0x10

   #define  hp_device_id_0       0x02		/* LSB */
      #define  ORION_DEV_0    0x30 

   #define  hp_device_id_1       0x03		/* MSB */
      #define  ORION_DEV_1    0x81 

	/* Sub Vendor ID and Sub Device ID only available in
		Harpoon Version 2 and higher */

   #define  hp_sub_vendor_id_0   0x04		/* LSB */
   #define  hp_sub_vendor_id_1   0x05		/* MSB */
   #define  hp_sub_device_id_0   0x06		/* LSB */
   #define  hp_sub_device_id_1   0x07		/* MSB */


   #define  hp_dual_addr_lo      0x08
   #define  hp_dual_addr_lmi     0x09
   #define  hp_dual_addr_hmi     0x0A
   #define  hp_dual_addr_hi      0x0B

   #define  hp_semaphore         0x0C
      #define SCCB_MGR_ACTIVE    BIT(0)
      #define TICKLE_ME          BIT(1)
      #define SCCB_MGR_PRESENT   BIT(3)
      #define BIOS_IN_USE        BIT(4)

   #define  hp_user_defined_D    0x0D

   #define  hp_reserved_E        0x0E

   #define  hp_sys_ctrl          0x0F

      #define  STOP_CLK          BIT(0)      /*Turn off BusMaster Clock */
      #define  DRVR_RST          BIT(1)      /*Firmware Reset to 80C15 chip */
      #define  HALT_MACH         BIT(3)      /*Halt State Machine      */
      #define  HARD_ABORT        BIT(4)      /*Hard Abort              */
      #define  DIAG_MODE         BIT(5)      /*Diagnostic Mode         */

      #define  BM_ABORT_TMOUT    0x50        /*Halt State machine time out */

   #define  hp_sys_cfg           0x10

      #define  DONT_RST_FIFO     BIT(7)      /*Don't reset FIFO      */


   #define  hp_host_ctrl0        0x11

      #define  DUAL_ADDR_MODE    BIT(0)   /*Enable 64-bit addresses */
      #define  IO_MEM_SPACE      BIT(1)   /*I/O Memory Space    */
      #define  RESOURCE_LOCK     BIT(2)   /*Enable Resource Lock */
      #define  IGNOR_ACCESS_ERR  BIT(3)   /*Ignore Access Error */
      #define  HOST_INT_EDGE     BIT(4)   /*Host interrupt level/edge mode sel */
      #define  SIX_CLOCKS        BIT(5)   /*6 Clocks between Strobe   */
      #define  DMA_EVEN_PARITY   BIT(6)   /*Enable DMA Enen Parity */

/*
      #define  BURST_MODE        BIT(0)
*/

   #define  hp_reserved_12       0x12

   #define  hp_host_blk_cnt      0x13

      #define  XFER_BLK1         0x00     /*     0 0 0  1 byte per block*/
      #define  XFER_BLK2         0x01     /*     0 0 1  2 byte per block*/
      #define  XFER_BLK4         0x02     /*     0 1 0  4 byte per block*/
      #define  XFER_BLK8         0x03     /*     0 1 1  8 byte per block*/
      #define  XFER_BLK16        0x04     /*     1 0 0 16 byte per block*/
      #define  XFER_BLK32        0x05     /*     1 0 1 32 byte per block*/
      #define  XFER_BLK64        0x06     /*     1 1 0 64 byte per block*/
   
      #define  BM_THRESHOLD      0x40     /* PCI mode can only xfer 16 bytes*/


   #define  hp_reserved_14       0x14
   #define  hp_reserved_15       0x15
   #define  hp_reserved_16       0x16

   #define  hp_int_mask          0x17

      #define  INT_CMD_COMPL     BIT(0)   /* DMA command complete   */
      #define  INT_EXT_STATUS    BIT(1)   /* Extended Status Set    */
      #define  INT_SCSI          BIT(2)   /* Scsi block interrupt   */
      #define  INT_FIFO_RDY      BIT(4)   /* FIFO data ready        */


   #define  hp_xfer_cnt_lo       0x18
   #define  hp_xfer_cnt_mi       0x19
   #define  hp_xfer_cnt_hi       0x1A
   #define  hp_xfer_cmd          0x1B

      #define  XFER_HOST_DMA     0x00     /*     0 0 0 Transfer Host -> DMA */
      #define  XFER_DMA_HOST     0x01     /*     0 0 1 Transfer DMA  -> Host */
      #define  XFER_HOST_MPU     0x02     /*     0 1 0 Transfer Host -> MPU  */
      #define  XFER_MPU_HOST     0x03     /*     0 1 1 Transfer MPU  -> Host */
      #define  XFER_DMA_MPU      0x04     /*     1 0 0 Transfer DMA  -> MPU  */
      #define  XFER_MPU_DMA      0x05     /*     1 0 1 Transfer MPU  -> DMA  */
      #define  SET_SEMAPHORE     0x06     /*     1 1 0 Set Semaphore         */
      #define  XFER_NOP          0x07     /*     1 1 1 Transfer NOP          */
      #define  XFER_MB_MPU       0x06     /*     1 1 0 Transfer MB -> MPU */
      #define  XFER_MB_DMA       0x07     /*     1 1 1 Transfer MB -> DMA */


      #define  XFER_HOST_AUTO    0x00     /*     0 0 Auto Transfer Size   */
      #define  XFER_HOST_8BIT    0x08     /*     0 1 8 BIT Transfer Size  */
      #define  XFER_HOST_16BIT   0x10     /*     1 0 16 BIT Transfer Size */
      #define  XFER_HOST_32BIT   0x18     /*     1 1 32 BIT Transfer Size */

      #define  XFER_DMA_8BIT     0x20     /*     0 1 8 BIT  Transfer Size */
      #define  XFER_DMA_16BIT    0x40     /*     1 0 16 BIT Transfer Size */

      #define  DISABLE_INT       BIT(7)   /*Do not interrupt at end of cmd. */

      #define  HOST_WRT_CMD      ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
      #define  HOST_RD_CMD       ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
      #define  WIDE_HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_16BIT))
      #define  WIDE_HOST_RD_CMD  ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_16BIT))

   #define  hp_host_addr_lo      0x1C
   #define  hp_host_addr_lmi     0x1D
   #define  hp_host_addr_hmi     0x1E
   #define  hp_host_addr_hi      0x1F

   #define  hp_pio_data          0x20
   #define  hp_reserved_21       0x21
   #define  hp_ee_ctrl           0x22

      #define  EXT_ARB_ACK       BIT(7)
      #define  SCSI_TERM_ENA_H   BIT(6)   /* SCSI high byte terminator */
      #define  SEE_MS            BIT(5)
      #define  SEE_CS            BIT(3)
      #define  SEE_CLK           BIT(2)
      #define  SEE_DO            BIT(1)
      #define  SEE_DI            BIT(0)

      #define  EE_READ           0x06
      #define  EE_WRITE          0x05
      #define  EWEN              0x04
      #define  EWEN_ADDR         0x03C0
      #define  EWDS              0x04
      #define  EWDS_ADDR         0x0000

   #define  hp_brdctl            0x23

      #define  DAT_7             BIT(7)
      #define  DAT_6             BIT(6)
      #define  DAT_5             BIT(5)
      #define  BRD_STB           BIT(4)
      #define  BRD_CS            BIT(3)
      #define  BRD_WR            BIT(2)

   #define  hp_reserved_24       0x24
   #define  hp_reserved_25       0x25




   #define  hp_bm_ctrl           0x26

      #define  SCSI_TERM_ENA_L   BIT(0)   /*Enable/Disable external terminators */
      #define  FLUSH_XFER_CNTR   BIT(1)   /*Flush transfer counter */
      #define  BM_XFER_MIN_8     BIT(2)   /*Enable bus master transfer of 9 */
      #define  BIOS_ENA          BIT(3)   /*Enable BIOS/FLASH Enable */
      #define  FORCE1_XFER       BIT(5)   /*Always xfer one byte in byte mode */
      #define  FAST_SINGLE       BIT(6)   /*?? */

      #define  BMCTRL_DEFAULT    (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)

   #define  hp_reserved_27       0x27

   #define  hp_sg_addr           0x28
   #define  hp_page_ctrl         0x29

      #define  SCATTER_EN        BIT(0)   
      #define  SGRAM_ARAM        BIT(1)   
      #define  BIOS_SHADOW       BIT(2)   
      #define  G_INT_DISABLE     BIT(3)   /* Enable/Disable all Interrupts */
      #define  NARROW_SCSI_CARD  BIT(4)   /* NARROW/WIDE SCSI config pin */

   #define  hp_reserved_2A       0x2A
   #define  hp_pci_cmd_cfg       0x2B

      #define  IO_SPACE_ENA      BIT(0)   /*enable I/O space */
      #define  MEM_SPACE_ENA     BIT(1)   /*enable memory space */
      #define  BUS_MSTR_ENA      BIT(2)   /*enable bus master operation */
      #define  MEM_WI_ENA        BIT(4)   /*enable Write and Invalidate */
      #define  PAR_ERR_RESP      BIT(6)   /*enable parity error responce. */

   #define  hp_reserved_2C       0x2C

   #define  hp_pci_stat_cfg      0x2D

      #define  DATA_PARITY_ERR   BIT(0)   
      #define  REC_TARGET_ABORT  BIT(4)   /*received Target abort */
      #define  REC_MASTER_ABORT  BIT(5)   /*received Master abort */
      #define  SIG_SYSTEM_ERR    BIT(6)   
      #define  DETECTED_PAR_ERR  BIT(7)   

   #define  hp_reserved_2E       0x2E

   #define  hp_sys_status        0x2F

      #define  SLV_DATA_RDY      BIT(0)   /*Slave data ready */
      #define  XFER_CNT_ZERO     BIT(1)   /*Transfer counter = 0 */
      #define  BM_FIFO_EMPTY     BIT(2)   /*FIFO empty */
      #define  BM_FIFO_FULL      BIT(3)   /*FIFO full */
      #define  HOST_OP_DONE      BIT(4)   /*host operation done */
      #define  DMA_OP_DONE       BIT(5)   /*DMA operation done */
      #define  SLV_OP_DONE       BIT(6)   /*Slave operation done */
      #define  PWR_ON_FLAG       BIT(7)   /*Power on flag */

   #define  hp_reserved_30       0x30

   #define  hp_host_status0      0x31

      #define  HOST_TERM         BIT(5)   /*Host Terminal Count */
      #define  HOST_TRSHLD       BIT(6)   /*Host Threshold      */
      #define  CONNECTED_2_HOST  BIT(7)   /*Connected to Host   */

   #define  hp_reserved_32       0x32

   #define  hp_rev_num           0x33

      #define  REV_A_CONST       0x0E
      #define  REV_B_CONST       0x0E

   #define  hp_stack_data        0x34
   #define  hp_stack_addr        0x35

   #define  hp_ext_status        0x36

      #define  BM_FORCE_OFF      BIT(0)   /*Bus Master is forced to get off */
      #define  PCI_TGT_ABORT     BIT(0)   /*PCI bus master transaction aborted */
      #define  PCI_DEV_TMOUT     BIT(1)   /*PCI Device Time out */
      #define  FIFO_TC_NOT_ZERO  BIT(2)   /*FIFO or transfer counter not zero */
      #define  CHIP_RST_OCCUR    BIT(3)   /*Chip reset occurs */
      #define  CMD_ABORTED       BIT(4)   /*Command aborted */
      #define  BM_PARITY_ERR     BIT(5)   /*parity error on data received   */
      #define  PIO_OVERRUN       BIT(6)   /*Slave data overrun */
      #define  BM_CMD_BUSY       BIT(7)   /*Bus master transfer command busy */
      #define  BAD_EXT_STATUS    (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
                                  BM_PARITY_ERR | PIO_OVERRUN)

   #define  hp_int_status        0x37
      
      #define  BM_CMD_CMPL       BIT(0)   /*Bus Master command complete */
      #define  EXT_STATUS_ON     BIT(1)   /*Extended status is valid */
      #define  SCSI_INTERRUPT    BIT(2)   /*Global indication of a SCSI int. */
      #define  BM_FIFO_RDY       BIT(4)   
      #define  INT_ASSERTED      BIT(5)   /* */
      #define  SRAM_BUSY         BIT(6)   /*Scatter/Gather RAM busy */
      #define  CMD_REG_BUSY      BIT(7)                                       


   #define  hp_fifo_cnt          0x38
   #define  hp_curr_host_cnt     0x39
   #define  hp_reserved_3A       0x3A
   #define  hp_fifo_in_addr      0x3B

   #define  hp_fifo_out_addr     0x3C
   #define  hp_reserved_3D       0x3D
   #define  hp_reserved_3E       0x3E
   #define  hp_reserved_3F       0x3F



   extern USHORT default_intena;

   #define  hp_intena		 0x40

      #define  RESET		 BITW(7)
      #define  PROG_HLT		 BITW(6)  
      #define  PARITY		 BITW(5)
      #define  FIFO		 BITW(4)
      #define  SEL		 BITW(3)
      #define  SCAM_SEL		 BITW(2) 
      #define  RSEL		 BITW(1)
      #define  TIMEOUT		 BITW(0)
      #define  BUS_FREE		 BITW(15)
      #define  XFER_CNT_0	 BITW(14)
      #define  PHASE		 BITW(13)
      #define  IUNKWN		 BITW(12)
      #define  ICMD_COMP	 BITW(11)
      #define  ITICKLE		 BITW(10)
      #define  IDO_STRT		 BITW(9)
      #define  ITAR_DISC	 BITW(8)
      #define  AUTO_INT		 (BITW(12)+BITW(11)+BITW(10)+BITW(9)+BITW(8))
      #define  CLR_ALL_INT	 0xFFFF
      #define  CLR_ALL_INT_1	 0xFF00

   #define  hp_intstat		 0x42

   #define  hp_scsisig           0x44

      #define  SCSI_SEL          BIT(7)
      #define  SCSI_BSY          BIT(6)
      #define  SCSI_REQ          BIT(5)
      #define  SCSI_ACK          BIT(4)
      #define  SCSI_ATN          BIT(3)
      #define  SCSI_CD           BIT(2)
      #define  SCSI_MSG          BIT(1)
      #define  SCSI_IOBIT        BIT(0)

      #define  S_SCSI_PHZ        (BIT(2)+BIT(1)+BIT(0))
      #define  S_CMD_PH          (BIT(2)              )
      #define  S_MSGO_PH         (BIT(2)+BIT(1)       )
      #define  S_STAT_PH         (BIT(2)       +BIT(0))
      #define  S_MSGI_PH         (BIT(2)+BIT(1)+BIT(0))
      #define  S_DATAI_PH        (              BIT(0))
      #define  S_DATAO_PH        0x00
      #define  S_ILL_PH          (       BIT(1)       )

   #define  hp_scsictrl_0        0x45

      #define  NO_ARB            BIT(7)
      #define  SEL_TAR           BIT(6)
      #define  ENA_ATN           BIT(4)
      #define  ENA_RESEL         BIT(2)
      #define  SCSI_RST          BIT(1)
      #define  ENA_SCAM_SEL      BIT(0)



   #define  hp_portctrl_0        0x46

      #define  SCSI_PORT         BIT(7)
      #define  SCSI_INBIT        BIT(6)
      #define  DMA_PORT          BIT(5)
      #define  DMA_RD            BIT(4)
      #define  HOST_PORT         BIT(3)
      #define  HOST_WRT          BIT(2)
      #define  SCSI_BUS_EN       BIT(1)
      #define  START_TO          BIT(0)

   #define  hp_scsireset         0x47

      #define  SCSI_TAR          BIT(7)
      #define  SCSI_INI          BIT(6)
      #define  SCAM_EN           BIT(5)
      #define  ACK_HOLD          BIT(4)
      #define  DMA_RESET         BIT(3)
      #define  HPSCSI_RESET      BIT(2)
      #define  PROG_RESET        BIT(1)
      #define  FIFO_CLR          BIT(0)

   #define  hp_xfercnt_0         0x48
   #define  hp_xfercnt_1         0x49
   #define  hp_xfercnt_2         0x4A
   #define  hp_xfercnt_3         0x4B

   #define  hp_fifodata_0        0x4C
   #define  hp_fifodata_1        0x4D
   #define  hp_addstat           0x4E

      #define  SCAM_TIMER        BIT(7)
      #define  AUTO_RUNNING      BIT(6)
      #define  FAST_SYNC         BIT(5)
      #define  SCSI_MODE8        BIT(3)
      #define  SCSI_PAR_ERR      BIT(0)

   #define  hp_prgmcnt_0         0x4F

      #define  AUTO_PC_MASK      0x3F

   #define  hp_selfid_0          0x50
   #define  hp_selfid_1          0x51
   #define  hp_arb_id            0x52

      #define  ARB_ID            (BIT(3) + BIT(2) + BIT(1) + BIT(0))

   #define  hp_select_id         0x53

      #define  RESEL_ID          (BIT(7) + BIT(6) + BIT(5) + BIT(4))
      #define  SELECT_ID         (BIT(3) + BIT(2) + BIT(1) + BIT(0))

   #define  hp_synctarg_base     0x54
   #define  hp_synctarg_12       0x54
   #define  hp_synctarg_13       0x55
   #define  hp_synctarg_14       0x56
   #define  hp_synctarg_15       0x57

   #define  hp_synctarg_8        0x58
   #define  hp_synctarg_9        0x59
   #define  hp_synctarg_10       0x5A
   #define  hp_synctarg_11       0x5B

   #define  hp_synctarg_4        0x5C
   #define  hp_synctarg_5        0x5D
   #define  hp_synctarg_6        0x5E
   #define  hp_synctarg_7        0x5F

   #define  hp_synctarg_0        0x60
   #define  hp_synctarg_1        0x61
   #define  hp_synctarg_2        0x62
   #define  hp_synctarg_3        0x63

      #define  RATE_20MB         0x00
      #define  RATE_10MB         (              BIT(5))
      #define  RATE_6_6MB        (       BIT(6)       )   
      #define  RATE_5MB          (       BIT(6)+BIT(5))
      #define  RATE_4MB          (BIT(7)              )
      #define  RATE_3_33MB       (BIT(7)       +BIT(5))
      #define  RATE_2_85MB       (BIT(7)+BIT(6)       )
      #define  RATE_2_5MB        (BIT(7)+BIT(5)+BIT(6))
      #define  NEXT_CLK          BIT(5)
      #define  SLOWEST_SYNC      (BIT(7)+BIT(6)+BIT(5))
      #define  NARROW_SCSI       BIT(4)
      #define  SYNC_OFFSET       (BIT(3) + BIT(2) + BIT(1) + BIT(0))
      #define  DEFAULT_ASYNC     0x00
      #define  DEFAULT_OFFSET    0x0F

   #define  hp_autostart_0       0x64
   #define  hp_autostart_1       0x65
   #define  hp_autostart_2       0x66
   #define  hp_autostart_3       0x67



      #define  DISABLE  0x00
      #define  AUTO_IMMED    BIT(5)
      #define  SELECT   BIT(6)
      #define  RESELECT (BIT(6)+BIT(5))
      #define  BUSFREE  BIT(7)
      #define  XFER_0   (BIT(7)+BIT(5))
      #define  END_DATA (BIT(7)+BIT(6))
      #define  MSG_PHZ  (BIT(7)+BIT(6)+BIT(5))

   #define  hp_gp_reg_0          0x68
   #define  hp_gp_reg_1          0x69
   #define  hp_gp_reg_2          0x6A
   #define  hp_gp_reg_3          0x6B

   #define  hp_seltimeout        0x6C


      #define  TO_2ms            0x54      /* 2.0503ms */
      #define  TO_4ms            0x67      /* 3.9959ms */

      #define  TO_5ms            0x03      /* 4.9152ms */
      #define  TO_10ms           0x07      /* 11.xxxms */
      #define  TO_250ms          0x99      /* 250.68ms */
      #define  TO_290ms          0xB1      /* 289.99ms */
      #define  TO_350ms          0xD6      /* 350.62ms */
      #define  TO_417ms          0xFF      /* 417.79ms */

   #define  hp_clkctrl_0         0x6D

      #define  PWR_DWN           BIT(6)
      #define  ACTdeassert       BIT(4)
      #define  ATNonErr          BIT(3)
      #define  CLK_30MHZ         BIT(1)
      #define  CLK_40MHZ         (BIT(1) + BIT(0))
      #define  CLK_50MHZ         BIT(2)

      #define  CLKCTRL_DEFAULT   (ACTdeassert | CLK_40MHZ)

   #define  hp_fiforead          0x6E
   #define  hp_fifowrite         0x6F

   #define  hp_offsetctr         0x70
   #define  hp_xferstat          0x71

      #define  FIFO_FULL         BIT(7)
      #define  FIFO_EMPTY        BIT(6)
      #define  FIFO_MASK         0x3F   /* Mask for the FIFO count value. */
      #define  FIFO_LEN          0x20

   #define  hp_portctrl_1        0x72

      #define  EVEN_HOST_P       BIT(5)
      #define  INVT_SCSI         BIT(4)
      #define  CHK_SCSI_P        BIT(3)
      #define  HOST_MODE8        BIT(0)
      #define  HOST_MODE16       0x00

   #define  hp_xfer_pad          0x73

      #define  ID_UNLOCK         BIT(3)
      #define  XFER_PAD          BIT(2)

   #define  hp_scsidata_0        0x74
   #define  hp_scsidata_1        0x75
   #define  hp_timer_0           0x76
   #define  hp_timer_1           0x77

   #define  hp_reserved_78       0x78
   #define  hp_reserved_79       0x79
   #define  hp_reserved_7A       0x7A
   #define  hp_reserved_7B       0x7B

   #define  hp_reserved_7C       0x7C
   #define  hp_reserved_7D       0x7D
   #define  hp_reserved_7E       0x7E
   #define  hp_reserved_7F       0x7F

   #define  hp_aramBase          0x80
   #define  BIOS_DATA_OFFSET     0x60
   #define  BIOS_RELATIVE_CARD   0x64




      #define  AUTO_LEN 0x80
      #define  AR0      0x00
      #define  AR1      BITW(8)
      #define  AR2      BITW(9)
      #define  AR3      (BITW(9) + BITW(8))
      #define  SDATA    BITW(10)

      #define  NOP_OP   0x00        /* Nop command */

      #define  CRD_OP   BITW(11)     /* Cmp Reg. w/ Data */

      #define  CRR_OP   BITW(12)     /* Cmp Reg. w. Reg. */

      #define  CBE_OP   (BITW(14)+BITW(12)+BITW(11)) /* Cmp SCSI cmd class & Branch EQ */
      
      #define  CBN_OP   (BITW(14)+BITW(13))  /* Cmp SCSI cmd class & Branch NOT EQ */
      
      #define  CPE_OP   (BITW(14)+BITW(11))  /* Cmp SCSI phs & Branch EQ */

      #define  CPN_OP   (BITW(14)+BITW(12))  /* Cmp SCSI phs & Branch NOT EQ */


      #define  ADATA_OUT   0x00     
      #define  ADATA_IN    BITW(8)
      #define  ACOMMAND    BITW(10)
      #define  ASTATUS     (BITW(10)+BITW(8))
      #define  AMSG_OUT    (BITW(10)+BITW(9))
      #define  AMSG_IN     (BITW(10)+BITW(9)+BITW(8))
      #define  AILLEGAL    (BITW(9)+BITW(8))


      #define  BRH_OP   BITW(13)   /* Branch */

      
      #define  ALWAYS   0x00
      #define  EQUAL    BITW(8)
      #define  NOT_EQ   BITW(9)

      #define  TCB_OP   (BITW(13)+BITW(11))    /* Test condition & branch */

      
      #define  ATN_SET     BITW(8)
      #define  ATN_RESET   BITW(9)
      #define  XFER_CNT    (BITW(9)+BITW(8))
      #define  FIFO_0      BITW(10)
      #define  FIFO_NOT0   (BITW(10)+BITW(8))
      #define  T_USE_SYNC0 (BITW(10)+BITW(9))


      #define  MPM_OP   BITW(15)        /* Match phase and move data */

      #define  MDR_OP   (BITW(12)+BITW(11)) /* Move data to Reg. */

      #define  MRR_OP   BITW(14)        /* Move DReg. to Reg. */


      #define  S_IDREG  (BIT(2)+BIT(1)+BIT(0))


      #define  D_AR0    0x00
      #define  D_AR1    BIT(0)
      #define  D_AR2    BIT(1)
      #define  D_AR3    (BIT(1) + BIT(0))
      #define  D_SDATA  BIT(2)
      #define  D_BUCKET (BIT(2) + BIT(1) + BIT(0))


      #define  ADR_OP   (BITW(13)+BITW(12)) /* Logical AND Reg. w. Data */

      #define  ADS_OP   (BITW(14)+BITW(13)+BITW(12)) 

      #define  ODR_OP   (BITW(13)+BITW(12)+BITW(11))  

      #define  ODS_OP   (BITW(14)+BITW(13)+BITW(12)+BITW(11))  

      #define  STR_OP   (BITW(15)+BITW(14)) /* Store to A_Reg. */

      #define  AINT_ENA1   0x00
      #define  AINT_STAT1  BITW(8)
      #define  ASCSI_SIG   BITW(9)
      #define  ASCSI_CNTL  (BITW(9)+BITW(8))
      #define  APORT_CNTL  BITW(10)
      #define  ARST_CNTL   (BITW(10)+BITW(8))
      #define  AXFERCNT0   (BITW(10)+BITW(9))
      #define  AXFERCNT1   (BITW(10)+BITW(9)+BITW(8))
      #define  AXFERCNT2   BITW(11)
      #define  AFIFO_DATA  (BITW(11)+BITW(8))
      #define  ASCSISELID  (BITW(11)+BITW(9))
      #define  ASCSISYNC0  (BITW(11)+BITW(9)+BITW(8))


      #define  RAT_OP      (BITW(14)+BITW(13)+BITW(11))

      #define  SSI_OP      (BITW(15)+BITW(11))


      #define  SSI_ITAR_DISC	(ITAR_DISC >> 8)
      #define  SSI_IDO_STRT	(IDO_STRT >> 8)
      #define  SSI_IDI_STRT	(IDO_STRT >> 8)

      #define  SSI_ICMD_COMP	(ICMD_COMP >> 8)
      #define  SSI_ITICKLE	(ITICKLE >> 8)

      #define  SSI_IUNKWN	(IUNKWN >> 8)
      #define  SSI_INO_CC	(IUNKWN >> 8)
      #define  SSI_IRFAIL	(IUNKWN >> 8)


      #define  NP    0x10     /*Next Phase */
      #define  NTCMD 0x02     /*Non- Tagged Command start */
      #define  CMDPZ 0x04     /*Command phase */
      #define  DINT  0x12     /*Data Out/In interrupt */
      #define  DI    0x13     /*Data Out */
      #define  MI    0x14     /*Message In */
      #define  DC    0x19     /*Disconnect Message */
      #define  ST    0x1D     /*Status Phase */
      #define  UNKNWN 0x24    /*Unknown bus action */
      #define  CC    0x25     /*Command Completion failure */
      #define  TICK  0x26     /*New target reselected us. */
      #define  RFAIL 0x27     /*Reselection failed */
      #define  SELCHK 0x28     /*Select & Check SCSI ID latch reg */


      #define  ID_MSG_STRT    hp_aramBase + 0x00
      #define  NON_TAG_ID_MSG hp_aramBase + 0x06
      #define  CMD_STRT       hp_aramBase + 0x08
      #define  SYNC_MSGS      hp_aramBase + 0x08





      #define  TAG_STRT          0x00
      #define  SELECTION_START   0x00
      #define  DISCONNECT_START  0x10/2
      #define  END_DATA_START    0x14/2
      #define  NONTAG_STRT       0x02/2
      #define  CMD_ONLY_STRT     CMDPZ/2
      #define  TICKLE_STRT     TICK/2
      #define  SELCHK_STRT     SELCHK/2




#define mEEPROM_CLK_DELAY(port) (RD_HARPOON(port+hp_intstat_1))

#define mWAIT_10MS(port) (RD_HARPOON(port+hp_intstat_1))


#define CLR_XFER_CNT(port) (WR_HARPOON(port+hp_xfercnt_0, 0x00))

#define SET_XFER_CNT(port, data) (WR_HARP32(port,hp_xfercnt_0,data))

#define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
/* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
                                 xfercnt <<= 16,\
                                 xfercnt |= RDW_HARPOON((USHORT)(port+hp_xfercnt_0)))
 */
#if defined(DOS)
#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((USHORT)(port+hp_host_addr_lo), (USHORT)(addr & 0x0000FFFFL)),\
         addr >>= 16,\
         WRW_HARPOON((USHORT)(port+hp_host_addr_hmi), (USHORT)(addr & 0x0000FFFFL)),\
         WR_HARP32(port,hp_xfercnt_0,count),\
         WRW_HARPOON((USHORT)(port+hp_xfer_cnt_lo), (USHORT)(count & 0x0000FFFFL)),\
         count >>= 16,\
         WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
#else
#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (USHORT)(addr & 0x0000FFFFL)),\
         addr >>= 16,\
         WRW_HARPOON((port+hp_host_addr_hmi), (USHORT)(addr & 0x0000FFFFL)),\
         WR_HARP32(port,hp_xfercnt_0,count),\
         WRW_HARPOON((port+hp_xfer_cnt_lo), (USHORT)(count & 0x0000FFFFL)),\
         count >>= 16,\
         WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
#endif

#define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
                          WR_HARPOON(port+hp_scsisig, S_ILL_PH);}


#define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
                          WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}

#define ACCEPT_STAT(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
                          WR_HARPOON(port+hp_scsisig, S_ILL_PH);}

#define ACCEPT_STAT_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
                          WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}

#define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
                        WR_HARPOON(port+hp_scsireset, 0x00))

#define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
                             (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))

#define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
                             (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))

#define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
                             (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))

#define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
                             (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))



#endif


#if (FW_TYPE==_UCB_MGR_)
void ReadNVRam(PSCCBcard pCurrCard,PUCB p_ucb);
void WriteNVRam(PSCCBcard pCurrCard,PUCB p_ucb);
void UpdateCheckSum(u32bits baseport);
#endif // (FW_TYPE==_UCB_MGR_)

#if defined(DOS)
UCHAR sfm(USHORT port, PSCCB pcurrSCCB);
void  scsiStartAuto(USHORT port);
UCHAR sisyncn(USHORT port, UCHAR p_card, UCHAR syncFlag);
void  ssel(USHORT port, UCHAR p_card);
void  sres(USHORT port, UCHAR p_card, PSCCBcard pCurrCard);
void  sdecm(UCHAR message, USHORT port, UCHAR p_card);
void  shandem(USHORT port, UCHAR p_card,PSCCB pCurrSCCB);
void  stsyncn(USHORT port, UCHAR p_card);
void  sisyncr(USHORT port,UCHAR sync_pulse, UCHAR offset);
void  sssyncv(USHORT p_port, UCHAR p_id, UCHAR p_sync_value, PSCCBMgr_tar_info currTar_Info);
void  sresb(USHORT port, UCHAR p_card);
void  sxfrp(USHORT p_port, UCHAR p_card);
void  schkdd(USHORT port, UCHAR p_card);
UCHAR RdStack(USHORT port, UCHAR index);
void  WrStack(USHORT portBase, UCHAR index, UCHAR data);
UCHAR ChkIfChipInitialized(USHORT ioPort);

#if defined(V302)
UCHAR GetTarLun(USHORT port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun);
#endif

void SendMsg(USHORT port, UCHAR message);
void  queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code);
UCHAR scsellDOS(USHORT p_port, UCHAR targ_id);
#else
UCHAR sfm(ULONG port, PSCCB pcurrSCCB);
void  scsiStartAuto(ULONG port);
UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag);
void  ssel(ULONG port, UCHAR p_card);
void  sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard);
void  sdecm(UCHAR message, ULONG port, UCHAR p_card);
void  shandem(ULONG port, UCHAR p_card,PSCCB pCurrSCCB);
void  stsyncn(ULONG port, UCHAR p_card);
void  sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset);
void  sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value, PSCCBMgr_tar_info currTar_Info);
void  sresb(ULONG port, UCHAR p_card);
void  sxfrp(ULONG p_port, UCHAR p_card);
void  schkdd(ULONG port, UCHAR p_card);
UCHAR RdStack(ULONG port, UCHAR index);
void  WrStack(ULONG portBase, UCHAR index, UCHAR data);
UCHAR ChkIfChipInitialized(ULONG ioPort);

#if defined(V302)
UCHAR GetTarLun(ULONG port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tar, PUCHAR lun);
#endif

void SendMsg(ULONG port, UCHAR message);
void  queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code);
#endif

void  ssenss(PSCCBcard pCurrCard);
void  sinits(PSCCB p_sccb, UCHAR p_card);
void  RNVRamData(PNVRamInfo pNvRamInfo);

#if defined(WIDE_SCSI)
   #if defined(DOS)
   UCHAR siwidn(USHORT port, UCHAR p_card);
   void  stwidn(USHORT port, UCHAR p_card);
   void  siwidr(USHORT port, UCHAR width);
   #else
   UCHAR siwidn(ULONG port, UCHAR p_card);
   void  stwidn(ULONG port, UCHAR p_card);
   void  siwidr(ULONG port, UCHAR width);
   #endif
#endif


void  queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card);
void  queueDisconnect(PSCCB p_SCCB, UCHAR p_card);
void  queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_SCCB, UCHAR p_card);
void  queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card);
void  queueFlushSccb(UCHAR p_card, UCHAR error_code);
void  queueAddSccb(PSCCB p_SCCB, UCHAR card);
UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card);
void  utilUpdateResidual(PSCCB p_SCCB);
USHORT CalcCrc16(UCHAR buffer[]);
UCHAR  CalcLrc(UCHAR buffer[]);


#if defined(DOS)
void  Wait1Second(USHORT p_port);
void  Wait(USHORT p_port, UCHAR p_delay);
void  utilEEWriteOnOff(USHORT p_port,UCHAR p_mode);
void  utilEEWrite(USHORT p_port, USHORT ee_data, USHORT ee_addr);
USHORT utilEERead(USHORT p_port, USHORT ee_addr);
USHORT utilEEReadOrg(USHORT p_port, USHORT ee_addr);
void  utilEESendCmdAddr(USHORT p_port, UCHAR ee_cmd, USHORT ee_addr);
#else
void  Wait1Second(ULONG p_port);
void  Wait(ULONG p_port, UCHAR p_delay);
void  utilEEWriteOnOff(ULONG p_port,UCHAR p_mode);
void  utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr);
USHORT utilEERead(ULONG p_port, USHORT ee_addr);
USHORT utilEEReadOrg(ULONG p_port, USHORT ee_addr);
void  utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr);
#endif



#if defined(OS2)
   void  far phaseDataOut(ULONG port, UCHAR p_card);
   void  far phaseDataIn(ULONG port, UCHAR p_card);
   void  far phaseCommand(ULONG port, UCHAR p_card);
   void  far phaseStatus(ULONG port, UCHAR p_card);
   void  far phaseMsgOut(ULONG port, UCHAR p_card);
   void  far phaseMsgIn(ULONG port, UCHAR p_card);
   void  far phaseIllegal(ULONG port, UCHAR p_card);
#else
   #if defined(DOS)
      void  phaseDataOut(USHORT port, UCHAR p_card);
      void  phaseDataIn(USHORT port, UCHAR p_card);
      void  phaseCommand(USHORT port, UCHAR p_card);
      void  phaseStatus(USHORT port, UCHAR p_card);
      void  phaseMsgOut(USHORT port, UCHAR p_card);
      void  phaseMsgIn(USHORT port, UCHAR p_card);
      void  phaseIllegal(USHORT port, UCHAR p_card);
   #else
      void  phaseDataOut(ULONG port, UCHAR p_card);
      void  phaseDataIn(ULONG port, UCHAR p_card);
      void  phaseCommand(ULONG port, UCHAR p_card);
      void  phaseStatus(ULONG port, UCHAR p_card);
      void  phaseMsgOut(ULONG port, UCHAR p_card);
      void  phaseMsgIn(ULONG port, UCHAR p_card);
      void  phaseIllegal(ULONG port, UCHAR p_card);
   #endif
#endif

#if defined(DOS)
void  phaseDecode(USHORT port, UCHAR p_card);
void  phaseChkFifo(USHORT port, UCHAR p_card);
void  phaseBusFree(USHORT p_port, UCHAR p_card);
#else
void  phaseDecode(ULONG port, UCHAR p_card);
void  phaseChkFifo(ULONG port, UCHAR p_card);
void  phaseBusFree(ULONG p_port, UCHAR p_card);
#endif




#if defined(DOS)
void  XbowInit(USHORT port, UCHAR scamFlg);
void  BusMasterInit(USHORT p_port);
int   DiagXbow(USHORT port);
int   DiagBusMaster(USHORT port);
void  DiagEEPROM(USHORT p_port);
#else
void  XbowInit(ULONG port, UCHAR scamFlg);
void  BusMasterInit(ULONG p_port);
int   DiagXbow(ULONG port);
int   DiagBusMaster(ULONG port);
void  DiagEEPROM(ULONG p_port);
#endif




#if defined(DOS)
void  busMstrAbort(USHORT port);
UCHAR busMstrTimeOut(USHORT port);
void  dataXferProcessor(USHORT port, PSCCBcard pCurrCard);
void  busMstrSGDataXferStart(USHORT port, PSCCB pCurrSCCB);
void  busMstrDataXferStart(USHORT port, PSCCB pCurrSCCB);
void  hostDataXferAbort(USHORT port, UCHAR p_card, PSCCB pCurrSCCB);
#else
void  busMstrAbort(ULONG port);
UCHAR busMstrTimeOut(ULONG port);
void  dataXferProcessor(ULONG port, PSCCBcard pCurrCard);
void  busMstrSGDataXferStart(ULONG port, PSCCB pCurrSCCB);
void  busMstrDataXferStart(ULONG port, PSCCB pCurrSCCB);
void  hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB);
#endif
void  hostDataXferRestart(PSCCB currSCCB);


#if defined (DOS)
UCHAR SccbMgr_bad_isr(USHORT p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int);
#else
UCHAR SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int);

#endif

void  SccbMgrTableInitAll(void);
void  SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card);
void  SccbMgrTableInitTarget(UCHAR p_card, UCHAR target);



void  scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up);

#if defined(DOS)
int   scarb(USHORT p_port, UCHAR p_sel_type);
void  scbusf(USHORT p_port);
void  scsel(USHORT p_port);
void  scasid(UCHAR p_card, USHORT p_port);
UCHAR scxferc(USHORT p_port, UCHAR p_data);
UCHAR scsendi(USHORT p_port, UCHAR p_id_string[]);
UCHAR sciso(USHORT p_port, UCHAR p_id_string[]);
void  scwirod(USHORT p_port, UCHAR p_data_bit);
void  scwiros(USHORT p_port, UCHAR p_data_bit);
UCHAR scvalq(UCHAR p_quintet);
UCHAR scsell(USHORT p_port, UCHAR targ_id);
void  scwtsel(USHORT p_port);
void  inisci(UCHAR p_card, USHORT p_port, UCHAR p_our_id);
void  scsavdi(UCHAR p_card, USHORT p_port);
#else
int   scarb(ULONG p_port, UCHAR p_sel_type);
void  scbusf(ULONG p_port);
void  scsel(ULONG p_port);
void  scasid(UCHAR p_card, ULONG p_port);
UCHAR scxferc(ULONG p_port, UCHAR p_data);
UCHAR scsendi(ULONG p_port, UCHAR p_id_string[]);
UCHAR sciso(ULONG p_port, UCHAR p_id_string[]);
void  scwirod(ULONG p_port, UCHAR p_data_bit);
void  scwiros(ULONG p_port, UCHAR p_data_bit);
UCHAR scvalq(UCHAR p_quintet);
UCHAR scsell(ULONG p_port, UCHAR targ_id);
void  scwtsel(ULONG p_port);
void  inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id);
void  scsavdi(UCHAR p_card, ULONG p_port);
#endif
UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[]);


#if defined(DOS)
void  autoCmdCmplt(USHORT p_port, UCHAR p_card);
void  autoLoadDefaultMap(USHORT p_port);
#else
void  autoCmdCmplt(ULONG p_port, UCHAR p_card);
void  autoLoadDefaultMap(ULONG p_port);
#endif



#if (FW_TYPE==_SCCB_MGR_)
	void  OS_start_timer(unsigned long ioport, unsigned long timeout);
	void  OS_stop_timer(unsigned long ioport, unsigned long timeout);
	void  OS_disable_int(unsigned char intvec);
	void  OS_enable_int(unsigned char intvec);
	void  OS_delay(unsigned long count);
	int   OS_VirtToPhys(u32bits CardHandle, u32bits *physaddr, u32bits *virtaddr);
	#if !(defined(UNIX) || defined(OS2) || defined(SOLARIS_REAL_MODE)) 
	void  OS_Lock(PSCCBMGR_INFO pCardInfo);
	void  OS_UnLock(PSCCBMGR_INFO pCardInfo);
#endif // if FW_TYPE == ...

#endif

extern SCCBCARD BL_Card[MAX_CARDS];
extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];


#if defined(OS2)
   extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR);
#else
   #if defined(DOS)
      extern void (*s_PhaseTbl[8]) (USHORT, UCHAR);
   #else
      extern void (*s_PhaseTbl[8]) (ULONG, UCHAR);
   #endif
#endif

extern SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR];
extern NVRAMINFO nvRamInfo[MAX_MB_CARDS];
#if defined(DOS) || defined(OS2)
extern UCHAR temp_id_string[ID_STRING_LENGTH];
#endif
extern UCHAR scamHAString[];


extern UCHAR mbCards;
#if defined(BUGBUG)
extern UCHAR debug_int[MAX_CARDS][debug_size];
extern UCHAR debug_index[MAX_CARDS];
void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
#endif

#if (FW_TYPE==_SCCB_MGR_)
#if defined(DOS)
   extern UCHAR first_time;
#endif
#endif /* (FW_TYPE==_SCCB_MGR_) */

#if (FW_TYPE==_UCB_MGR_)
#if defined(DOS)
   extern u08bits first_time;
#endif
#endif /* (FW_TYPE==_UCB_MGR_) */

#if defined(BUGBUG)
void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
#endif

extern unsigned int SccbGlobalFlags;


#ident "$Id: sccb.c 1.18 1997/06/10 16:47:04 mohan Exp $"
/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   sccb.c  $
 *
 *   Description:  Functions relating to handling of the SCCB interface
 *                 between the device driver and the HARPOON.
 *
 *   $Date: 1997/06/10 16:47:04 $
 *
 *   $Revision: 1.18 $
 *
 *----------------------------------------------------------------------*/

/*#include <globals.h>*/

#if (FW_TYPE==_UCB_MGR_)
	/*#include <budi.h>*/
	/*#include <budioctl.h>*/
#endif

/*#include <sccbmgr.h>*/
/*#include <blx30.h>*/
/*#include <target.h>*/
/*#include <eeprom.h>*/
/*#include <scsi2.h>*/
/*#include <harpoon.h>*/



#if (FW_TYPE==_SCCB_MGR_)
#define mOS_Lock(card)    OS_Lock((PSCCBMGR_INFO)(((PSCCBcard)card)->cardInfo))
#define mOS_UnLock(card)  OS_UnLock((PSCCBMGR_INFO)(((PSCCBcard)card)->cardInfo))
#else /* FW_TYPE==_UCB_MGR_ */
#define mOS_Lock(card)    OS_Lock((u32bits)(((PSCCBcard)card)->ioPort))
#define mOS_UnLock(card)  OS_UnLock((u32bits)(((PSCCBcard)card)->ioPort))
#endif


/*
extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
extern SCCBCARD BL_Card[MAX_CARDS];

extern NVRAMINFO nvRamInfo[MAX_MB_CARDS];
extern UCHAR mbCards;

#if defined (OS2)
   extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR);
#else
   #if defined(DOS)
      extern void (*s_PhaseTbl[8]) (USHORT, UCHAR);
   #else
      extern void (*s_PhaseTbl[8]) (ULONG, UCHAR);
   #endif
#endif


#if defined(BUGBUG)
extern UCHAR debug_int[MAX_CARDS][debug_size];
extern UCHAR debug_index[MAX_CARDS];
void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
#endif
*/

#if (FW_TYPE==_SCCB_MGR_)

/*---------------------------------------------------------------------
 *
 * Function: SccbMgr_sense_adapter
 *
 * Description: Setup and/or Search for cards and return info to caller.
 *
 *---------------------------------------------------------------------*/

int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
{
#if defined(DOS)
#else
   static UCHAR first_time = 1;
#endif

   UCHAR i,j,id,ScamFlg;
   USHORT temp,temp2,temp3,temp4,temp5,temp6;
#if defined(DOS)
   USHORT ioport;
#else
   ULONG ioport;
#endif
	PNVRamInfo pCurrNvRam;

#if defined(DOS)
   ioport = (USHORT)pCardInfo->si_baseaddr;
#else
   ioport = pCardInfo->si_baseaddr;
#endif


   if (RD_HARPOON(ioport+hp_vendor_id_0) != ORION_VEND_0)
      return((int)FAILURE);

   if ((RD_HARPOON(ioport+hp_vendor_id_1) != ORION_VEND_1))
      return((int)FAILURE);

   if ((RD_HARPOON(ioport+hp_device_id_0) != ORION_DEV_0))
      return((int)FAILURE);

   if ((RD_HARPOON(ioport+hp_device_id_1) != ORION_DEV_1))
      return((int)FAILURE);


   if (RD_HARPOON(ioport+hp_rev_num) != 0x0f){

/* For new Harpoon then check for sub_device ID LSB
   the bits(0-3) must be all ZERO for compatible with
   current version of SCCBMgr, else skip this Harpoon
	device. */

	   if (RD_HARPOON(ioport+hp_sub_device_id_0) & 0x0f)
	      return((int)FAILURE);
	}

   if (first_time)
      {
      SccbMgrTableInitAll();
      first_time = 0;
		mbCards = 0;
      }

	if(RdStack(ioport, 0) != 0x00) {
		if(ChkIfChipInitialized(ioport) == FALSE)
		{
			pCurrNvRam = NULL;
		   WR_HARPOON(ioport+hp_semaphore, 0x00);
			XbowInit(ioport, 0);             /*Must Init the SCSI before attempting */
			DiagEEPROM(ioport);
		}
		else
		{
			if(mbCards < MAX_MB_CARDS) {
				pCurrNvRam = &nvRamInfo[mbCards];
				mbCards++;
				pCurrNvRam->niBaseAddr = ioport;
				RNVRamData(pCurrNvRam);
			}else
				return((int) FAILURE);
		}
	}else
		pCurrNvRam = NULL;
#if defined (NO_BIOS_OPTION)
	pCurrNvRam = NULL;
   XbowInit(ioport, 0);                /*Must Init the SCSI before attempting */
   DiagEEPROM(ioport);
#endif  /* No BIOS Option */

   WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT);
   WR_HARPOON(ioport+hp_sys_ctrl, 0x00);

	if(pCurrNvRam)
		pCardInfo->si_id = pCurrNvRam->niAdapId;
	else
	   pCardInfo->si_id = (UCHAR)(utilEERead(ioport, (ADAPTER_SCSI_ID/2)) &
   	   (UCHAR)0x0FF);

   pCardInfo->si_lun = 0x00;
   pCardInfo->si_fw_revision = ORION_FW_REV;
   temp2 = 0x0000;
   temp3 = 0x0000;
   temp4 = 0x0000;
   temp5 = 0x0000;
   temp6 = 0x0000;

   for (id = 0; id < (16/2); id++) {

		if(pCurrNvRam){
			temp = (USHORT) pCurrNvRam->niSyncTbl[id];
			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
					 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
		}else
	      temp = utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id));

      for (i = 0; i < 2; temp >>=8,i++) {

         temp2 >>= 1;
         temp3 >>= 1;
         temp4 >>= 1;
         temp5 >>= 1;
         temp6 >>= 1;
	 switch (temp & 0x3)
	   {
	   case AUTO_RATE_20:	/* Synchronous, 20 mega-transfers/second */
	     temp6 |= 0x8000;	/* Fall through */
	   case AUTO_RATE_10:	/* Synchronous, 10 mega-transfers/second */
	     temp5 |= 0x8000;	/* Fall through */
	   case AUTO_RATE_05:	/* Synchronous, 5 mega-transfers/second */
	     temp2 |= 0x8000;	/* Fall through */
	   case AUTO_RATE_00:	/* Asynchronous */
	     break;
	   }

         if (temp & DISC_ENABLE_BIT)
	   temp3 |= 0x8000;

         if (temp & WIDE_NEGO_BIT)
	   temp4 |= 0x8000;

         }
      }

   pCardInfo->si_per_targ_init_sync = temp2;
   pCardInfo->si_per_targ_no_disc = temp3;
   pCardInfo->si_per_targ_wide_nego = temp4;
   pCardInfo->si_per_targ_fast_nego = temp5;
   pCardInfo->si_per_targ_ultra_nego = temp6;

	if(pCurrNvRam)
		i = pCurrNvRam->niSysConf;
	else
	   i = (UCHAR)(utilEERead(ioport, (SYSTEM_CONFIG/2)));

	if(pCurrNvRam)
		ScamFlg = pCurrNvRam->niScamConf;
	else
	   ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2);

   pCardInfo->si_flags = 0x0000;

   if (i & 0x01)
      pCardInfo->si_flags |= SCSI_PARITY_ENA;

   if (!(i & 0x02))
      pCardInfo->si_flags |= SOFT_RESET;

   if (i & 0x10)
      pCardInfo->si_flags |= EXTENDED_TRANSLATION;

   if (ScamFlg & SCAM_ENABLED)
     pCardInfo->si_flags |= FLAG_SCAM_ENABLED;

   if (ScamFlg & SCAM_LEVEL2)
     pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;

   j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
   if (i & 0x04) {
      j |= SCSI_TERM_ENA_L;
      }
   WR_HARPOON(ioport+hp_bm_ctrl, j );

   j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
   if (i & 0x08) {
      j |= SCSI_TERM_ENA_H;
      }
   WR_HARPOON(ioport+hp_ee_ctrl, j );

   if (!(RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD))

      pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;

   pCardInfo->si_card_family = HARPOON_FAMILY;
   pCardInfo->si_bustype = BUSTYPE_PCI;

	if(pCurrNvRam){
   	pCardInfo->si_card_model[0] = '9';
		switch(pCurrNvRam->niModel & 0x0f){
			case MODEL_LT:
		   	pCardInfo->si_card_model[1] = '3';
		   	pCardInfo->si_card_model[2] = '0';
				break;
			case MODEL_LW:
		   	pCardInfo->si_card_model[1] = '5';
		   	pCardInfo->si_card_model[2] = '0';
				break;
			case MODEL_DL:
		   	pCardInfo->si_card_model[1] = '3';
		   	pCardInfo->si_card_model[2] = '2';
				break;
			case MODEL_DW:
		   	pCardInfo->si_card_model[1] = '5';
		   	pCardInfo->si_card_model[2] = '2';
				break;
		}
	}else{
	   temp = utilEERead(ioport, (MODEL_NUMB_0/2));
   	pCardInfo->si_card_model[0] = (UCHAR)(temp >> 8);
	   temp = utilEERead(ioport, (MODEL_NUMB_2/2));

   	pCardInfo->si_card_model[1] = (UCHAR)(temp & 0x00FF);
	   pCardInfo->si_card_model[2] = (UCHAR)(temp >> 8);
	}

   if (pCardInfo->si_card_model[1] == '3')
     {
       if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7))
	 pCardInfo->si_flags |= LOW_BYTE_TERM;
     }
   else if (pCardInfo->si_card_model[2] == '0')
     {
       temp = RD_HARPOON(ioport+hp_xfer_pad);
       WR_HARPOON(ioport+hp_xfer_pad, (temp & ~BIT(4)));
       if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7))
	 pCardInfo->si_flags |= LOW_BYTE_TERM;
       WR_HARPOON(ioport+hp_xfer_pad, (temp | BIT(4)));
       if (RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7))
	 pCardInfo->si_flags |= HIGH_BYTE_TERM;
       WR_HARPOON(ioport+hp_xfer_pad, temp);
     }
   else
     {
       temp = RD_HARPOON(ioport+hp_ee_ctrl);
       temp2 = RD_HARPOON(ioport+hp_xfer_pad);
       WR_HARPOON(ioport+hp_ee_ctrl, (temp | SEE_CS));
       WR_HARPOON(ioport+hp_xfer_pad, (temp2 | BIT(4)));
       temp3 = 0;
       for (i = 0; i < 8; i++)
	 {
	   temp3 <<= 1;
	   if (!(RD_HARPOON(ioport+hp_ee_ctrl) & BIT(7)))
	     temp3 |= 1;
	   WR_HARPOON(ioport+hp_xfer_pad, (temp2 & ~BIT(4)));
	   WR_HARPOON(ioport+hp_xfer_pad, (temp2 | BIT(4)));
	 }
       WR_HARPOON(ioport+hp_ee_ctrl, temp);
       WR_HARPOON(ioport+hp_xfer_pad, temp2);
       if (!(temp3 & BIT(7)))
	 pCardInfo->si_flags |= LOW_BYTE_TERM;
       if (!(temp3 & BIT(6)))
	 pCardInfo->si_flags |= HIGH_BYTE_TERM;
     }


   ARAM_ACCESS(ioport);

   for ( i = 0; i < 4; i++ ) {

      pCardInfo->si_XlatInfo[i] =
         RD_HARPOON(ioport+hp_aramBase+BIOS_DATA_OFFSET+i);
      }

	/* return with -1 if no sort, else return with
	   logical card number sorted by BIOS (zero-based) */

	pCardInfo->si_relative_cardnum =
	(UCHAR)(RD_HARPOON(ioport+hp_aramBase+BIOS_RELATIVE_CARD)-1);

   SGRAM_ACCESS(ioport);

   s_PhaseTbl[0] = phaseDataOut;
   s_PhaseTbl[1] = phaseDataIn;
   s_PhaseTbl[2] = phaseIllegal;
   s_PhaseTbl[3] = phaseIllegal;
   s_PhaseTbl[4] = phaseCommand;
   s_PhaseTbl[5] = phaseStatus;
   s_PhaseTbl[6] = phaseMsgOut;
   s_PhaseTbl[7] = phaseMsgIn;

   pCardInfo->si_present = 0x01;

#if defined(BUGBUG)


   for (i = 0; i < MAX_CARDS; i++) {

      for (id=0; id<debug_size; id++)
         debug_int[i][id] =  (UCHAR)0x00;
      debug_index[i] = 0;
      }

#endif

   return(0);
}


/*---------------------------------------------------------------------
 *
 * Function: SccbMgr_config_adapter
 *
 * Description: Setup adapter for normal operation (hard reset).
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
USHORT SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
#else
ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
#endif
{
   PSCCBcard CurrCard = NULL;
	PNVRamInfo pCurrNvRam;
   UCHAR i,j,thisCard, ScamFlg;
   USHORT temp,sync_bit_map,id;
#if defined(DOS)
   USHORT ioport;
#else
   ULONG ioport;
#endif

#if defined(DOS)
   ioport = (USHORT)pCardInfo->si_baseaddr;
#else
   ioport = pCardInfo->si_baseaddr;
#endif

   for(thisCard =0; thisCard <= MAX_CARDS; thisCard++) {

      if (thisCard == MAX_CARDS) {

	 return(FAILURE);
         }

      if (BL_Card[thisCard].ioPort == ioport) {

         CurrCard = &BL_Card[thisCard];
         SccbMgrTableInitCard(CurrCard,thisCard);
         break;
         }

      else if (BL_Card[thisCard].ioPort == 0x00) {

         BL_Card[thisCard].ioPort = ioport;
         CurrCard = &BL_Card[thisCard];

			if(mbCards)
				for(i = 0; i < mbCards; i++){
					if(CurrCard->ioPort == nvRamInfo[i].niBaseAddr)
						CurrCard->pNvRamInfo = &nvRamInfo[i];
				}
         SccbMgrTableInitCard(CurrCard,thisCard);
         CurrCard->cardIndex = thisCard;
         CurrCard->cardInfo = pCardInfo;

	 break;
         }
      }

	pCurrNvRam = CurrCard->pNvRamInfo;

	if(pCurrNvRam){
		ScamFlg = pCurrNvRam->niScamConf;
	}
	else{
	   ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2);
	}


   BusMasterInit(ioport);
   XbowInit(ioport, ScamFlg);

#if defined (NO_BIOS_OPTION)


   if (DiagXbow(ioport)) return(FAILURE);
   if (DiagBusMaster(ioport)) return(FAILURE);

#endif  /* No BIOS Option */

   autoLoadDefaultMap(ioport);


   for (i = 0,id = 0x01; i != pCardInfo->si_id; i++,id <<= 1){}

   WR_HARPOON(ioport+hp_selfid_0, id);
   WR_HARPOON(ioport+hp_selfid_1, 0x00);
   WR_HARPOON(ioport+hp_arb_id, pCardInfo->si_id);
   CurrCard->ourId = pCardInfo->si_id;

   i = (UCHAR) pCardInfo->si_flags;
   if (i & SCSI_PARITY_ENA)
       WR_HARPOON(ioport+hp_portctrl_1,(HOST_MODE8 | CHK_SCSI_P));

   j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
   if (i & LOW_BYTE_TERM)
      j |= SCSI_TERM_ENA_L;
   WR_HARPOON(ioport+hp_bm_ctrl, j);

   j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
   if (i & HIGH_BYTE_TERM)
      j |= SCSI_TERM_ENA_H;
   WR_HARPOON(ioport+hp_ee_ctrl, j );


   if (!(pCardInfo->si_flags & SOFT_RESET)) {

      sresb(ioport,thisCard);

         scini(thisCard, pCardInfo->si_id, 0);
      }



   if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
      CurrCard->globalFlags |= F_NO_FILTER;

	if(pCurrNvRam){
		if(pCurrNvRam->niSysConf & 0x10)
			CurrCard->globalFlags |= F_GREEN_PC;
	}
	else{
	   if (utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA)
   	   CurrCard->globalFlags |= F_GREEN_PC;
	}

	/* Set global flag to indicate Re-Negotiation to be done on all
		ckeck condition */
	if(pCurrNvRam){
		if(pCurrNvRam->niScsiConf & 0x04)
			CurrCard->globalFlags |= F_DO_RENEGO;
	}
	else{
	   if (utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA)
   	   CurrCard->globalFlags |= F_DO_RENEGO;
	}

	if(pCurrNvRam){
		if(pCurrNvRam->niScsiConf & 0x08)
			CurrCard->globalFlags |= F_CONLUN_IO;
	}
	else{
	   if (utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA)
   	   CurrCard->globalFlags |= F_CONLUN_IO;
	}


   temp = pCardInfo->si_per_targ_no_disc;

   for (i = 0,id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {

      if (temp & id)
	 sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
      }

   sync_bit_map = 0x0001;

   for (id = 0; id < (MAX_SCSI_TAR/2); id++) {

		if(pCurrNvRam){
			temp = (USHORT) pCurrNvRam->niSyncTbl[id];
			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
					 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
		}else
	      temp = utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id));

      for (i = 0; i < 2; temp >>=8,i++) {

         if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {

            sccbMgrTbl[thisCard][id*2+i].TarEEValue = (UCHAR)temp;
            }

         else {
	    sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED;
            sccbMgrTbl[thisCard][id*2+i].TarEEValue =
               (UCHAR)(temp & ~EE_SYNC_MASK);
            }

#if defined(WIDE_SCSI)
/*         if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
            (id*2+i >= 8)){
*/
         if (pCardInfo->si_per_targ_wide_nego & sync_bit_map){

            sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI;

            }

         else { /* NARROW SCSI */
            sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
            }

#else
         sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
#endif


	 sync_bit_map <<= 1;



         }
      }

   WR_HARPOON((ioport+hp_semaphore),
      (UCHAR)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT));

#if defined(DOS)
   return((USHORT)CurrCard);
#else
   return((ULONG)CurrCard);
#endif
}

#else  			/* end (FW_TYPE==_SCCB_MGR_)  */



STATIC s16bits FP_PresenceCheck(PMGR_INFO pMgrInfo)
{
	PMGR_ENTRYPNTS	pMgr_EntryPnts = &pMgrInfo->mi_Functions;

      pMgr_EntryPnts->UCBMgr_probe_adapter = probe_adapter;
      pMgr_EntryPnts->UCBMgr_init_adapter = init_adapter;
      pMgr_EntryPnts->UCBMgr_start_UCB = SccbMgr_start_sccb;
      pMgr_EntryPnts->UCBMgr_build_UCB = build_UCB;
      pMgr_EntryPnts->UCBMgr_abort_UCB = SccbMgr_abort_sccb;
      pMgr_EntryPnts->UCBMgr_my_int = SccbMgr_my_int;
      pMgr_EntryPnts->UCBMgr_isr = SccbMgr_isr;
      pMgr_EntryPnts->UCBMgr_scsi_reset = SccbMgr_scsi_reset;
      pMgr_EntryPnts->UCBMgr_timer_expired = SccbMgr_timer_expired;
#ifndef NO_IOCTLS
	  pMgr_EntryPnts->UCBMgr_unload_card = SccbMgr_unload_card;
	  pMgr_EntryPnts->UCBMgr_save_foreign_state =
	  									SccbMgr_save_foreign_state;
	  pMgr_EntryPnts->UCBMgr_restore_foreign_state =
	  									SccbMgr_restore_foreign_state;
	  pMgr_EntryPnts->UCBMgr_restore_native_state =
	  									SccbMgr_restore_native_state;
#endif /*NO_IOCTLS*/

      pMgrInfo->mi_SGListFormat=0x01;
      pMgrInfo->mi_DataPtrFormat=0x01;
      pMgrInfo->mi_MaxSGElements= (u16bits) 0xffffffff;
      pMgrInfo->mi_MgrPrivateLen=sizeof(SCCB);
      pMgrInfo->mi_PCIVendorID=BL_VENDOR_ID;
      pMgrInfo->mi_PCIDeviceID=FP_DEVICE_ID;
      pMgrInfo->mi_MgrAttributes= ATTR_IO_MAPPED +
											 ATTR_PHYSICAL_ADDRESS +
											 ATTR_VIRTUAL_ADDRESS +
											 ATTR_OVERLAPPED_IO_IOCTLS_OK;
      pMgrInfo->mi_IoRangeLen = 256;
      return(0);
}



/*---------------------------------------------------------------------
 *
 * Function: probe_adapter
 *
 * Description: Setup and/or Search for cards and return info to caller.
 *
 *---------------------------------------------------------------------*/
STATIC s32bits probe_adapter(PADAPTER_INFO pAdapterInfo)
{
   u16bits temp,temp2,temp3,temp4;
   u08bits i,j,id;

#if defined(DOS)
#else
   static u08bits first_time = 1;
#endif
   BASE_PORT ioport;
	PNVRamInfo pCurrNvRam;

   ioport = (BASE_PORT)pAdapterInfo->ai_baseaddr;



   if (RD_HARPOON(ioport+hp_vendor_id_0) != ORION_VEND_0)
      return(1);

   if ((RD_HARPOON(ioport+hp_vendor_id_1) != ORION_VEND_1))
      return(2);

   if ((RD_HARPOON(ioport+hp_device_id_0) != ORION_DEV_0))
      return(3);

   if ((RD_HARPOON(ioport+hp_device_id_1) != ORION_DEV_1))
      return(4);


   if (RD_HARPOON(ioport+hp_rev_num) != 0x0f){


/* For new Harpoon then check for sub_device ID LSB
   the bits(0-3) must be all ZERO for compatible with
   current version of SCCBMgr, else skip this Harpoon
	device. */

	   if (RD_HARPOON(ioport+hp_sub_device_id_0) & 0x0f)
	      return(5);
	}

   if (first_time) {

      SccbMgrTableInitAll();
      first_time = 0;
		mbCards = 0;
      }

	if(RdStack(ioport, 0) != 0x00) {
		if(ChkIfChipInitialized(ioport) == FALSE)
		{
			pCurrNvRam = NULL;
		   WR_HARPOON(ioport+hp_semaphore, 0x00);
			XbowInit(ioport, 0);                /*Must Init the SCSI before attempting */
			DiagEEPROM(ioport);
		}
		else
		{
			if(mbCards < MAX_MB_CARDS) {
				pCurrNvRam = &nvRamInfo[mbCards];
				mbCards++;
				pCurrNvRam->niBaseAddr = ioport;
				RNVRamData(pCurrNvRam);
			}else
				return((int) FAILURE);
		}
	}else
		pCurrNvRam = NULL;

#if defined (NO_BIOS_OPTION)
	pCurrNvRam = NULL;
   XbowInit(ioport, 0);                /*Must Init the SCSI before attempting */
   DiagEEPROM(ioport);
#endif  /* No BIOS Option */

   WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT);
   WR_HARPOON(ioport+hp_sys_ctrl, 0x00);

	if(pCurrNvRam)
		pAdapterInfo->ai_id = pCurrNvRam->niAdapId;
	else
   	pAdapterInfo->ai_id = (u08bits)(utilEERead(ioport, (ADAPTER_SCSI_ID/2)) &
      	(u08bits)0x0FF);

   pAdapterInfo->ai_lun = 0x00;
   pAdapterInfo->ai_fw_revision[0] = '3';
   pAdapterInfo->ai_fw_revision[1] = '1';
   pAdapterInfo->ai_fw_revision[2] = '1';
   pAdapterInfo->ai_fw_revision[3] = ' ';
   pAdapterInfo->ai_NumChannels = 1;

   temp2 = 0x0000;
   temp3 = 0x0000;
   temp4 = 0x0000;

   for (id = 0; id < (16/2); id++) {

		if(pCurrNvRam){
			temp = (USHORT) pCurrNvRam->niSyncTbl[id];
			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
					 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
		}else
	      temp = utilEERead(ioport, (u16bits)((SYNC_RATE_TBL/2)+id));

      for (i = 0; i < 2; temp >>=8,i++) {

         if ((temp & 0x03) != AUTO_RATE_00) {

            temp2 >>= 0x01;
            temp2 |= 0x8000;
            }

         else {
            temp2 >>= 0x01;
            }

         if (temp & DISC_ENABLE_BIT) {

            temp3 >>= 0x01;
            temp3 |= 0x8000;
            }

         else {
            temp3 >>= 0x01;
            }

         if (temp & WIDE_NEGO_BIT) {

            temp4 >>= 0x01;
            temp4 |= 0x8000;
            }

         else {
            temp4 >>= 0x01;
            }

         }
      }

   pAdapterInfo->ai_per_targ_init_sync = temp2;
   pAdapterInfo->ai_per_targ_no_disc = temp3;
   pAdapterInfo->ai_per_targ_wide_nego = temp4;
	if(pCurrNvRam)
		i = pCurrNvRam->niSysConf;
	else
   	i = (u08bits)(utilEERead(ioport, (SYSTEM_CONFIG/2)));

   /*
   ** interrupts always level-triggered for FlashPoint
   */
   pAdapterInfo->ai_stateinfo |= LEVEL_TRIG;

   if (i & 0x01)
      pAdapterInfo->ai_stateinfo |= SCSI_PARITY_ENA;

	if (i & 0x02)	/* SCSI Bus reset in AutoSCSI Set ? */
	{
		if(pCurrNvRam)
		{
			j = pCurrNvRam->niScamConf;
		}
		else
		{
		j = (u08bits) utilEERead(ioport, SCAM_CONFIG/2);
		}
		if(j & SCAM_ENABLED)
		{
			if(j & SCAM_LEVEL2)
			{
				pAdapterInfo->ai_stateinfo |= SCAM2_ENA;
			}
			else
			{
				pAdapterInfo->ai_stateinfo |= SCAM1_ENA;
			}
		}
	}
   j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
   if (i & 0x04) {
      j |= SCSI_TERM_ENA_L;
      pAdapterInfo->ai_stateinfo |= LOW_BYTE_TERM_ENA;
      }
   WR_HARPOON(ioport+hp_bm_ctrl, j );

   j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
   if (i & 0x08) {
      j |= SCSI_TERM_ENA_H;
      pAdapterInfo->ai_stateinfo |= HIGH_BYTE_TERM_ENA;
      }
   WR_HARPOON(ioport+hp_ee_ctrl, j );

	if(RD_HARPOON(ioport + hp_page_ctrl) & BIOS_SHADOW)
	{
		pAdapterInfo->ai_FlashRomSize = 64 * 1024;	/* 64k ROM */
	}
	else
	{
		pAdapterInfo->ai_FlashRomSize = 32 * 1024;	/* 32k ROM */
	}

   pAdapterInfo->ai_stateinfo |= (FAST20_ENA | TAG_QUEUE_ENA);
   if (!(RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD))
	{
      pAdapterInfo->ai_attributes |= (WIDE_CAPABLE | FAST20_CAPABLE
													| SCAM2_CAPABLE
													| TAG_QUEUE_CAPABLE
													| SUPRESS_UNDERRRUNS_CAPABLE
													| SCSI_PARITY_CAPABLE);
		pAdapterInfo->ai_MaxTarg = 16;
		pAdapterInfo->ai_MaxLun  = 32;
	}
	else
	{
      pAdapterInfo->ai_attributes |= (FAST20_CAPABLE | SCAM2_CAPABLE
													| TAG_QUEUE_CAPABLE
													| SUPRESS_UNDERRRUNS_CAPABLE
													| SCSI_PARITY_CAPABLE);
		pAdapterInfo->ai_MaxTarg = 8;
		pAdapterInfo->ai_MaxLun  = 8;
	}

   pAdapterInfo->ai_product_family = HARPOON_FAMILY;
   pAdapterInfo->ai_HBAbustype = BUSTYPE_PCI;

   for (i=0;i<CARD_MODEL_NAMELEN;i++)
   {
      pAdapterInfo->ai_card_model[i]=' '; /* initialize the ai_card_model */
   }

	if(pCurrNvRam){
	pAdapterInfo->ai_card_model[0] = '9';
		switch(pCurrNvRam->niModel & 0x0f){
			case MODEL_LT:
			pAdapterInfo->ai_card_model[1] = '3';
			pAdapterInfo->ai_card_model[2] = '0';
				break;
			case MODEL_LW:
			pAdapterInfo->ai_card_model[1] = '5';
			pAdapterInfo->ai_card_model[2] = '0';
				break;
			case MODEL_DL:
			pAdapterInfo->ai_card_model[1] = '3';
			pAdapterInfo->ai_card_model[2] = '2';
				break;
			case MODEL_DW:
			pAdapterInfo->ai_card_model[1] = '5';
			pAdapterInfo->ai_card_model[2] = '2';
				break;
		}
	}else{
	   temp = utilEERead(ioport, (MODEL_NUMB_0/2));
		pAdapterInfo->ai_card_model[0] = (u08bits)(temp >> 8);
	   temp = utilEERead(ioport, (MODEL_NUMB_2/2));

		pAdapterInfo->ai_card_model[1] = (u08bits)(temp & 0x00FF);
	   pAdapterInfo->ai_card_model[2] = (u08bits)(temp >> 8);
	}



   pAdapterInfo->ai_FiberProductType = 0;

   pAdapterInfo->ai_secondary_range = 0;

   for (i=0;i<WORLD_WIDE_NAMELEN;i++)
   {
      pAdapterInfo->ai_worldwidename[i]='\0';
   }

   for (i=0;i<VENDOR_NAMELEN;i++)
   {
      pAdapterInfo->ai_vendorstring[i]='\0';
   }
   	pAdapterInfo->ai_vendorstring[0]='B';
   	pAdapterInfo->ai_vendorstring[1]='U';
   	pAdapterInfo->ai_vendorstring[2]='S';
   	pAdapterInfo->ai_vendorstring[3]='L';
   	pAdapterInfo->ai_vendorstring[4]='O';
   	pAdapterInfo->ai_vendorstring[5]='G';
   	pAdapterInfo->ai_vendorstring[6]='I';
   	pAdapterInfo->ai_vendorstring[7]='C';

	for (i=0;i<FAMILY_NAMELEN;i++)
	{
	   pAdapterInfo->ai_AdapterFamilyString[i]='\0';
	}
   	pAdapterInfo->ai_AdapterFamilyString[0]='F';
   	pAdapterInfo->ai_AdapterFamilyString[1]='L';
   	pAdapterInfo->ai_AdapterFamilyString[2]='A';
   	pAdapterInfo->ai_AdapterFamilyString[3]='S';
   	pAdapterInfo->ai_AdapterFamilyString[4]='H';
   	pAdapterInfo->ai_AdapterFamilyString[5]='P';
   	pAdapterInfo->ai_AdapterFamilyString[6]='O';
   	pAdapterInfo->ai_AdapterFamilyString[7]='I';
   	pAdapterInfo->ai_AdapterFamilyString[8]='N';
   	pAdapterInfo->ai_AdapterFamilyString[9]='T';

   ARAM_ACCESS(ioport);

   for ( i = 0; i < 4; i++ ) {

      pAdapterInfo->ai_XlatInfo[i] =
         RD_HARPOON(ioport+hp_aramBase+BIOS_DATA_OFFSET+i);
      }

	/* return with -1 if no sort, else return with
	   logical card number sorted by BIOS (zero-based) */


	pAdapterInfo->ai_relative_cardnum = 
      (u08bits)(RD_HARPOON(ioport+hp_aramBase+BIOS_RELATIVE_CARD)-1); 

   SGRAM_ACCESS(ioport);

   s_PhaseTbl[0] = phaseDataOut;
   s_PhaseTbl[1] = phaseDataIn;
   s_PhaseTbl[2] = phaseIllegal;
   s_PhaseTbl[3] = phaseIllegal;
   s_PhaseTbl[4] = phaseCommand;
   s_PhaseTbl[5] = phaseStatus;
   s_PhaseTbl[6] = phaseMsgOut;
   s_PhaseTbl[7] = phaseMsgIn;

   pAdapterInfo->ai_present = 0x01;

#if defined(BUGBUG)


   for (i = 0; i < MAX_CARDS; i++) {

      for (id=0; id<debug_size; id++)
         debug_int[i][id] =  (u08bits)0x00;
      debug_index[i] = 0;
      }

#endif

   return(0);
}





/*---------------------------------------------------------------------
 *
 * Function: init_adapter, exported to BUDI via UCBMgr_init_adapter entry
 *
 *
 * Description: Setup adapter for normal operation (hard reset).
 *
 *---------------------------------------------------------------------*/
STATIC CARD_HANDLE init_adapter(PADAPTER_INFO pCardInfo)
{
   PSCCBcard CurrCard;
	PNVRamInfo pCurrNvRam;
   u08bits i,j,thisCard, ScamFlg;
   u16bits temp,sync_bit_map,id;
   BASE_PORT ioport;

   ioport = (BASE_PORT)pCardInfo->ai_baseaddr;

   for(thisCard =0; thisCard <= MAX_CARDS; thisCard++) {

      if (thisCard == MAX_CARDS) {

         return(FAILURE);
         }

      if (BL_Card[thisCard].ioPort == ioport) {

         CurrCard = &BL_Card[thisCard];
         SccbMgrTableInitCard(CurrCard,thisCard);
         break;
         }

      else if (BL_Card[thisCard].ioPort == 0x00) {

         BL_Card[thisCard].ioPort = ioport;
         CurrCard = &BL_Card[thisCard];

			if(mbCards)
				for(i = 0; i < mbCards; i++){
					if(CurrCard->ioPort == nvRamInfo[i].niBaseAddr)
						CurrCard->pNvRamInfo = &nvRamInfo[i];
				}
         SccbMgrTableInitCard(CurrCard,thisCard);
         CurrCard->cardIndex = thisCard;
         CurrCard->cardInfo = pCardInfo;

         break;
         }
      }

	pCurrNvRam = CurrCard->pNvRamInfo;

   
	if(pCurrNvRam){
		ScamFlg = pCurrNvRam->niScamConf;
	}
	else{
	   ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2);
	}
	

   BusMasterInit(ioport);
   XbowInit(ioport, ScamFlg);

#if defined (NO_BIOS_OPTION)


   if (DiagXbow(ioport)) return(FAILURE);
   if (DiagBusMaster(ioport)) return(FAILURE);

#endif  /* No BIOS Option */

   autoLoadDefaultMap(ioport);


   for (i = 0,id = 0x01; i != pCardInfo->ai_id; i++,id <<= 1){}

   WR_HARPOON(ioport+hp_selfid_0, id);
   WR_HARPOON(ioport+hp_selfid_1, 0x00);
   WR_HARPOON(ioport+hp_arb_id, pCardInfo->ai_id);
   CurrCard->ourId = (unsigned char) pCardInfo->ai_id;

   i = (u08bits) pCardInfo->ai_stateinfo;
   if (i & SCSI_PARITY_ENA)
       WR_HARPOON(ioport+hp_portctrl_1,(HOST_MODE8 | CHK_SCSI_P));

   j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
   if (i & LOW_BYTE_TERM_ENA)
      j |= SCSI_TERM_ENA_L;
   WR_HARPOON(ioport+hp_bm_ctrl, j);

   j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
   if (i & HIGH_BYTE_TERM_ENA)
      j |= SCSI_TERM_ENA_H;
   WR_HARPOON(ioport+hp_ee_ctrl, j );


   if (!(pCardInfo->ai_stateinfo & NO_RESET_IN_INIT)) {

      sresb(ioport,thisCard);

         scini(thisCard, (u08bits) pCardInfo->ai_id, 0);
      }



   if (pCardInfo->ai_stateinfo & SUPRESS_UNDERRRUNS_ENA)
      CurrCard->globalFlags |= F_NO_FILTER;

	if(pCurrNvRam){
		if(pCurrNvRam->niSysConf & 0x10)
			CurrCard->globalFlags |= F_GREEN_PC;
	}
	else{
	   if (utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA)
   	   CurrCard->globalFlags |= F_GREEN_PC;
	}

	/* Set global flag to indicate Re-Negotiation to be done on all
		ckeck condition */
	if(pCurrNvRam){
		if(pCurrNvRam->niScsiConf & 0x04)
			CurrCard->globalFlags |= F_DO_RENEGO;
	}
	else{
	   if (utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA)
   	   CurrCard->globalFlags |= F_DO_RENEGO;
	}

	if(pCurrNvRam){
		if(pCurrNvRam->niScsiConf & 0x08)
			CurrCard->globalFlags |= F_CONLUN_IO;
	}
	else{
	   if (utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA)
   	   CurrCard->globalFlags |= F_CONLUN_IO;
	}

   temp = pCardInfo->ai_per_targ_no_disc;

   for (i = 0,id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {

      if (temp & id)
         sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
      }

   sync_bit_map = 0x0001;

   for (id = 0; id < (MAX_SCSI_TAR/2); id++){

		if(pCurrNvRam){
			temp = (USHORT) pCurrNvRam->niSyncTbl[id];
			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
					 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
		}else
	      temp = utilEERead(ioport, (u16bits)((SYNC_RATE_TBL/2)+id));

      for (i = 0; i < 2; temp >>=8,i++){

         if (pCardInfo->ai_per_targ_init_sync & sync_bit_map){

            sccbMgrTbl[thisCard][id*2+i].TarEEValue = (u08bits)temp;
            }

         else {
            sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED;
            sccbMgrTbl[thisCard][id*2+i].TarEEValue =
               (u08bits)(temp & ~EE_SYNC_MASK);
            }

#if defined(WIDE_SCSI)
/*         if ((pCardInfo->ai_per_targ_wide_nego & sync_bit_map) ||
            (id*2+i >= 8)){
*/
         if (pCardInfo->ai_per_targ_wide_nego & sync_bit_map){

            sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI;

            }

         else { /* NARROW SCSI */
            sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
            }

#else
         sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
#endif


         sync_bit_map <<= 1;
         }
      }


   pCardInfo->ai_SGListFormat=0x01;
   pCardInfo->ai_DataPtrFormat=0x01;
   pCardInfo->ai_AEN_mask &= SCSI_RESET_COMPLETE;

   WR_HARPOON((ioport+hp_semaphore),
      (u08bits)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT));

   return((u32bits)CurrCard);

}


/*---------------------------------------------------------------------
 *
 * Function: build_ucb, exported to BUDI via UCBMgr_build_ucb entry
 *
 * Description: prepare fw portion of ucb. do not start, resource not guaranteed
 *             so don't manipulate anything that's derived from states which
 *             may change
 *
 *---------------------------------------------------------------------*/
void build_UCB(CARD_HANDLE pCurrCard, PUCB p_ucb)
{

   u08bits thisCard;
   u08bits i,j;

   PSCCB p_sccb;


   thisCard = ((PSCCBcard) pCurrCard)->cardIndex;


   p_sccb=(PSCCB)p_ucb->UCB_MgrPrivatePtr;


   p_sccb->Sccb_ucb_ptr=p_ucb;

   switch (p_ucb->UCB_opcode & (OPC_DEVICE_RESET+OPC_XFER_SG+OPC_CHK_RESIDUAL))
   {
      case OPC_DEVICE_RESET:
         p_sccb->OperationCode=RESET_COMMAND;
         break;
      case OPC_XFER_SG:
         p_sccb->OperationCode=SCATTER_GATHER_COMMAND;
         break;
      case OPC_XFER_SG+OPC_CHK_RESIDUAL:
         p_sccb->OperationCode=RESIDUAL_SG_COMMAND;
         break;
      case OPC_CHK_RESIDUAL:

	      p_sccb->OperationCode=RESIDUAL_COMMAND;
	      break;
      default:
	      p_sccb->OperationCode=SCSI_INITIATOR_COMMAND;
	      break;
   }

   if (p_ucb->UCB_opcode & OPC_TQ_ENABLE)
   {
      p_sccb->ControlByte = (u08bits)((p_ucb->UCB_opcode & OPC_TQ_MASK)>>2) | F_USE_CMD_Q;
   }
   else
   {
      p_sccb->ControlByte = 0;
   }


   p_sccb->CdbLength = (u08bits)p_ucb->UCB_cdblen;

   if (p_ucb->UCB_opcode & OPC_NO_AUTO_SENSE)
   {
      p_sccb->RequestSenseLength = 0;
   }
   else
   {
      p_sccb->RequestSenseLength = (unsigned char) p_ucb->UCB_senselen;
   }


   if (p_ucb->UCB_opcode & OPC_XFER_SG)
   {
      p_sccb->DataPointer=p_ucb->UCB_virt_dataptr;
      p_sccb->DataLength = (((u32bits)p_ucb->UCB_NumSgElements)<<3);
   }
   else
   {
      p_sccb->DataPointer=p_ucb->UCB_phys_dataptr;
      p_sccb->DataLength=p_ucb->UCB_datalen;
   };

   p_sccb->HostStatus=0;
   p_sccb->TargetStatus=0;
   p_sccb->TargID=(unsigned char)p_ucb->UCB_targid;
   p_sccb->Lun=(unsigned char) p_ucb->UCB_lun;
   p_sccb->SccbIOPort=((PSCCBcard)pCurrCard)->ioPort;

   j=p_ucb->UCB_cdblen;
   for (i=0;i<j;i++)
   {
      p_sccb->Cdb[i] = p_ucb->UCB_cdb[i];
   }

   p_sccb->SensePointer=p_ucb->UCB_phys_senseptr;

   sinits(p_sccb,thisCard);

}
#ifndef NO_IOCTLS

/*---------------------------------------------------------------------
 *
 * Function: GetDevSyncRate
 *
 *---------------------------------------------------------------------*/
STATIC  int GetDevSyncRate(PSCCBcard pCurrCard,PUCB p_ucb)
{
	struct _SYNC_RATE_INFO * pSyncStr;
   PSCCBMgr_tar_info currTar_Info;
	BASE_PORT ioport;
	u08bits scsiID, j;

#if (FW_TYPE != _SCCB_MGR_)
	if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg )
	{
		return(1);
	}
#endif

	ioport  = pCurrCard->ioPort;
	pSyncStr	= (struct _SYNC_RATE_INFO *) p_ucb->UCB_virt_dataptr;
	scsiID = (u08bits) p_ucb->UCB_targid;
   currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID];
	j = currTar_Info->TarSyncCtrl;

	switch (currTar_Info->TarEEValue & EE_SYNC_MASK)
	{
		case EE_SYNC_ASYNC:
			pSyncStr->RequestMegaXferRate = 0x00;
			break;
		case EE_SYNC_5MB:
			pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 50 : 100;
			break;
		case EE_SYNC_10MB:
			pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 100 : 200;
			break;
		case EE_SYNC_20MB:
			pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 200 : 400;
			break;
	}

	switch ((j >> 5) & 0x07)
	{
		case 0x00:
			if((j & 0x07) == 0x00)
			{
				pSyncStr->ActualMegaXferRate = 0x00;	/* Async Mode */
			}
			else
			{
				pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 200 : 400;
			}
			break;
		case 0x01:
			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 100 : 200;
			break;
		case 0x02:
			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 66 : 122;
			break;
		case 0x03:
			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 50 : 100;
			break;
		case 0x04:
			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 40 : 80;
			break;
		case 0x05:
			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 33 : 66;
			break;
		case 0x06:
			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 28 : 56;
			break;
		case 0x07:
			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 25 : 50;
			break;
	}
	pSyncStr->NegotiatedOffset = j & 0x0f;

	return(0);
}

/*---------------------------------------------------------------------
 *
 * Function: SetDevSyncRate
 *
 *---------------------------------------------------------------------*/
STATIC int SetDevSyncRate(PSCCBcard pCurrCard, PUCB p_ucb)
{
	struct _SYNC_RATE_INFO * pSyncStr;
   PSCCBMgr_tar_info currTar_Info;
	BASE_PORT ioPort;
	u08bits scsiID, i, j, syncVal;
	u16bits syncOffset, actualXferRate;
	union {
		u08bits tempb[2];
		u16bits tempw;
	}temp2;

#if (FW_TYPE != _SCCB_MGR_)
	if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg )
	{
		return(1);
	}
#endif

	ioPort  = pCurrCard->ioPort;
	pSyncStr	= (struct _SYNC_RATE_INFO *) p_ucb->UCB_virt_dataptr;
	scsiID = (u08bits) p_ucb->UCB_targid;
   currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID];
	i = RD_HARPOON(ioPort+hp_xfer_pad);		/* Save current value */
	WR_HARPOON(ioPort+hp_xfer_pad, (i | ID_UNLOCK));
	WR_HARPOON(ioPort+hp_select_id, ((scsiID << 4) | scsiID));
	j = RD_HARPOON(ioPort+hp_synctarg_0);
	WR_HARPOON(ioPort+hp_xfer_pad, i);		/* restore value */

	actualXferRate = pSyncStr->ActualMegaXferRate;
	if(!(j & NARROW_SCSI))
	{
		actualXferRate <<= 1;
	}
	if(actualXferRate == 0x00)
	{
		syncVal = EE_SYNC_ASYNC;			/* Async Mode */
	}
	if(actualXferRate == 0x0200)
	{
		syncVal = EE_SYNC_20MB;				/* 20/40 MB Mode */
	}
	if(actualXferRate > 0x0050 && actualXferRate < 0x0200 )
	{
		syncVal = EE_SYNC_10MB;				/* 10/20 MB Mode */
	}
	else
	{
		syncVal = EE_SYNC_5MB;				/* 5/10 MB Mode */
	}
	if(currTar_Info->TarEEValue && EE_SYNC_MASK == syncVal)
		return(0);
	currTar_Info->TarEEValue = (currTar_Info->TarEEValue & !EE_SYNC_MASK)
											| syncVal;
	syncOffset = (SYNC_RATE_TBL + scsiID) / 2;
	temp2.tempw = utilEERead(ioPort, syncOffset);
	if(scsiID & 0x01)
	{
		temp2.tempb[0] = (temp2.tempb[0] & !EE_SYNC_MASK) | syncVal;
	}
	else
	{
		temp2.tempb[1] = (temp2.tempb[1] & !EE_SYNC_MASK) | syncVal;
	}
	utilEEWriteOnOff(ioPort, 1);
	utilEEWrite(ioPort, temp2.tempw, syncOffset);
	utilEEWriteOnOff(ioPort, 0);
	UpdateCheckSum(ioPort);

	return(0);
}
/*---------------------------------------------------------------------
 *
 * Function: GetDevWideMode
 *
 *---------------------------------------------------------------------*/
int GetDevWideMode(PSCCBcard pCurrCard,PUCB p_ucb)
{
	u08bits *pData;

	pData = (u08bits *)p_ucb->UCB_virt_dataptr;
	if(sccbMgrTbl[pCurrCard->cardIndex][p_ucb->UCB_targid].TarEEValue
				& EE_WIDE_SCSI)
	{
		*pData = 1;
	}
	else
	{
		*pData = 0;
	}

	return(0);
}

/*---------------------------------------------------------------------
 *
 * Function: SetDevWideMode
 *
 *---------------------------------------------------------------------*/
int SetDevWideMode(PSCCBcard pCurrCard,PUCB p_ucb)
{
	u08bits *pData;
   PSCCBMgr_tar_info currTar_Info;
	BASE_PORT ioPort;
	u08bits scsiID, scsiWideMode;
	u16bits syncOffset;
	union {
		u08bits tempb[2];
		u16bits tempw;
	}temp2;

#if (FW_TYPE != _SCCB_MGR_)
	if( !(pCurrCard->cardInfo->ai_attributes & WIDE_CAPABLE) )
	{
		return(1);
	}

	if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg )
	{
		return(1);
	}
#endif

	ioPort  = pCurrCard->ioPort;
	pData = (u08bits *)p_ucb->UCB_virt_dataptr;
	scsiID = (u08bits) p_ucb->UCB_targid;
	currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID];

	if(*pData)
	{
		if(currTar_Info->TarEEValue & EE_WIDE_SCSI)
		{
			return(0);
		}
		else
		{
			scsiWideMode = EE_WIDE_SCSI;
		}
	}
	else
	{
		if(!currTar_Info->TarEEValue & EE_WIDE_SCSI)
		{
			return(0);
		}
		else
		{
			scsiWideMode = 0;
		}
	}
	currTar_Info->TarEEValue = (currTar_Info->TarEEValue & !EE_WIDE_SCSI)
											| scsiWideMode;

	syncOffset = (SYNC_RATE_TBL + scsiID) / 2;
	temp2.tempw = utilEERead(ioPort, syncOffset);
	if(scsiID & 0x01)
	{
		temp2.tempb[0] = (temp2.tempb[0] & !EE_WIDE_SCSI) | scsiWideMode;
	}
	else
	{
		temp2.tempb[1] = (temp2.tempb[1] & !EE_WIDE_SCSI) | scsiWideMode;
	}
	utilEEWriteOnOff(ioPort, 1);
	utilEEWrite(ioPort, temp2.tempw, syncOffset);
	utilEEWriteOnOff(ioPort, 0);
	UpdateCheckSum(ioPort);

	return(0);
}

/*---------------------------------------------------------------------
 *
 * Function: ReadNVRam
 *
 *---------------------------------------------------------------------*/
void ReadNVRam(PSCCBcard pCurrCard,PUCB p_ucb)
{
	u08bits *pdata;
	u16bits i,numwrds,numbytes,offset,temp;
	u08bits OneMore = FALSE;
#if defined(DOS)
	u16bits ioport;
#else
	u32bits ioport;
#endif

	numbytes = (u16bits) p_ucb->UCB_datalen;
	ioport  = pCurrCard->ioPort;
   pdata   = (u08bits *) p_ucb->UCB_virt_dataptr;
	offset  = (u16bits) (p_ucb->UCB_IOCTLParams[0]);



   if (offset & 0x1)
	{
	    *((u16bits*) pdata) = utilEERead(ioport,(u16bits)((offset - 1) / 2)); /* 16 bit read */
		 *pdata = *(pdata + 1);
		 ++offset;
   	 ++pdata;
		 --numbytes;
	}

	numwrds = numbytes / 2;
	if (numbytes & 1)
	 	OneMore = TRUE;

	for (i = 0; i < numwrds; i++)
	{
   	*((u16bits*) pdata) = utilEERead(ioport,(u16bits)(offset / 2));
		pdata += 2;
		offset += 2;
   }
	if (OneMore)
	{
		--pdata;
		-- offset;
   	temp = utilEERead(ioport,(u16bits)(offset / 2));
		*pdata = (u08bits) (temp);
	}

} /* end proc ReadNVRam */


/*---------------------------------------------------------------------
 *
 * Function: WriteNVRam
 *
 *---------------------------------------------------------------------*/
void WriteNVRam(PSCCBcard pCurrCard,PUCB p_ucb)
{
	u08bits *pdata;
	u16bits i,numwrds,numbytes,offset, eeprom_end;
	u08bits OneMore = FALSE;
	union {
		u08bits  tempb[2];
		u16bits  tempw;
	} temp2;

#if defined(DOS)
	u16bits ioport;
#else
	u32bits ioport;
#endif

	numbytes = (u16bits) p_ucb->UCB_datalen;
	ioport  = pCurrCard->ioPort;
   pdata   = (u08bits *) p_ucb->UCB_virt_dataptr;
	offset  = (u16bits) (p_ucb->UCB_IOCTLParams[0]);

   if (RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD)
      eeprom_end = 512;
   else
      eeprom_end = 768;
	
	if(offset > eeprom_end)
		return;

	if((offset + numbytes) > eeprom_end)
		numbytes = eeprom_end - offset;

    utilEEWriteOnOff(ioport,1);   /* Enable write access to the EEPROM */



   if (offset & 0x1)
	{
	    temp2.tempw = utilEERead(ioport,(u16bits)((offset - 1) / 2)); /* 16 bit read */
		 temp2.tempb[1] = *pdata;
	    utilEEWrite(ioport, temp2.tempw, (u16bits)((offset -1) / 2));
		 *pdata = *(pdata + 1);
		 ++offset;
   	 ++pdata;
		 --numbytes;
	}

	numwrds = numbytes / 2;
	if (numbytes & 1)
	 	OneMore = TRUE;

	for (i = 0; i < numwrds; i++)
	{
   	utilEEWrite(ioport, *((pu16bits)pdata),(u16bits)(offset / 2));
		pdata += 2;
		offset += 2;
   }
	if (OneMore)
	{

   	temp2.tempw = utilEERead(ioport,(u16bits)(offset / 2));
		temp2.tempb[0] = *pdata;
   	utilEEWrite(ioport, temp2.tempw, (u16bits)(offset / 2));
	}
   utilEEWriteOnOff(ioport,0);   /* Turn off write access */
   UpdateCheckSum((u32bits)ioport);

} /* end proc WriteNVRam */



/*---------------------------------------------------------------------
 *
 * Function: UpdateCheckSum
 *
 * Description: Update Check Sum in EEPROM
 *
 *---------------------------------------------------------------------*/


void UpdateCheckSum(u32bits baseport)
{
	USHORT i,sum_data, eeprom_end;

	sum_data = 0x0000;


   if (RD_HARPOON(baseport+hp_page_ctrl) & NARROW_SCSI_CARD)
      eeprom_end = 512;
   else
      eeprom_end = 768;

	for (i = 1; i < eeprom_end/2; i++)
	{
		sum_data += utilEERead(baseport, i);
	}

   utilEEWriteOnOff(baseport,1);   /* Enable write access to the EEPROM */

   utilEEWrite(baseport, sum_data, EEPROM_CHECK_SUM/2);
   utilEEWriteOnOff(baseport,0);   /* Turn off write access */
}

void SccbMgr_save_foreign_state(PADAPTER_INFO pAdapterInfo)
{
}


void SccbMgr_restore_foreign_state(CARD_HANDLE pCurrCard)
{
}

void SccbMgr_restore_native_state(CARD_HANDLE pCurrCard)
{
}

#endif /* NO_IOCTLS */

#endif /* (FW_TYPE==_UCB_MGR_)   */

#ifndef NO_IOCTLS
#if (FW_TYPE==_UCB_MGR_)
void SccbMgr_unload_card(CARD_HANDLE pCurrCard)
#else
#if defined(DOS)
void SccbMgr_unload_card(USHORT pCurrCard)
#else
void SccbMgr_unload_card(ULONG pCurrCard)
#endif
#endif
{
	UCHAR i;
#if defined(DOS)
	USHORT portBase;
	USHORT regOffset;
#else
	ULONG portBase;
	ULONG regOffset;
#endif
	ULONG scamData;
#if defined(OS2)
	ULONG far *pScamTbl;
#else
	ULONG *pScamTbl;
#endif
	PNVRamInfo pCurrNvRam;

	pCurrNvRam = ((PSCCBcard)pCurrCard)->pNvRamInfo;

	if(pCurrNvRam){
		WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
		WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
		WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
		WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
		WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);

		for(i = 0; i < MAX_SCSI_TAR / 2; i++)
			WrStack(pCurrNvRam->niBaseAddr, (UCHAR)(i+5), pCurrNvRam->niSyncTbl[i]);

		portBase = pCurrNvRam->niBaseAddr;

		for(i = 0; i < MAX_SCSI_TAR; i++){
			regOffset = hp_aramBase + 64 + i*4;
#if defined(OS2)
			pScamTbl = (ULONG far *) &pCurrNvRam->niScamTbl[i];
#else
			pScamTbl = (ULONG *) &pCurrNvRam->niScamTbl[i];
#endif
			scamData = *pScamTbl;
			WR_HARP32(portBase, regOffset, scamData);
		}

	}else{
		WrStack(((PSCCBcard)pCurrCard)->ioPort, 0, 0);
	}
}
#endif /* NO_IOCTLS */


void RNVRamData(PNVRamInfo pNvRamInfo)
{
	UCHAR i;
#if defined(DOS)
	USHORT portBase;
	USHORT regOffset;
#else
	ULONG portBase;
	ULONG regOffset;
#endif
	ULONG scamData;
#if defined (OS2)
	ULONG far *pScamTbl;
#else
	ULONG *pScamTbl;
#endif

	pNvRamInfo->niModel    = RdStack(pNvRamInfo->niBaseAddr, 0);
	pNvRamInfo->niSysConf  = RdStack(pNvRamInfo->niBaseAddr, 1);
	pNvRamInfo->niScsiConf = RdStack(pNvRamInfo->niBaseAddr, 2);
	pNvRamInfo->niScamConf = RdStack(pNvRamInfo->niBaseAddr, 3);
	pNvRamInfo->niAdapId   = RdStack(pNvRamInfo->niBaseAddr, 4);

	for(i = 0; i < MAX_SCSI_TAR / 2; i++)
		pNvRamInfo->niSyncTbl[i] = RdStack(pNvRamInfo->niBaseAddr, (UCHAR)(i+5));

	portBase = pNvRamInfo->niBaseAddr;

	for(i = 0; i < MAX_SCSI_TAR; i++){
		regOffset = hp_aramBase + 64 + i*4;
		RD_HARP32(portBase, regOffset, scamData);
#if defined(OS2)
		pScamTbl = (ULONG far *) &pNvRamInfo->niScamTbl[i];
#else
		pScamTbl = (ULONG *) &pNvRamInfo->niScamTbl[i];
#endif
		*pScamTbl = scamData;
	}

}

#if defined(DOS)
UCHAR RdStack(USHORT portBase, UCHAR index)
#else
UCHAR RdStack(ULONG portBase, UCHAR index)
#endif
{
	WR_HARPOON(portBase + hp_stack_addr, index);
	return(RD_HARPOON(portBase + hp_stack_data));
}

#if defined(DOS)
void WrStack(USHORT portBase, UCHAR index, UCHAR data)
#else
void WrStack(ULONG portBase, UCHAR index, UCHAR data)
#endif
{
	WR_HARPOON(portBase + hp_stack_addr, index);
	WR_HARPOON(portBase + hp_stack_data, data);
}


#if (FW_TYPE==_UCB_MGR_)
u08bits ChkIfChipInitialized(BASE_PORT ioPort)
#else
#if defined(DOS)
UCHAR ChkIfChipInitialized(USHORT ioPort)
#else
UCHAR ChkIfChipInitialized(ULONG ioPort)
#endif
#endif
{
	if((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != RdStack(ioPort, 4))
		return(FALSE);
	if((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
								!= CLKCTRL_DEFAULT)
		return(FALSE);
	if((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
		(RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
		return(TRUE);
	return(FALSE);

}
/*---------------------------------------------------------------------
 *
 * Function: SccbMgr_start_sccb
 *
 * Description: Start a command pointed to by p_Sccb. When the
 *              command is completed it will be returned via the
 *              callback function.
 *
 *---------------------------------------------------------------------*/
#if (FW_TYPE==_UCB_MGR_)
void SccbMgr_start_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb)
#else
#if defined(DOS)
void SccbMgr_start_sccb(USHORT pCurrCard, PSCCB p_Sccb)
#else
void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb)
#endif
#endif
{
#if defined(DOS)
   USHORT ioport;
#else
   ULONG ioport;
#endif
   UCHAR thisCard, lun;
	PSCCB pSaveSccb;
   CALL_BK_FN callback;

#if (FW_TYPE==_UCB_MGR_)
   PSCCB p_Sccb;
#endif

   mOS_Lock((PSCCBcard)pCurrCard);
   thisCard = ((PSCCBcard) pCurrCard)->cardIndex;
   ioport = ((PSCCBcard) pCurrCard)->ioPort;

#if (FW_TYPE==_UCB_MGR_)
   p_Sccb = (PSCCB)p_ucb->UCB_MgrPrivatePtr;
#endif

	if((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN))
	{

#if (FW_TYPE==_UCB_MGR_)
		p_ucb->UCB_hbastat = SCCB_COMPLETE;
		p_ucb->UCB_status=SCCB_ERROR;
		callback = (CALL_BK_FN)p_ucb->UCB_callback;
		if (callback)
			callback(p_ucb);
#endif

#if (FW_TYPE==_SCCB_MGR_)
		p_Sccb->HostStatus = SCCB_COMPLETE;
		p_Sccb->SccbStatus = SCCB_ERROR;
		callback = (CALL_BK_FN)p_Sccb->SccbCallback;
		if (callback)
			callback(p_Sccb);
#endif

		mOS_UnLock((PSCCBcard)pCurrCard);
		return;
	}

#if (FW_TYPE==_SCCB_MGR_)
   sinits(p_Sccb,thisCard);
#endif


#if (FW_TYPE==_UCB_MGR_)
#ifndef NO_IOCTLS

   if (p_ucb->UCB_opcode & OPC_IOCTL)
	{

		switch (p_ucb->UCB_IOCTLCommand) 
		{
			case READ_NVRAM:
				ReadNVRam((PSCCBcard)pCurrCard,p_ucb);
				p_ucb->UCB_status=UCB_SUCCESS;
				callback = (CALL_BK_FN)p_ucb->UCB_callback;
				if (callback)
					callback(p_ucb);
				mOS_UnLock((PSCCBcard)pCurrCard);
				return;

			case WRITE_NVRAM:
				WriteNVRam((PSCCBcard)pCurrCard,p_ucb);
				p_ucb->UCB_status=UCB_SUCCESS;
				callback = (CALL_BK_FN)p_ucb->UCB_callback;
				if (callback)
					callback(p_ucb);
				mOS_UnLock((PSCCBcard)pCurrCard);
				return;

			case SEND_SCSI_PASSTHRU:
#if (FW_TYPE != _SCCB_MGR_)
				if( p_ucb->UCB_targid >=
				    ((PSCCBcard)pCurrCard)->cardInfo->ai_MaxTarg )
				{
					p_ucb->UCB_status = UCB_ERROR;
					p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
					callback = (CALL_BK_FN)p_ucb->UCB_callback;
					if (callback)
						callback(p_ucb);
					mOS_UnLock((PSCCBcard)pCurrCard);
					return;
				}
#endif
				break;

			case HARD_RESET:
				p_ucb->UCB_status = UCB_INVALID;
				callback = (CALL_BK_FN)p_ucb->UCB_callback;
				if (callback)
					callback(p_ucb);
				mOS_UnLock((PSCCBcard)pCurrCard);
				return;
			case GET_DEVICE_SYNCRATE:
				if( !GetDevSyncRate((PSCCBcard)pCurrCard,p_ucb) )
				{
					p_ucb->UCB_status = UCB_SUCCESS;
				}
				else
				{
					p_ucb->UCB_status = UCB_ERROR;
					p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
				}
				callback = (CALL_BK_FN)p_ucb->UCB_callback;
				if (callback)
					callback(p_ucb);
				mOS_UnLock((PSCCBcard)pCurrCard);
				return;
			case SET_DEVICE_SYNCRATE:
				if( !SetDevSyncRate((PSCCBcard)pCurrCard,p_ucb) )
				{
					p_ucb->UCB_status = UCB_SUCCESS;
				}
				else
				{
					p_ucb->UCB_status = UCB_ERROR;
					p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
				}
				callback = (CALL_BK_FN)p_ucb->UCB_callback;
				if (callback)
					callback(p_ucb);
				mOS_UnLock((PSCCBcard)pCurrCard);
				return;
			case GET_WIDE_MODE:
				if( !GetDevWideMode((PSCCBcard)pCurrCard,p_ucb) )
				{
					p_ucb->UCB_status = UCB_SUCCESS;
				}
				else
				{
					p_ucb->UCB_status = UCB_ERROR;
					p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
				}
				callback = (CALL_BK_FN)p_ucb->UCB_callback;
				if (callback)
					callback(p_ucb);
				mOS_UnLock((PSCCBcard)pCurrCard);
				return;
			case SET_WIDE_MODE:
				if( !SetDevWideMode((PSCCBcard)pCurrCard,p_ucb) )
				{
					p_ucb->UCB_status = UCB_SUCCESS;
				}
				else
				{
					p_ucb->UCB_status = UCB_ERROR;
					p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
				}
				callback = (CALL_BK_FN)p_ucb->UCB_callback;
				if (callback)
					callback(p_ucb);
				mOS_UnLock((PSCCBcard)pCurrCard);
				return;
			default:
				p_ucb->UCB_status=UCB_INVALID;
				callback = (CALL_BK_FN)p_ucb->UCB_callback;
				if (callback)
					callback(p_ucb);
				mOS_UnLock((PSCCBcard)pCurrCard);
				return;
		}
	}
#endif /* NO_IOCTLS */
#endif /* (FW_TYPE==_UCB_MGR_) */


   if (!((PSCCBcard) pCurrCard)->cmdCounter)
      {
      WR_HARPOON(ioport+hp_semaphore, (RD_HARPOON(ioport+hp_semaphore)
         | SCCB_MGR_ACTIVE));

      if (((PSCCBcard) pCurrCard)->globalFlags & F_GREEN_PC)
         {
		 WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT);
		 WR_HARPOON(ioport+hp_sys_ctrl, 0x00);
         }
      }

   ((PSCCBcard)pCurrCard)->cmdCounter++;

   if (RD_HARPOON(ioport+hp_semaphore) & BIOS_IN_USE) {

      WR_HARPOON(ioport+hp_semaphore, (RD_HARPOON(ioport+hp_semaphore)
         | TICKLE_ME));
		if(p_Sccb->OperationCode == RESET_COMMAND)
			{
				pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB;
				((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
				queueSelectFail(&BL_Card[thisCard], thisCard);
				((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb;
			}
		else
			{
	      queueAddSccb(p_Sccb,thisCard);
			}
      }

   else if ((RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE)) {

			if(p_Sccb->OperationCode == RESET_COMMAND)
				{
					pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB;
					((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
					queueSelectFail(&BL_Card[thisCard], thisCard);
					((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb;
				}
			else
				{
		      queueAddSccb(p_Sccb,thisCard);
				}
      }

   else {

      MDISABLE_INT(ioport);

		if((((PSCCBcard) pCurrCard)->globalFlags & F_CONLUN_IO) && 
			((sccbMgrTbl[thisCard][p_Sccb->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
			lun = p_Sccb->Lun;
		else
			lun = 0;
      if ((((PSCCBcard) pCurrCard)->currentSCCB == NULL) &&
         (sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0) &&
         (sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
         == FALSE)) {

            ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
			   mOS_UnLock((PSCCBcard)pCurrCard);
#if defined(DOS)
            ssel((USHORT)p_Sccb->SccbIOPort,thisCard);
#else
	    ssel(p_Sccb->SccbIOPort,thisCard);
#endif
			   mOS_Lock((PSCCBcard)pCurrCard);
         }

      else {

			if(p_Sccb->OperationCode == RESET_COMMAND)
				{
					pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB;
					((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
					queueSelectFail(&BL_Card[thisCard], thisCard);
					((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb;
				}
			else
				{
	         	queueAddSccb(p_Sccb,thisCard);
				}
         }


      MENABLE_INT(ioport);
      }

   mOS_UnLock((PSCCBcard)pCurrCard);
}


/*---------------------------------------------------------------------
 *
 * Function: SccbMgr_abort_sccb
 *
 * Description: Abort the command pointed to by p_Sccb.  When the
 *              command is completed it will be returned via the
 *              callback function.
 *
 *---------------------------------------------------------------------*/
#if (FW_TYPE==_UCB_MGR_)
s32bits SccbMgr_abort_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb)
#else
#if defined(DOS)
int SccbMgr_abort_sccb(USHORT pCurrCard, PSCCB p_Sccb)
#else
int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb)
#endif
#endif

{
#if defined(DOS)
	USHORT ioport;
#else
	ULONG ioport;
#endif

	UCHAR thisCard;
	CALL_BK_FN callback;
	UCHAR TID;
	PSCCB pSaveSCCB;
	PSCCBMgr_tar_info currTar_Info;


#if (FW_TYPE==_UCB_MGR_)
	PSCCB    p_Sccb;
	p_Sccb=(PSCCB)p_ucb->UCB_MgrPrivatePtr;
#endif

	ioport = ((PSCCBcard) pCurrCard)->ioPort;

	thisCard = ((PSCCBcard)pCurrCard)->cardIndex;

	mOS_Lock((PSCCBcard)pCurrCard);

	if (RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE)
	{
		mOS_UnLock((PSCCBcard)pCurrCard);
	}

	else
	{

		if (queueFindSccb(p_Sccb,thisCard))
		{

			mOS_UnLock((PSCCBcard)pCurrCard);

			((PSCCBcard)pCurrCard)->cmdCounter--;

			if (!((PSCCBcard)pCurrCard)->cmdCounter)
				WR_HARPOON(ioport+hp_semaphore,(RD_HARPOON(ioport+hp_semaphore)
					& (UCHAR)(~(SCCB_MGR_ACTIVE | TICKLE_ME)) ));

#if (FW_TYPE==_SCCB_MGR_)
			p_Sccb->SccbStatus = SCCB_ABORT;
			callback = p_Sccb->SccbCallback;
			callback(p_Sccb);
#else
			p_ucb->UCB_status=SCCB_ABORT;
			callback = (CALL_BK_FN)p_ucb->UCB_callback;
			callback(p_ucb);
#endif

			return(0);
		}

		else
		{
			mOS_UnLock((PSCCBcard)pCurrCard);

			if (((PSCCBcard)pCurrCard)->currentSCCB == p_Sccb)
			{
				p_Sccb->SccbStatus = SCCB_ABORT;
				return(0);

			}

			else
			{

				TID = p_Sccb->TargID;


				if(p_Sccb->Sccb_tag)
				{
					MDISABLE_INT(ioport);
					if (((PSCCBcard) pCurrCard)->discQ_Tbl[p_Sccb->Sccb_tag]==p_Sccb)
					{
						p_Sccb->SccbStatus = SCCB_ABORT;
						p_Sccb->Sccb_scsistat = ABORT_ST;
#if (FW_TYPE==_UCB_MGR_)
						p_ucb->UCB_status=SCCB_ABORT;
#endif
						p_Sccb->Sccb_scsimsg = SMABORT_TAG;

						if(((PSCCBcard) pCurrCard)->currentSCCB == NULL)
						{
							((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
							ssel(ioport, thisCard);
						}
						else
						{
							pSaveSCCB = ((PSCCBcard) pCurrCard)->currentSCCB;
							((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
							queueSelectFail((PSCCBcard) pCurrCard, thisCard);
							((PSCCBcard) pCurrCard)->currentSCCB = pSaveSCCB;
						}
					}
					MENABLE_INT(ioport);
					return(0);
				}
				else
				{
					currTar_Info = &sccbMgrTbl[thisCard][p_Sccb->TargID];

					if(BL_Card[thisCard].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_Sccb->Lun]] 
							== p_Sccb)
					{
						p_Sccb->SccbStatus = SCCB_ABORT;
						return(0);
					}
				}
			}
		}
	}
	return(-1);
}


/*---------------------------------------------------------------------
 *
 * Function: SccbMgr_my_int
 *
 * Description: Do a quick check to determine if there is a pending
 *              interrupt for this card and disable the IRQ Pin if so.
 *
 *---------------------------------------------------------------------*/
#if (FW_TYPE==_UCB_MGR_)
u08bits SccbMgr_my_int(CARD_HANDLE pCurrCard)
#else
#if defined(DOS)
UCHAR SccbMgr_my_int(USHORT pCurrCard)
#else
UCHAR SccbMgr_my_int(ULONG pCurrCard)
#endif
#endif
{
#if defined(DOS)
   USHORT ioport;
#else
   ULONG ioport;
#endif

   ioport = ((PSCCBcard)pCurrCard)->ioPort;

   if (RD_HARPOON(ioport+hp_int_status) & INT_ASSERTED)
   {

#if defined(DOS)
      MDISABLE_INT(ioport);
#endif

      return(TRUE);
   }

   else

      return(FALSE);
}



/*---------------------------------------------------------------------
 *
 * Function: SccbMgr_isr
 *
 * Description: This is our entry point when an interrupt is generated
 *              by the card and the upper level driver passes it on to
 *              us.
 *
 *---------------------------------------------------------------------*/
#if (FW_TYPE==_UCB_MGR_)
s32bits SccbMgr_isr(CARD_HANDLE pCurrCard)
#else
#if defined(DOS)
int SccbMgr_isr(USHORT pCurrCard)
#else
int SccbMgr_isr(ULONG pCurrCard)
#endif
#endif
{
   PSCCB currSCCB;
   UCHAR thisCard,result,bm_status, bm_int_st;
   USHORT hp_int;
   UCHAR i, target;
#if defined(DOS)
   USHORT ioport;
#else
   ULONG ioport;
#endif

   mOS_Lock((PSCCBcard)pCurrCard);

   thisCard = ((PSCCBcard)pCurrCard)->cardIndex;
   ioport = ((PSCCBcard)pCurrCard)->ioPort;

   MDISABLE_INT(ioport);

#if defined(BUGBUG)
   WR_HARPOON(ioport+hp_user_defined_D, RD_HARPOON(ioport+hp_int_status));
#endif

   if ((bm_int_st=RD_HARPOON(ioport+hp_int_status)) & EXT_STATUS_ON)
		bm_status = RD_HARPOON(ioport+hp_ext_status) & (UCHAR)BAD_EXT_STATUS;
   else
      bm_status = 0;

   WR_HARPOON(ioport+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));

   mOS_UnLock((PSCCBcard)pCurrCard);

   while ((hp_int = RDW_HARPOON((ioport+hp_intstat)) & default_intena) |
	  bm_status)
     {

       currSCCB = ((PSCCBcard)pCurrCard)->currentSCCB;

#if defined(BUGBUG)
   Debug_Load(thisCard,(UCHAR) 0XFF);
   Debug_Load(thisCard,bm_int_st);

   Debug_Load(thisCard,hp_int_0);
   Debug_Load(thisCard,hp_int_1);
#endif


      if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
         result = SccbMgr_bad_isr(ioport,thisCard,((PSCCBcard)pCurrCard),hp_int);
         WRW_HARPOON((ioport+hp_intstat), (FIFO | TIMEOUT | RESET | SCAM_SEL));
         bm_status = 0;

         if (result) {

			   mOS_Lock((PSCCBcard)pCurrCard);
            MENABLE_INT(ioport);
			   mOS_UnLock((PSCCBcard)pCurrCard);
            return(result);
            }
         }


      else if (hp_int & ICMD_COMP) {

         if ( !(hp_int & BUS_FREE) ) {
            /* Wait for the BusFree before starting a new command.  We
               must also check for being reselected since the BusFree
               may not show up if another device reselects us in 1.5us or
               less.  SRR Wednesday, 3/8/1995.
	         */
	   while (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL))) ;
	 }

         if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT)

            phaseChkFifo(ioport, thisCard);

/*         WRW_HARPOON((ioport+hp_intstat),
            (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
         */

		 WRW_HARPOON((ioport+hp_intstat), CLR_ALL_INT_1);

         autoCmdCmplt(ioport,thisCard);

         }


      else if (hp_int & ITAR_DISC)
         {

         if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) {

            phaseChkFifo(ioport, thisCard);

            }

         if (RD_HARPOON(ioport+hp_gp_reg_1) == SMSAVE_DATA_PTR) {

            WR_HARPOON(ioport+hp_gp_reg_1, 0x00);
            currSCCB->Sccb_XferState |= F_NO_DATA_YET;

            currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
            }

         currSCCB->Sccb_scsistat = DISCONNECT_ST;
         queueDisconnect(currSCCB,thisCard);

            /* Wait for the BusFree before starting a new command.  We
               must also check for being reselected since the BusFree
               may not show up if another device reselects us in 1.5us or
               less.  SRR Wednesday, 3/8/1995.
             */
	   while (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL)) &&
		  !((RDW_HARPOON((ioport+hp_intstat)) & PHASE) &&
		    RD_HARPOON((ioport+hp_scsisig)) ==
		    (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG | SCSI_IOBIT))) ;

	   /*
	     The additional loop exit condition above detects a timing problem
	     with the revision D/E harpoon chips.  The caller should reset the
	     host adapter to recover when 0xFE is returned.
	   */
	   if (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL)))
	     {
	       mOS_Lock((PSCCBcard)pCurrCard);
	       MENABLE_INT(ioport);
	       mOS_UnLock((PSCCBcard)pCurrCard);
	       return 0xFE;
	     }

         WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ITAR_DISC));


         ((PSCCBcard)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD;

      	}


      else if (hp_int & RSEL) {

         WRW_HARPOON((ioport+hp_intstat), (PROG_HLT | RSEL | PHASE | BUS_FREE));

         if (RDW_HARPOON((ioport+hp_intstat)) & ITAR_DISC)
		      {
            if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT)
			      {
               phaseChkFifo(ioport, thisCard);
               }

            if (RD_HARPOON(ioport+hp_gp_reg_1) == SMSAVE_DATA_PTR)
			      {
               WR_HARPOON(ioport+hp_gp_reg_1, 0x00);
               currSCCB->Sccb_XferState |= F_NO_DATA_YET;
               currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
               }

            WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ITAR_DISC));
            currSCCB->Sccb_scsistat = DISCONNECT_ST;
            queueDisconnect(currSCCB,thisCard);
            }

         sres(ioport,thisCard,((PSCCBcard)pCurrCard));
         phaseDecode(ioport,thisCard);

         }


      else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE)))
         {

            WRW_HARPOON((ioport+hp_intstat), (IDO_STRT | XFER_CNT_0));
            phaseDecode(ioport,thisCard);

         }


      else if ( (hp_int & IUNKWN) || (hp_int & PROG_HLT) )
		   {
	 	   WRW_HARPOON((ioport+hp_intstat), (PHASE | IUNKWN | PROG_HLT));
	 	   if ((RD_HARPOON(ioport+hp_prgmcnt_0) & (UCHAR)0x3f)< (UCHAR)SELCHK)
	    		{
	    		phaseDecode(ioport,thisCard);
	    		}
	 	   else
	    		{
   /* Harpoon problem some SCSI target device respond to selection
   with short BUSY pulse (<400ns) this will make the Harpoon is not able
   to latch the correct Target ID into reg. x53.
   The work around require to correct this reg. But when write to this
   reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
   need to read this reg first then restore it later. After update to 0x53 */

	    		i = (UCHAR)(RD_HARPOON(ioport+hp_fifowrite));
	    		target = (UCHAR)(RD_HARPOON(ioport+hp_gp_reg_3));
	    		WR_HARPOON(ioport+hp_xfer_pad, (UCHAR) ID_UNLOCK);
	    		WR_HARPOON(ioport+hp_select_id, (UCHAR)(target | target<<4));
	    		WR_HARPOON(ioport+hp_xfer_pad, (UCHAR) 0x00);
	    		WR_HARPOON(ioport+hp_fifowrite, i);
	    		WR_HARPOON(ioport+hp_autostart_3, (AUTO_IMMED+TAG_STRT));
	    		}
	 	   }

      else if (hp_int & XFER_CNT_0) {

         WRW_HARPOON((ioport+hp_intstat), XFER_CNT_0);

         schkdd(ioport,thisCard);

         }


      else if (hp_int & BUS_FREE) {

         WRW_HARPOON((ioport+hp_intstat), BUS_FREE);

        	if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) {

           	hostDataXferAbort(ioport,thisCard,currSCCB);
				}

         phaseBusFree(ioport,thisCard);
			}


      else if (hp_int & ITICKLE) {

         WRW_HARPOON((ioport+hp_intstat), ITICKLE);
         ((PSCCBcard)pCurrCard)->globalFlags |= F_NEW_SCCB_CMD;
         }



      if (((PSCCBcard)pCurrCard)->globalFlags & F_NEW_SCCB_CMD) {


         ((PSCCBcard)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD;


         if (((PSCCBcard)pCurrCard)->currentSCCB == NULL) {

            queueSearchSelect(((PSCCBcard)pCurrCard),thisCard);
            }

         if (((PSCCBcard)pCurrCard)->currentSCCB != NULL) {
            ((PSCCBcard)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD;
            ssel(ioport,thisCard);
            }

         break;

         }

      }  /*end while */

   mOS_Lock((PSCCBcard)pCurrCard);
   MENABLE_INT(ioport);
   mOS_UnLock((PSCCBcard)pCurrCard);

   return(0);
}

/*---------------------------------------------------------------------
 *
 * Function: Sccb_bad_isr
 *
 * Description: Some type of interrupt has occurred which is slightly
 *              out of the ordinary.  We will now decode it fully, in
 *              this routine.  This is broken up in an attempt to save
 *              processing time.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
UCHAR SccbMgr_bad_isr(USHORT p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int)
#else
UCHAR SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int)
#endif
{
#if defined(HARP_REVX)
   ULONG timer;
#endif
UCHAR temp, ScamFlg;
PSCCBMgr_tar_info currTar_Info;
PNVRamInfo pCurrNvRam;


   if (RD_HARPOON(p_port+hp_ext_status) &
         (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN) )
      {

      if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
         {

         hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB);
         }

      if (RD_HARPOON(p_port+hp_pci_stat_cfg) & REC_MASTER_ABORT)

         {
         WR_HARPOON(p_port+hp_pci_stat_cfg,
            (RD_HARPOON(p_port+hp_pci_stat_cfg) & ~REC_MASTER_ABORT));

         WR_HARPOON(p_port+hp_host_blk_cnt, 0x00);

         }

      if (pCurrCard->currentSCCB != NULL)
         {

         if (!pCurrCard->currentSCCB->HostStatus)
            pCurrCard->currentSCCB->HostStatus = SCCB_BM_ERR;

         sxfrp(p_port,p_card);

	     temp = (UCHAR)(RD_HARPOON(p_port+hp_ee_ctrl) &
							(EXT_ARB_ACK | SCSI_TERM_ENA_H));
      	WR_HARPOON(p_port+hp_ee_ctrl, ((UCHAR)temp | SEE_MS | SEE_CS));
         WR_HARPOON(p_port+hp_ee_ctrl, temp);

         if (!(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET)))
            {
            phaseDecode(p_port,p_card);
            }
         }
      }


   else if (p_int & RESET)
         {

				WR_HARPOON(p_port+hp_clkctrl_0, CLKCTRL_DEFAULT);
				WR_HARPOON(p_port+hp_sys_ctrl, 0x00);
           if (pCurrCard->currentSCCB != NULL) {

               if (pCurrCard->globalFlags & F_HOST_XFER_ACT)

               hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB);
               }


           DISABLE_AUTO(p_port);

           sresb(p_port,p_card);

           while(RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST) {}

				pCurrNvRam = pCurrCard->pNvRamInfo;
				if(pCurrNvRam){
					ScamFlg = pCurrNvRam->niScamConf;
				}
				else{
				   ScamFlg = (UCHAR) utilEERead(p_port, SCAM_CONFIG/2);
				}

           XbowInit(p_port, ScamFlg);

               scini(p_card, pCurrCard->ourId, 0);

           return(0xFF);
         }


   else if (p_int & FIFO) {

      WRW_HARPOON((p_port+hp_intstat), FIFO);

#if defined(HARP_REVX)

      for (timer=0x00FFFFFFL; timer != 0x00000000L; timer--) {

         if (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY)
            break;

         if (RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE)
            break;
         }


      if ( (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY) &&
           (RD_HARPOON(p_port+hp_fiforead) !=
            RD_HARPOON(p_port+hp_fifowrite)) &&
           (RD_HARPOON(p_port+hp_xfercnt_0))
         )

            WR_HARPOON((p_port+hp_xferstat), 0x01);

/*      else
 */
/*         sxfrp(p_port,p_card);
 */
#else
      if (pCurrCard->currentSCCB != NULL)
         sxfrp(p_port,p_card);
#endif
      }

   else if (p_int & TIMEOUT)
      {

      DISABLE_AUTO(p_port);

      WRW_HARPOON((p_port+hp_intstat),
		  (PROG_HLT | TIMEOUT | SEL |BUS_FREE | PHASE | IUNKWN));

      pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;


		currTar_Info = &sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
		if((pCurrCard->globalFlags & F_CONLUN_IO) &&
			((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
	      currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] = FALSE;
		else
	      currTar_Info->TarLUNBusy[0] = FALSE;


      if (currTar_Info->TarEEValue & EE_SYNC_MASK)
         {
	       currTar_Info->TarSyncCtrl = 0;
         currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
         }

      if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
         {
         currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
         }

      sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,currTar_Info);

      queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);

      }

#if defined(SCAM_LEV_2)

   else if (p_int & SCAM_SEL)
      {

      scarb(p_port,LEVEL2_TAR);
      scsel(p_port);
      scasid(p_card, p_port);

      scbusf(p_port);

      WRW_HARPOON((p_port+hp_intstat), SCAM_SEL);
      }
#endif

   return(0x00);
}


/*---------------------------------------------------------------------
 *
 * Function: SccbMgr_scsi_reset
 *
 * Description: A SCSI bus reset will be generated and all outstanding
 *              Sccbs will be returned via the callback.
 *
 *---------------------------------------------------------------------*/
#if (FW_TYPE==_UCB_MGR_)
void SccbMgr_scsi_reset(CARD_HANDLE pCurrCard)
#else
#if defined(DOS)
void SccbMgr_scsi_reset(USHORT pCurrCard)
#else
void SccbMgr_scsi_reset(ULONG pCurrCard)
#endif
#endif
{
   UCHAR thisCard;

   thisCard = ((PSCCBcard)pCurrCard)->cardIndex;

   mOS_Lock((PSCCBcard)pCurrCard);

   if (((PSCCBcard) pCurrCard)->globalFlags & F_GREEN_PC)
      {
      WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_clkctrl_0, CLKCTRL_DEFAULT);
      WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_sys_ctrl, 0x00);
      }

   sresb(((PSCCBcard)pCurrCard)->ioPort,thisCard);

   if (RD_HARPOON(((PSCCBcard)pCurrCard)->ioPort+hp_ext_status) & BM_CMD_BUSY)
      {
      WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_page_ctrl,
         (RD_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_page_ctrl)
         & ~SCATTER_EN));

      WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_sg_addr,0x00);

      ((PSCCBcard) pCurrCard)->globalFlags &= ~F_HOST_XFER_ACT;
      busMstrTimeOut(((PSCCBcard) pCurrCard)->ioPort);

      WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_int_mask,
         (INT_CMD_COMPL | SCSI_INTERRUPT));
      }

/*
      if (utilEERead(((PSCCBcard)pCurrCard)->ioPort, (SCAM_CONFIG/2))
            & SCAM_ENABLED)
*/
         scini(thisCard, ((PSCCBcard)pCurrCard)->ourId, 0);

#if (FW_TYPE==_UCB_MGR_)
   ((PSCCBcard)pCurrCard)->cardInfo->ai_AEN_routine(0x01,pCurrCard,0,0,0,0);
#endif

   mOS_UnLock((PSCCBcard)pCurrCard);
}


/*---------------------------------------------------------------------
 *
 * Function: SccbMgr_timer_expired
 *
 * Description: This function allow me to kill my own job that has not
 *              yet completed, and has cause a timeout to occur.  This
 *              timeout has caused the upper level driver to call this
 *              function.
 *
 *---------------------------------------------------------------------*/

#if (FW_TYPE==_UCB_MGR_)
void SccbMgr_timer_expired(CARD_HANDLE pCurrCard)
#else
#if defined(DOS)
void SccbMgr_timer_expired(USHORT pCurrCard)
#else
void SccbMgr_timer_expired(ULONG pCurrCard)
#endif
#endif
{
}

#if defined(DOS)
/*---------------------------------------------------------------------
 *
 * Function: SccbMgr_status
 *
 * Description: This function returns the number of outstanding SCCB's.
 *              This is specific to the DOS enviroment, which needs this
 *              to help them keep protected and real mode commands staight.
 *
 *---------------------------------------------------------------------*/

USHORT SccbMgr_status(USHORT pCurrCard)
{
   return(BL_Card[pCurrCard].cmdCounter);
}
#endif

/*---------------------------------------------------------------------
 *
 * Function: SccbMgrTableInit
 *
 * Description: Initialize all Sccb manager data structures.
 *
 *---------------------------------------------------------------------*/

void SccbMgrTableInitAll()
{
   UCHAR thisCard;

   for (thisCard = 0; thisCard < MAX_CARDS; thisCard++)
      {
      SccbMgrTableInitCard(&BL_Card[thisCard],thisCard);

      BL_Card[thisCard].ioPort      = 0x00;
      BL_Card[thisCard].cardInfo    = NULL;
      BL_Card[thisCard].cardIndex   = 0xFF;
      BL_Card[thisCard].ourId       = 0x00;
		BL_Card[thisCard].pNvRamInfo	= NULL;
      }
}


/*---------------------------------------------------------------------
 *
 * Function: SccbMgrTableInit
 *
 * Description: Initialize all Sccb manager data structures.
 *
 *---------------------------------------------------------------------*/

void SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card)
{
   UCHAR scsiID, qtag;

	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++)
	{
		BL_Card[p_card].discQ_Tbl[qtag] = NULL;
	}

   for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++)
      {
      sccbMgrTbl[p_card][scsiID].TarStatus = 0;
      sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
      SccbMgrTableInitTarget(p_card, scsiID);
      }

   pCurrCard->scanIndex = 0x00;
   pCurrCard->currentSCCB = NULL;
   pCurrCard->globalFlags = 0x00;
   pCurrCard->cmdCounter  = 0x00;
	pCurrCard->tagQ_Lst = 0x01;
	pCurrCard->discQCount = 0; 


}


/*---------------------------------------------------------------------
 *
 * Function: SccbMgrTableInit
 *
 * Description: Initialize all Sccb manager data structures.
 *
 *---------------------------------------------------------------------*/

void SccbMgrTableInitTarget(UCHAR p_card, UCHAR target)
{

	UCHAR lun, qtag;
	PSCCBMgr_tar_info currTar_Info;

	currTar_Info = &sccbMgrTbl[p_card][target];

	currTar_Info->TarSelQ_Cnt = 0;
	currTar_Info->TarSyncCtrl = 0;

	currTar_Info->TarSelQ_Head = NULL;
	currTar_Info->TarSelQ_Tail = NULL;
	currTar_Info->TarTagQ_Cnt = 0;
	currTar_Info->TarLUN_CA = FALSE;


	for (lun = 0; lun < MAX_LUN; lun++)
	{
		currTar_Info->TarLUNBusy[lun] = FALSE;
		currTar_Info->LunDiscQ_Idx[lun] = 0;
	}

	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++)
	{
		if(BL_Card[p_card].discQ_Tbl[qtag] != NULL)
		{
			if(BL_Card[p_card].discQ_Tbl[qtag]->TargID == target)
			{
				BL_Card[p_card].discQ_Tbl[qtag] = NULL;
				BL_Card[p_card].discQCount--;
			}
		}
	}
}

#if defined(BUGBUG)

/*****************************************************************
 * Save the current byte in the debug array
 *****************************************************************/


void Debug_Load(UCHAR p_card, UCHAR p_bug_data)
{
   debug_int[p_card][debug_index[p_card]] = p_bug_data;
   debug_index[p_card]++;

   if (debug_index[p_card] == debug_size)

      debug_index[p_card] = 0;
}

#endif
#ident "$Id: sccb_dat.c 1.10 1997/02/22 03:16:02 awin Exp $"
/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   sccb_dat.c  $
 *
 *   Description:  Functions relating to handling of the SCCB interface 
 *                 between the device driver and the HARPOON.
 *
 *   $Date: 1997/02/22 03:16:02 $
 *
 *   $Revision: 1.10 $
 *
 *----------------------------------------------------------------------*/

/*#include <globals.h>*/

#if (FW_TYPE==_UCB_MGR_)
	/*#include <budi.h>*/
#endif

/*#include <sccbmgr.h>*/
/*#include <blx30.h>*/
/*#include <target.h>*/
/*#include <harpoon.h>*/

/*
**  IMPORTANT NOTE!!!
**
**  You MUST preassign all data to a valid value or zero.  This is
**  required due to the MS compiler bug under OS/2 and Solaris Real-Mode
**  driver environment.
*/


SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } };
SCCBCARD BL_Card[MAX_CARDS] = { { 0 } };
SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR] = { { { 0 } } };
NVRAMINFO nvRamInfo[MAX_MB_CARDS] = { { 0 } };


#if defined(OS2)
void (far *s_PhaseTbl[8]) (ULONG, UCHAR) = { 0 };
UCHAR temp_id_string[ID_STRING_LENGTH] = { 0 };
#elif defined(SOLARIS_REAL_MODE) || defined(__STDC__)
void (*s_PhaseTbl[8]) (ULONG, UCHAR) = { 0 };
#else
void (*s_PhaseTbl[8]) ();
#endif

#if defined(DOS)
UCHAR first_time = 0;
#endif

UCHAR mbCards = 0;
UCHAR scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', \
								' ', 'B', 'T', '-', '9', '3', '0', \
								0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \
								0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};

USHORT default_intena = 0;

#if defined(BUGBUG)
UCHAR    debug_int[MAX_CARDS][debug_size] = { 0 };
UCHAR    debug_index[MAX_CARDS] = { 0 };
UCHAR    reserved_1[3] = { 0 };
#endif
#ident "$Id: scsi.c 1.23 1997/07/09 21:42:54 mohan Exp $"
/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   scsi.c  $
 *
 *   Description:  Functions for handling SCSI bus functions such as
 *                 selection/reselection, sync negotiation, message-in
 *                 decoding.
 *
 *   $Date: 1997/07/09 21:42:54 $
 *
 *   $Revision: 1.23 $
 *
 *----------------------------------------------------------------------*/

/*#include <globals.h>*/

#if (FW_TYPE==_UCB_MGR_)
	/*#include <budi.h>*/
#endif

/*#include <sccbmgr.h>*/
/*#include <blx30.h>*/
/*#include <target.h>*/
/*#include <scsi2.h>*/
/*#include <eeprom.h>*/
/*#include <harpoon.h>*/


/*
extern SCCBCARD BL_Card[MAX_CARDS];
extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
#if defined(BUGBUG)
void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
#endif
*/

/*---------------------------------------------------------------------
 *
 * Function: sfetm
 *
 * Description: Read in a message byte from the SCSI bus, and check
 *              for a parity error.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
UCHAR sfm(USHORT port, PSCCB pCurrSCCB)
#else
UCHAR sfm(ULONG port, PSCCB pCurrSCCB)
#endif
{
	UCHAR message;
	USHORT TimeOutLoop;

	TimeOutLoop = 0;
	while( (!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) &&
			(TimeOutLoop++ < 20000) ){}


	WR_HARPOON(port+hp_portctrl_0, SCSI_PORT);

	message = RD_HARPOON(port+hp_scsidata_0);

	WR_HARPOON(port+hp_scsisig, SCSI_ACK + S_MSGI_PH);


	if (TimeOutLoop > 20000)
		message = 0x00;   /* force message byte = 0 if Time Out on Req */

	if ((RDW_HARPOON((port+hp_intstat)) & PARITY) &&
		(RD_HARPOON(port+hp_addstat) & SCSI_PAR_ERR))
	{
		WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH));
		WR_HARPOON(port+hp_xferstat, 0);
		WR_HARPOON(port+hp_fiforead, 0);
		WR_HARPOON(port+hp_fifowrite, 0);
		if (pCurrSCCB != NULL)
		{
			pCurrSCCB->Sccb_scsimsg = SMPARITY;
		}
		message = 0x00;
		do
		{
			ACCEPT_MSG_ATN(port);
			TimeOutLoop = 0;
			while( (!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) &&
				(TimeOutLoop++ < 20000) ){}
			if (TimeOutLoop > 20000)
			{
				WRW_HARPOON((port+hp_intstat), PARITY);
				return(message);
			}
			if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) != S_MSGI_PH)
			{
				WRW_HARPOON((port+hp_intstat), PARITY);
				return(message);
			}
			WR_HARPOON(port+hp_portctrl_0, SCSI_PORT);

			RD_HARPOON(port+hp_scsidata_0);

			WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH));

		}while(1);

	}
	WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH));
	WR_HARPOON(port+hp_xferstat, 0);
	WR_HARPOON(port+hp_fiforead, 0);
	WR_HARPOON(port+hp_fifowrite, 0);
	return(message);
}


/*---------------------------------------------------------------------
 *
 * Function: ssel
 *
 * Description: Load up automation and select target device.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void ssel(USHORT port, UCHAR p_card)
#else
void ssel(ULONG port, UCHAR p_card)
#endif
{

#if defined(DOS)
   UCHAR auto_loaded, i, target, *theCCB;
#elif defined(OS2)
   UCHAR auto_loaded, i, target;
   UCHAR far *theCCB;
#else
   UCHAR auto_loaded, i, target, *theCCB;
#endif

#if defined(DOS)
   USHORT cdb_reg;
#else
   ULONG cdb_reg;
#endif
   PSCCBcard CurrCard;
   PSCCB currSCCB;
   PSCCBMgr_tar_info currTar_Info;
   UCHAR lastTag, lun;

   CurrCard = &BL_Card[p_card];
   currSCCB = CurrCard->currentSCCB;
   target = currSCCB->TargID;
   currTar_Info = &sccbMgrTbl[p_card][target];
   lastTag = CurrCard->tagQ_Lst;

   ARAM_ACCESS(port);


	if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
		currSCCB->ControlByte &= ~F_USE_CMD_Q;

	if(((CurrCard->globalFlags & F_CONLUN_IO) && 
		((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))

	   lun = currSCCB->Lun;
	else
		lun = 0;


#if defined(DOS)
   currTar_Info->TarLUNBusy[lun] = TRUE;

#else

   if (CurrCard->globalFlags & F_TAG_STARTED)
      {
      if (!(currSCCB->ControlByte & F_USE_CMD_Q))
         {
      	if ((currTar_Info->TarLUN_CA == FALSE)
      	    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
      	    == TAG_Q_TRYING))
            {

	         if (currTar_Info->TarTagQ_Cnt !=0)
                  {
         		   currTar_Info->TarLUNBusy[lun] = TRUE;
            		queueSelectFail(CurrCard,p_card);
					   SGRAM_ACCESS(port);
         		   return;
         		   }

            else {
         		  currTar_Info->TarLUNBusy[lun] = TRUE;
         		  }

   	      }  /*End non-tagged */

	      else {
	         currTar_Info->TarLUNBusy[lun] = TRUE;
	         }

	      }  /*!Use cmd Q Tagged */

	   else {
   	     if (currTar_Info->TarLUN_CA == TRUE)
               {
      	      queueSelectFail(CurrCard,p_card);
				   SGRAM_ACCESS(port);
      	      return;
	            }

	        currTar_Info->TarLUNBusy[lun] = TRUE;

   	     }  /*else use cmd Q tagged */

      }  /*if glob tagged started */

   else {
        currTar_Info->TarLUNBusy[lun] = TRUE;
        }

#endif /* DOS */



	if((((CurrCard->globalFlags & F_CONLUN_IO) && 
		((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) 
		|| (!(currSCCB->ControlByte & F_USE_CMD_Q))))
	{
		if(CurrCard->discQCount >= QUEUE_DEPTH)
		{
			currTar_Info->TarLUNBusy[lun] = TRUE;
			queueSelectFail(CurrCard,p_card);
			SGRAM_ACCESS(port);
			return;
		}
		for (i = 1; i < QUEUE_DEPTH; i++)
		{
			if (++lastTag >= QUEUE_DEPTH) lastTag = 1;
			if (CurrCard->discQ_Tbl[lastTag] == NULL)
			{
				CurrCard->tagQ_Lst = lastTag;
				currTar_Info->LunDiscQ_Idx[lun] = lastTag;
				CurrCard->discQ_Tbl[lastTag] = currSCCB;
				CurrCard->discQCount++;
				break;
			}
		}
		if(i == QUEUE_DEPTH)
		{
			currTar_Info->TarLUNBusy[lun] = TRUE;
			queueSelectFail(CurrCard,p_card);
			SGRAM_ACCESS(port);
			return;
		}
	}



   auto_loaded = FALSE;

   WR_HARPOON(port+hp_select_id, target);
   WR_HARPOON(port+hp_gp_reg_3, target);  /* Use by new automation logic */

   if (currSCCB->OperationCode == RESET_COMMAND) {
      WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+
               	 (currSCCB->Sccb_idmsg & ~DISC_PRIV)));

      WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+NP);

      currSCCB->Sccb_scsimsg = SMDEV_RESET;

      WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
      auto_loaded = TRUE;
      currSCCB->Sccb_scsistat = SELECT_BDR_ST;

      if (currTar_Info->TarEEValue & EE_SYNC_MASK)
         {
	       currTar_Info->TarSyncCtrl = 0;
	      currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
	      }

#if defined(WIDE_SCSI)

      if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
         {
      	currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
      	}
#endif

      sssyncv(port, target, NARROW_SCSI,currTar_Info);
      SccbMgrTableInitTarget(p_card, target);

      }

		else if(currSCCB->Sccb_scsistat == ABORT_ST)
		{
			WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+
								(currSCCB->Sccb_idmsg & ~DISC_PRIV)));

      WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ);

			WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+
								(((UCHAR)(currSCCB->ControlByte & TAG_TYPE_MASK)
								>> 6) | (UCHAR)0x20)));
			WRW_HARPOON((port+SYNC_MSGS+2),
							(MPM_OP+AMSG_OUT+currSCCB->Sccb_tag));
			WRW_HARPOON((port+SYNC_MSGS+4), (BRH_OP+ALWAYS+NP ));

			WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
			auto_loaded = TRUE;
		
		}

#if defined(WIDE_SCSI)


   else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED))  {
      auto_loaded = siwidn(port,p_card);
      currSCCB->Sccb_scsistat = SELECT_WN_ST;
      }

#endif


   else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
      == SYNC_SUPPORTED))  {
      auto_loaded = sisyncn(port,p_card, FALSE);
      currSCCB->Sccb_scsistat = SELECT_SN_ST;
      }


   if (!auto_loaded)
      {

#if !defined(DOS)
      if (currSCCB->ControlByte & F_USE_CMD_Q)
         {

         CurrCard->globalFlags |= F_TAG_STARTED;

         if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
            == TAG_Q_REJECT)
            {
            currSCCB->ControlByte &= ~F_USE_CMD_Q;

            /* Fix up the start instruction with a jump to
               Non-Tag-CMD handling */
            WRW_HARPOON((port+ID_MSG_STRT),BRH_OP+ALWAYS+NTCMD);

            WRW_HARPOON((port+NON_TAG_ID_MSG),
	                     (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg));

	         WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));

	         /* Setup our STATE so we know what happend when
               the wheels fall off. */
            currSCCB->Sccb_scsistat = SELECT_ST;

	         currTar_Info->TarLUNBusy[lun] = TRUE;
            }

         else
            {
            WRW_HARPOON((port+ID_MSG_STRT), (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg));

            WRW_HARPOON((port+ID_MSG_STRT+2), (MPM_OP+AMSG_OUT+
                        (((UCHAR)(currSCCB->ControlByte & TAG_TYPE_MASK)
                        >> 6) | (UCHAR)0x20)));

				for (i = 1; i < QUEUE_DEPTH; i++)
				{
					if (++lastTag >= QUEUE_DEPTH) lastTag = 1;
					if (CurrCard->discQ_Tbl[lastTag] == NULL)
					{
						WRW_HARPOON((port+ID_MSG_STRT+6),
							(MPM_OP+AMSG_OUT+lastTag));
						CurrCard->tagQ_Lst = lastTag;
						currSCCB->Sccb_tag = lastTag;
						CurrCard->discQ_Tbl[lastTag] = currSCCB;
						CurrCard->discQCount++;
						break;
					}
				}


            if ( i == QUEUE_DEPTH )
               {
   	         currTar_Info->TarLUNBusy[lun] = TRUE;
               queueSelectFail(CurrCard,p_card);
				   SGRAM_ACCESS(port);
   	         return;
   	         }

            currSCCB->Sccb_scsistat = SELECT_Q_ST;

   	      WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
            }
         }

      else
         {
#endif   /* !DOS */

         WRW_HARPOON((port+ID_MSG_STRT),BRH_OP+ALWAYS+NTCMD);

      	WRW_HARPOON((port+NON_TAG_ID_MSG),
            (MPM_OP+AMSG_OUT+currSCCB->Sccb_idmsg));

         currSCCB->Sccb_scsistat = SELECT_ST;

         WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
#if !defined(DOS)
         }
#endif


#if defined(OS2)
      theCCB = (UCHAR far *)&currSCCB->Cdb[0];
#else
      theCCB = (UCHAR *)&currSCCB->Cdb[0];
#endif

      cdb_reg = port + CMD_STRT;

      for (i=0; i < currSCCB->CdbLength; i++)
         {
         WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
         cdb_reg +=2;
         theCCB++;
         }

      if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
         WRW_HARPOON(cdb_reg, (BRH_OP+ALWAYS+    NP));

      }  /* auto_loaded */

#if defined(WIDE_SCSI)
   WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00);
   WR_HARPOON(port+hp_xferstat, 0x00);
#endif

   WRW_HARPOON((port+hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));

   WR_HARPOON(port+hp_portctrl_0,(SCSI_PORT));


   if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED))
      {
      WR_HARPOON(port+hp_scsictrl_0, (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
      }
   else
      {

/*      auto_loaded =  (RD_HARPOON(port+hp_autostart_3) & (UCHAR)0x1F);
      auto_loaded |= AUTO_IMMED; */
      auto_loaded = AUTO_IMMED;

      DISABLE_AUTO(port);

      WR_HARPOON(port+hp_autostart_3, auto_loaded);
      }

   SGRAM_ACCESS(port);
}


/*---------------------------------------------------------------------
 *
 * Function: sres
 *
 * Description: Hookup the correct CCB and handle the incoming messages.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void sres(USHORT port, UCHAR p_card, PSCCBcard pCurrCard)
#else
void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
#endif
{

#if defined(V302)
#ifdef DOS
   UCHAR our_target,message, msgRetryCount;
   extern UCHAR lun, tag;
#else
   UCHAR our_target,message,lun,tag, msgRetryCount;
#endif

#else  /* V302 */
   UCHAR our_target, message, lun = 0, tag, msgRetryCount;
#endif /* V302 */


   PSCCBMgr_tar_info currTar_Info;
	PSCCB currSCCB;




	if(pCurrCard->currentSCCB != NULL)
	{
		currTar_Info = &sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
		DISABLE_AUTO(port);


		WR_HARPOON((port+hp_scsictrl_0),(ENA_RESEL | ENA_SCAM_SEL));


		currSCCB = pCurrCard->currentSCCB;
		if(currSCCB->Sccb_scsistat == SELECT_WN_ST)
		{
			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
			currSCCB->Sccb_scsistat = BUS_FREE_ST;
		}
		if(currSCCB->Sccb_scsistat == SELECT_SN_ST)
		{
			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
			currSCCB->Sccb_scsistat = BUS_FREE_ST;
		}
		if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
			((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
		{
      	currTar_Info->TarLUNBusy[currSCCB->Lun] = FALSE;
			if(currSCCB->Sccb_scsistat != ABORT_ST)
			{
				pCurrCard->discQCount--;
				pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[currSCCB->Lun]] 
													= NULL;
			}
		}
		else
		{
	      currTar_Info->TarLUNBusy[0] = FALSE;
			if(currSCCB->Sccb_tag)
			{
				if(currSCCB->Sccb_scsistat != ABORT_ST)
				{
					pCurrCard->discQCount--;
					pCurrCard->discQ_Tbl[currSCCB->Sccb_tag] = NULL;
				}
			}else
			{
				if(currSCCB->Sccb_scsistat != ABORT_ST)
				{
					pCurrCard->discQCount--;
					pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL;
				}
			}
		}

      queueSelectFail(&BL_Card[p_card],p_card);
	}

#if defined(WIDE_SCSI)
	WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00);
#endif


	our_target = (UCHAR)(RD_HARPOON(port+hp_select_id) >> 4);
	currTar_Info = &sccbMgrTbl[p_card][our_target];


	msgRetryCount = 0;
	do
	{

#if defined(V302)

		message = GetTarLun(port, p_card, our_target, pCurrCard, &tag, &lun);

#else /* V302 */

		currTar_Info = &sccbMgrTbl[p_card][our_target];
		tag = 0;


		while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ))
		{
			if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY))
			{

				WRW_HARPOON((port+hp_intstat), PHASE);
				return;
			}
		}

		WRW_HARPOON((port+hp_intstat), PHASE);
		if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH)
		{

			message = sfm(port,pCurrCard->currentSCCB);
			if (message)
			{

				if (message <= (0x80 | LUN_MASK))
				{
					lun = message & (UCHAR)LUN_MASK;

#if !defined(DOS)
					if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING)
					{
						if (currTar_Info->TarTagQ_Cnt != 0)
						{

							if (!(currTar_Info->TarLUN_CA))
							{
								ACCEPT_MSG(port);    /*Release the ACK for ID msg. */


								message = sfm(port,pCurrCard->currentSCCB);
								if (message)
								{
									ACCEPT_MSG(port);
								}

								else
   								message = FALSE;

								if(message != FALSE)
								{
									tag = sfm(port,pCurrCard->currentSCCB);

									if (!(tag)) 
										message = FALSE;
								}

							} /*C.A. exists! */

						} /*End Q cnt != 0 */

					} /*End Tag cmds supported! */
#endif /* !DOS */

				} /*End valid ID message.  */

				else
				{

					ACCEPT_MSG_ATN(port);
				}

			} /* End good id message. */

			else
			{

				message = FALSE;
			}
		}
		else
		{
			ACCEPT_MSG_ATN(port);

		   while (!(RDW_HARPOON((port+hp_intstat)) & (PHASE | RESET)) &&
			  !(RD_HARPOON(port+hp_scsisig) & SCSI_REQ) &&
			  (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ;

			return;
		}
	
#endif /* V302 */

		if(message == FALSE)
		{
			msgRetryCount++;
			if(msgRetryCount == 1)
			{
				SendMsg(port, SMPARITY);
			}
			else
			{
				SendMsg(port, SMDEV_RESET);

				sssyncv(port, our_target, NARROW_SCSI,currTar_Info);

				if (sccbMgrTbl[p_card][our_target].TarEEValue & EE_SYNC_MASK) 
				{
			
					sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_SYNC_MASK;

				}

				if (sccbMgrTbl[p_card][our_target].TarEEValue & EE_WIDE_SCSI) 
				{

					sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_WIDE_MASK;
				}


				queueFlushTargSccb(p_card, our_target, SCCB_COMPLETE);
				SccbMgrTableInitTarget(p_card,our_target);
				return;
			}
		}
	}while(message == FALSE);



	if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
		((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
	{
		currTar_Info->TarLUNBusy[lun] = TRUE;
		pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
		if(pCurrCard->currentSCCB != NULL)
		{
			ACCEPT_MSG(port);
		}
		else 
		{
			ACCEPT_MSG_ATN(port);
		}
	}
	else
	{
		currTar_Info->TarLUNBusy[0] = TRUE;


		if (tag)
		{
			if (pCurrCard->discQ_Tbl[tag] != NULL)
			{
				pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[tag];
		 		currTar_Info->TarTagQ_Cnt--;
				ACCEPT_MSG(port);
			}
			else
			{
			ACCEPT_MSG_ATN(port);
			}
		}else
		{
			pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
			if(pCurrCard->currentSCCB != NULL)
			{
				ACCEPT_MSG(port);
			}
			else 
			{
				ACCEPT_MSG_ATN(port);
			}
		}
	}

	if(pCurrCard->currentSCCB != NULL)
	{
		if(pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST)
		{
		/* During Abort Tag command, the target could have got re-selected
			and completed the command. Check the select Q and remove the CCB
			if it is in the Select Q */
			queueFindSccb(pCurrCard->currentSCCB, p_card);
		}
	}


   while (!(RDW_HARPOON((port+hp_intstat)) & (PHASE | RESET)) &&
	  !(RD_HARPOON(port+hp_scsisig) & SCSI_REQ) &&
	  (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ;
}

#if defined(V302)

#if defined(DOS)
UCHAR GetTarLun(USHORT port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun)
#else
UCHAR GetTarLun(ULONG port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun)
#endif
{
   UCHAR message;
   PSCCBMgr_tar_info currTar_Info;


	currTar_Info = &sccbMgrTbl[p_card][our_target];
	*tag = 0;


	while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ))
	{
		if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY))
		{

			WRW_HARPOON((port+hp_intstat), PHASE);
			return(TRUE);
		}
	}

	WRW_HARPOON((port+hp_intstat), PHASE);
	if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH)
	{

		message = sfm(port,pCurrCard->currentSCCB);
		if (message)
		{

			if (message <= (0x80 | LUN_MASK))
			{
				*lun = message & (UCHAR)LUN_MASK;

#if !defined(DOS)
				if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING)
				{
					if (currTar_Info->TarTagQ_Cnt != 0)
					{

						if (!(currTar_Info->TarLUN_CA))
						{
							ACCEPT_MSG(port);    /*Release the ACK for ID msg. */


							message = sfm(port,pCurrCard->currentSCCB);
							if (message)
							{
								ACCEPT_MSG(port);
							}

							else
   							return(FALSE);

							*tag = sfm(port,pCurrCard->currentSCCB);

							if (!(*tag)) return(FALSE);

						} /*C.A. exists! */

					} /*End Q cnt != 0 */

				} /*End Tag cmds supported! */
#endif /* !DOS */

			} /*End valid ID message.  */

			else
			{

				ACCEPT_MSG_ATN(port);
			}

		} /* End good id message. */

		else
		{

			return(FALSE);
		}
	}
	else
	{
		ACCEPT_MSG_ATN(port);
		return(TRUE);
	}
	return(TRUE);
}

#endif /* V302 */

#if defined(DOS)
void SendMsg(USHORT port, UCHAR message)
#else
void SendMsg(ULONG port, UCHAR message)
#endif
{
	while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ))
	{
		if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY))
		{

			WRW_HARPOON((port+hp_intstat), PHASE);
			return;
		}
	}

	WRW_HARPOON((port+hp_intstat), PHASE);
	if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH)
	{
		WRW_HARPOON((port+hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));


		WR_HARPOON(port+hp_portctrl_0, SCSI_BUS_EN);

		WR_HARPOON(port+hp_scsidata_0,message);

		WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH));

		ACCEPT_MSG(port);

		WR_HARPOON(port+hp_portctrl_0, 0x00);

		if ((message == SMABORT) || (message == SMDEV_RESET) ||
				(message == SMABORT_TAG) )
		{
			while(!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | PHASE))) {}

			if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE)
			{
			WRW_HARPOON((port+hp_intstat), BUS_FREE);
			}
		}
	}
}

/*---------------------------------------------------------------------
 *
 * Function: sdecm
 *
 * Description: Determine the proper responce to the message from the
 *              target device.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void sdecm(UCHAR message, USHORT port, UCHAR p_card)
#else
void sdecm(UCHAR message, ULONG port, UCHAR p_card)
#endif
{
	PSCCB currSCCB;
	PSCCBcard CurrCard;
	PSCCBMgr_tar_info currTar_Info;

	CurrCard = &BL_Card[p_card];
	currSCCB = CurrCard->currentSCCB;

	currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];

	if (message == SMREST_DATA_PTR)
	{
		if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET))
		{
			currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;

			hostDataXferRestart(currSCCB);
		}

		ACCEPT_MSG(port);
		WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
	}

	else if (message == SMCMD_COMP)
	{


		if (currSCCB->Sccb_scsistat == SELECT_Q_ST)
		{
			currTar_Info->TarStatus &= ~(UCHAR)TAR_TAG_Q_MASK;
			currTar_Info->TarStatus |= (UCHAR)TAG_Q_REJECT;
		}

		ACCEPT_MSG(port);

	}

	else if ((message == SMNO_OP) || (message >= SMIDENT) 
			|| (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY))
	{

		ACCEPT_MSG(port);
		WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
	}

	else if (message == SMREJECT)
	{

		if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
				(currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
				((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING ) ||
				((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING ) )

		{
			WRW_HARPOON((port+hp_intstat), BUS_FREE);

			ACCEPT_MSG(port);


			while ((!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) &&
				(!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE))) {}

			if(currSCCB->Lun == 0x00)
			{
				if ((currSCCB->Sccb_scsistat == SELECT_SN_ST))
				{

					currTar_Info->TarStatus |= (UCHAR)SYNC_SUPPORTED;

					currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
				}

#if defined(WIDE_SCSI)
				else if ((currSCCB->Sccb_scsistat == SELECT_WN_ST))
				{


					currTar_Info->TarStatus = (currTar_Info->TarStatus &
													~WIDE_ENABLED) | WIDE_NEGOCIATED;

					currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;

				}
#endif

				else if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING )
				{
					currTar_Info->TarStatus = (currTar_Info->TarStatus &
													~(UCHAR)TAR_TAG_Q_MASK) | TAG_Q_REJECT;


					currSCCB->ControlByte &= ~F_USE_CMD_Q;
					CurrCard->discQCount--;
					CurrCard->discQ_Tbl[currSCCB->Sccb_tag] = NULL;
					currSCCB->Sccb_tag = 0x00;

				}
			}

			if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE)
			{


				if(currSCCB->Lun == 0x00)
				{
					WRW_HARPOON((port+hp_intstat), BUS_FREE);
					CurrCard->globalFlags |= F_NEW_SCCB_CMD;
				}
			}

			else 
			{

				if((CurrCard->globalFlags & F_CONLUN_IO) &&
					((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
					currTar_Info->TarLUNBusy[currSCCB->Lun] = TRUE;
				else
					currTar_Info->TarLUNBusy[0] = TRUE;


				currSCCB->ControlByte &= ~(UCHAR)F_USE_CMD_Q;

				WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));

			}
		}

		else
		{
			ACCEPT_MSG(port);

			while ((!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ)) &&
				(!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE))) {}
	
			if (!(RDW_HARPOON((port+hp_intstat)) & BUS_FREE))
			{
				WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
			}
		}
	}

	else if (message == SMEXT)
	{

		ACCEPT_MSG(port);
		shandem(port,p_card,currSCCB);
	}

	else if (message == SMIGNORWR)
	{

		ACCEPT_MSG(port);          /* ACK the RESIDUE MSG */

		message = sfm(port,currSCCB);

		if(currSCCB->Sccb_scsimsg != SMPARITY)
			ACCEPT_MSG(port);
		WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
	}


	else
	{

		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
		currSCCB->Sccb_scsimsg = SMREJECT;

		ACCEPT_MSG_ATN(port);
		WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
	}
}


/*---------------------------------------------------------------------
 *
 * Function: shandem
 *
 * Description: Decide what to do with the extended message.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void shandem(USHORT port, UCHAR p_card, PSCCB pCurrSCCB)
#else
void shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
#endif
{
	UCHAR length,message;

	length = sfm(port,pCurrSCCB);
	if (length) 
	{

		ACCEPT_MSG(port);
		message = sfm(port,pCurrSCCB);
		if (message) 
		{

			if (message == SMSYNC) 
			{

				if (length == 0x03)
				{

					ACCEPT_MSG(port);
					stsyncn(port,p_card);
				}
				else 
				{

					pCurrSCCB->Sccb_scsimsg = SMREJECT;
					ACCEPT_MSG_ATN(port);
				}
			}
#if defined(WIDE_SCSI)
			else if (message == SMWDTR) 
			{

				if (length == 0x02)
				{

					ACCEPT_MSG(port);
					stwidn(port,p_card);
				}
				else 
				{

					pCurrSCCB->Sccb_scsimsg = SMREJECT;
					ACCEPT_MSG_ATN(port);

					WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
				}
			}
#endif
			else 
			{

				pCurrSCCB->Sccb_scsimsg = SMREJECT;
				ACCEPT_MSG_ATN(port);

				WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
			}
		}
		else
		{
			if(pCurrSCCB->Sccb_scsimsg != SMPARITY)
				ACCEPT_MSG(port);
			WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
		}
	}else
	{
			if(pCurrSCCB->Sccb_scsimsg == SMPARITY)
				WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
	}
}


/*---------------------------------------------------------------------
 *
 * Function: sisyncn
 *
 * Description: Read in a message byte from the SCSI bus, and check
 *              for a parity error.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
UCHAR sisyncn(USHORT port, UCHAR p_card, UCHAR syncFlag)
#else
UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag)
#endif
{
   PSCCB currSCCB;
   PSCCBMgr_tar_info currTar_Info;

   currSCCB = BL_Card[p_card].currentSCCB;
   currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];

   if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {


      WRW_HARPOON((port+ID_MSG_STRT),
                 (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV)));

      WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ);

      WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT ));
      WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x03  ));
      WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMSYNC));


      if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)

	 WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 12));

      else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)

	 WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 25));

      else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)

	 WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 50));

      else
	 WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+ 00));


      WRW_HARPOON((port+SYNC_MSGS+8), (RAT_OP                ));
      WRW_HARPOON((port+SYNC_MSGS+10),(MPM_OP+AMSG_OUT+DEFAULT_OFFSET));
      WRW_HARPOON((port+SYNC_MSGS+12),(BRH_OP+ALWAYS+NP      ));


		if(syncFlag == FALSE)
		{
		   WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
	      currTar_Info->TarStatus = ((currTar_Info->TarStatus &
   	      ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_TRYING);
		}
		else
		{
		   WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
		}


      return(TRUE);
      }

   else {

      currTar_Info->TarStatus |=	 (UCHAR)SYNC_SUPPORTED;
      currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
      return(FALSE);
      }
}



/*---------------------------------------------------------------------
 *
 * Function: stsyncn
 *
 * Description: The has sent us a Sync Nego message so handle it as
 *              necessary.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void stsyncn(USHORT port, UCHAR p_card)
#else
void stsyncn(ULONG port, UCHAR p_card)
#endif
{
   UCHAR sync_msg,offset,sync_reg,our_sync_msg;
   PSCCB currSCCB;
   PSCCBMgr_tar_info currTar_Info;

   currSCCB = BL_Card[p_card].currentSCCB;
   currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];

   sync_msg = sfm(port,currSCCB);

	if((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY))
	{
		WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
		return;
	}

   ACCEPT_MSG(port);


   offset = sfm(port,currSCCB);

	if((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY))
	{
		WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
		return;
	}

   if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)

      our_sync_msg = 12;              /* Setup our Message to 20mb/s */

   else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)

      our_sync_msg = 25;              /* Setup our Message to 10mb/s */

   else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)

      our_sync_msg = 50;              /* Setup our Message to 5mb/s */
   else

      our_sync_msg = 0;               /* Message = Async */

   if (sync_msg < our_sync_msg) {
      sync_msg = our_sync_msg;    /*if faster, then set to max. */
      }

   if (offset == ASYNC)
      sync_msg = ASYNC;

   if (offset > MAX_OFFSET)
      offset = MAX_OFFSET;

   sync_reg = 0x00;

   if (sync_msg > 12)

      sync_reg = 0x20;        /* Use 10MB/s */

   if (sync_msg > 25)

      sync_reg = 0x40;        /* Use 6.6MB/s */

   if (sync_msg > 38)

      sync_reg = 0x60;        /* Use 5MB/s */

   if (sync_msg > 50)

      sync_reg = 0x80;        /* Use 4MB/s */

   if (sync_msg > 62)

      sync_reg = 0xA0;        /* Use 3.33MB/s */

   if (sync_msg > 75)

      sync_reg = 0xC0;        /* Use 2.85MB/s */

   if (sync_msg > 87)

      sync_reg = 0xE0;        /* Use 2.5MB/s */

   if (sync_msg > 100) {

      sync_reg = 0x00;        /* Use ASYNC */
      offset = 0x00;
      }


#if defined(WIDE_SCSI)
   if (currTar_Info->TarStatus & WIDE_ENABLED)

      sync_reg |= offset;

   else

      sync_reg |= (offset | NARROW_SCSI);

#else
   sync_reg |= (offset | NARROW_SCSI);
#endif

   sssyncv(port,currSCCB->TargID,sync_reg,currTar_Info);


   if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {


      ACCEPT_MSG(port);

      currTar_Info->TarStatus = ((currTar_Info->TarStatus &
         ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_SUPPORTED);

      WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
      }

   else {


      ACCEPT_MSG_ATN(port);

      sisyncr(port,sync_msg,offset);

      currTar_Info->TarStatus = ((currTar_Info->TarStatus &
         ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_SUPPORTED);
      }
}


/*---------------------------------------------------------------------
 *
 * Function: sisyncr
 *
 * Description: Answer the targets sync message.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void sisyncr(USHORT port,UCHAR sync_pulse, UCHAR offset)
#else
void sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset)
#endif
{
   ARAM_ACCESS(port);
   WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT ));
   WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x03  ));
   WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMSYNC));
   WRW_HARPOON((port+SYNC_MSGS+6), (MPM_OP+AMSG_OUT+sync_pulse));
   WRW_HARPOON((port+SYNC_MSGS+8), (RAT_OP                ));
   WRW_HARPOON((port+SYNC_MSGS+10),(MPM_OP+AMSG_OUT+offset));
   WRW_HARPOON((port+SYNC_MSGS+12),(BRH_OP+ALWAYS+NP      ));
   SGRAM_ACCESS(port);

   WR_HARPOON(port+hp_portctrl_0, SCSI_PORT);
   WRW_HARPOON((port+hp_intstat), CLR_ALL_INT_1);

   WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED+CMD_ONLY_STRT));

   while (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | AUTO_INT))) {}
}



#if defined(WIDE_SCSI)

/*---------------------------------------------------------------------
 *
 * Function: siwidn
 *
 * Description: Read in a message byte from the SCSI bus, and check
 *              for a parity error.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
UCHAR siwidn(USHORT port, UCHAR p_card)
#else
UCHAR siwidn(ULONG port, UCHAR p_card)
#endif
{
   PSCCB currSCCB;
   PSCCBMgr_tar_info currTar_Info;

   currSCCB = BL_Card[p_card].currentSCCB;
   currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];

   if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {


      WRW_HARPOON((port+ID_MSG_STRT),
	              (MPM_OP+AMSG_OUT+(currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV)));

      WRW_HARPOON((port+ID_MSG_STRT+2),BRH_OP+ALWAYS+CMDPZ);

      WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT ));
      WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x02  ));
      WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMWDTR));
      WRW_HARPOON((port+SYNC_MSGS+6), (RAT_OP                ));
      WRW_HARPOON((port+SYNC_MSGS+8), (MPM_OP+AMSG_OUT+ SM16BIT));
      WRW_HARPOON((port+SYNC_MSGS+10),(BRH_OP+ALWAYS+NP      ));

      WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));


      currTar_Info->TarStatus = ((currTar_Info->TarStatus &
         ~(UCHAR)TAR_WIDE_MASK) | (UCHAR)WIDE_ENABLED);

      return(TRUE);
      }

   else {

      currTar_Info->TarStatus = ((currTar_Info->TarStatus &
               ~(UCHAR)TAR_WIDE_MASK) | WIDE_NEGOCIATED);

      currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
      return(FALSE);
      }
}



/*---------------------------------------------------------------------
 *
 * Function: stwidn
 *
 * Description: The has sent us a Wide Nego message so handle it as
 *              necessary.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void stwidn(USHORT port, UCHAR p_card)
#else
void stwidn(ULONG port, UCHAR p_card)
#endif
{
   UCHAR width;
   PSCCB currSCCB;
   PSCCBMgr_tar_info currTar_Info;

   currSCCB = BL_Card[p_card].currentSCCB;
   currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];

   width = sfm(port,currSCCB);

	if((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY))
	{
		WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
		return;
	}


   if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
      width = 0;

   if (width) {
      currTar_Info->TarStatus |= WIDE_ENABLED;
      width = 0;
      }
   else {
      width = NARROW_SCSI;
      currTar_Info->TarStatus &= ~WIDE_ENABLED;
      }


   sssyncv(port,currSCCB->TargID,width,currTar_Info);


   if (currSCCB->Sccb_scsistat == SELECT_WN_ST)
	{



      currTar_Info->TarStatus |=	 WIDE_NEGOCIATED;

	   if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_SUPPORTED))
		{
	      ACCEPT_MSG_ATN(port);
		   ARAM_ACCESS(port);
	     	sisyncn(port,p_card, TRUE);
	      currSCCB->Sccb_scsistat = SELECT_SN_ST;
		   SGRAM_ACCESS(port);
		}
		else
		{
	      ACCEPT_MSG(port);
  		   WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
		}
   }

   else {


      ACCEPT_MSG_ATN(port);

      if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
      	 width = SM16BIT;
      else
      	 width = SM8BIT;

      siwidr(port,width);

      currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
      }
}


/*---------------------------------------------------------------------
 *
 * Function: siwidr
 *
 * Description: Answer the targets Wide nego message.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void siwidr(USHORT port, UCHAR width)
#else
void siwidr(ULONG port, UCHAR width)
#endif
{
   ARAM_ACCESS(port);
   WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT ));
   WRW_HARPOON((port+SYNC_MSGS+2), (MPM_OP+AMSG_OUT+0x02  ));
   WRW_HARPOON((port+SYNC_MSGS+4), (MPM_OP+AMSG_OUT+SMWDTR));
   WRW_HARPOON((port+SYNC_MSGS+6), (RAT_OP                ));
   WRW_HARPOON((port+SYNC_MSGS+8),(MPM_OP+AMSG_OUT+width));
   WRW_HARPOON((port+SYNC_MSGS+10),(BRH_OP+ALWAYS+NP      ));
   SGRAM_ACCESS(port);

   WR_HARPOON(port+hp_portctrl_0, SCSI_PORT);
   WRW_HARPOON((port+hp_intstat), CLR_ALL_INT_1);

   WR_HARPOON(port+hp_autostart_3, (AUTO_IMMED+CMD_ONLY_STRT));

   while (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | AUTO_INT))) {}
}

#endif



/*---------------------------------------------------------------------
 *
 * Function: sssyncv
 *
 * Description: Write the desired value to the Sync Register for the
 *              ID specified.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void sssyncv(USHORT p_port, UCHAR p_id, UCHAR p_sync_value,PSCCBMgr_tar_info currTar_Info)
#else
void sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value,PSCCBMgr_tar_info currTar_Info)
#endif
{
   UCHAR index;

   index = p_id;

   switch (index) {

      case 0:
	 index = 12;             /* hp_synctarg_0 */
	 break;
      case 1:
	 index = 13;             /* hp_synctarg_1 */
	 break;
      case 2:
	 index = 14;             /* hp_synctarg_2 */
	 break;
      case 3:
	 index = 15;             /* hp_synctarg_3 */
	 break;
      case 4:
	 index = 8;              /* hp_synctarg_4 */
	 break;
      case 5:
	 index = 9;              /* hp_synctarg_5 */
	 break;
      case 6:
	 index = 10;             /* hp_synctarg_6 */
	 break;
      case 7:
	 index = 11;             /* hp_synctarg_7 */
	 break;
      case 8:
	 index = 4;              /* hp_synctarg_8 */
	 break;
      case 9:
	 index = 5;              /* hp_synctarg_9 */
	 break;
      case 10:
	 index = 6;              /* hp_synctarg_10 */
	 break;
      case 11:
	 index = 7;              /* hp_synctarg_11 */
	 break;
      case 12:
	 index = 0;              /* hp_synctarg_12 */
	 break;
      case 13:
	 index = 1;              /* hp_synctarg_13 */
	 break;
      case 14:
	 index = 2;              /* hp_synctarg_14 */
	 break;
      case 15:
	 index = 3;              /* hp_synctarg_15 */

      }

   WR_HARPOON(p_port+hp_synctarg_base+index, p_sync_value);

	currTar_Info->TarSyncCtrl = p_sync_value;
}


/*---------------------------------------------------------------------
 *
 * Function: sresb
 *
 * Description: Reset the desired card's SCSI bus.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void sresb(USHORT port, UCHAR p_card)
#else
void sresb(ULONG port, UCHAR p_card)
#endif
{
   UCHAR scsiID, i;

   PSCCBMgr_tar_info currTar_Info;

   WR_HARPOON(port+hp_page_ctrl,
      (RD_HARPOON(port+hp_page_ctrl) | G_INT_DISABLE));
   WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);

   WR_HARPOON(port+hp_scsictrl_0, SCSI_RST);

   scsiID = RD_HARPOON(port+hp_seltimeout);
   WR_HARPOON(port+hp_seltimeout,TO_5ms);
   WRW_HARPOON((port+hp_intstat), TIMEOUT);

   WR_HARPOON(port+hp_portctrl_0,(SCSI_PORT | START_TO));

   while (!(RDW_HARPOON((port+hp_intstat)) & TIMEOUT)) {}

   WR_HARPOON(port+hp_seltimeout,scsiID);

   WR_HARPOON(port+hp_scsictrl_0, ENA_SCAM_SEL);

   Wait(port, TO_5ms);

   WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);

   WR_HARPOON(port+hp_int_mask, (RD_HARPOON(port+hp_int_mask) | 0x00));

   for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++)
      {
      currTar_Info = &sccbMgrTbl[p_card][scsiID];

      if (currTar_Info->TarEEValue & EE_SYNC_MASK)
         {
	      	currTar_Info->TarSyncCtrl = 0;
	      	currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
	      }

      if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
         {
      	currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
      	}

      sssyncv(port, scsiID, NARROW_SCSI,currTar_Info);

      SccbMgrTableInitTarget(p_card, scsiID);
      }

   BL_Card[p_card].scanIndex = 0x00;
   BL_Card[p_card].currentSCCB = NULL;
   BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT 
													| F_NEW_SCCB_CMD);
   BL_Card[p_card].cmdCounter  = 0x00;
	BL_Card[p_card].discQCount = 0x00;
   BL_Card[p_card].tagQ_Lst = 0x01; 

	for(i = 0; i < QUEUE_DEPTH; i++)
		BL_Card[p_card].discQ_Tbl[i] = NULL;

   WR_HARPOON(port+hp_page_ctrl,
      (RD_HARPOON(port+hp_page_ctrl) & ~G_INT_DISABLE));

}

/*---------------------------------------------------------------------
 *
 * Function: ssenss
 *
 * Description: Setup for the Auto Sense command.
 *
 *---------------------------------------------------------------------*/
void ssenss(PSCCBcard pCurrCard)
{
   UCHAR i;
   PSCCB currSCCB;

   currSCCB = pCurrCard->currentSCCB;


   currSCCB->Save_CdbLen = currSCCB->CdbLength;

   for (i = 0; i < 6; i++) {

      currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
      }

   currSCCB->CdbLength = SIX_BYTE_CMD;
   currSCCB->Cdb[0]    = SCSI_REQUEST_SENSE;
   currSCCB->Cdb[1]    = currSCCB->Cdb[1] & (UCHAR)0xE0; /*Keep LUN. */
   currSCCB->Cdb[2]    = 0x00;
   currSCCB->Cdb[3]    = 0x00;
   currSCCB->Cdb[4]    = currSCCB->RequestSenseLength;
   currSCCB->Cdb[5]    = 0x00;

   currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength;

   currSCCB->Sccb_ATC = 0x00;

   currSCCB->Sccb_XferState |= F_AUTO_SENSE;

   currSCCB->Sccb_XferState &= ~F_SG_XFER;

   currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(UCHAR)DISC_PRIV;

   currSCCB->ControlByte = 0x00;

   currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
}



/*---------------------------------------------------------------------
 *
 * Function: sxfrp
 *
 * Description: Transfer data into the bit bucket until the device
 *              decides to switch phase.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void sxfrp(USHORT p_port, UCHAR p_card)
#else
void sxfrp(ULONG p_port, UCHAR p_card)
#endif
{
   UCHAR curr_phz;


   DISABLE_AUTO(p_port);

   if (BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {

      hostDataXferAbort(p_port,p_card,BL_Card[p_card].currentSCCB);

      }

   /* If the Automation handled the end of the transfer then do not
      match the phase or we will get out of sync with the ISR.       */

   if (RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | XFER_CNT_0 | AUTO_INT))
      return;

   WR_HARPOON(p_port+hp_xfercnt_0, 0x00);

   curr_phz = RD_HARPOON(p_port+hp_scsisig) & (UCHAR)S_SCSI_PHZ;

   WRW_HARPOON((p_port+hp_intstat), XFER_CNT_0);


   WR_HARPOON(p_port+hp_scsisig, curr_phz);

   while ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET)) &&
      (curr_phz == (RD_HARPOON(p_port+hp_scsisig) & (UCHAR)S_SCSI_PHZ)) )
      {
      if (curr_phz & (UCHAR)SCSI_IOBIT)
         {
      	WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | SCSI_INBIT));

	      if (!(RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY))
            {
	         RD_HARPOON(p_port+hp_fifodata_0);
	         }
	      }
      else
         {
      	WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | HOST_WRT));
   	   if (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY)
            {
	         WR_HARPOON(p_port+hp_fifodata_0,0xFA);
	         }
	      }
      } /* End of While loop for padding data I/O phase */

      while ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET)))
         {
         if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ)
      	   break;
         }

      WR_HARPOON(p_port+hp_portctrl_0, (SCSI_PORT | HOST_PORT | SCSI_INBIT));
      while (!(RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY))
         {
         RD_HARPOON(p_port+hp_fifodata_0);
         }

      if ( !(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET)))
         {
         WR_HARPOON(p_port+hp_autostart_0, (AUTO_IMMED+DISCONNECT_START));
         while (!(RDW_HARPOON((p_port+hp_intstat)) & AUTO_INT)) {}

         if (RDW_HARPOON((p_port+hp_intstat)) & (ICMD_COMP | ITAR_DISC))
   	   while (!(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RSEL))) ;
         }
}


/*---------------------------------------------------------------------
 *
 * Function: schkdd
 *
 * Description: Make sure data has been flushed from both FIFOs and abort
 *              the operations if necessary.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void schkdd(USHORT port, UCHAR p_card)
#else
void schkdd(ULONG port, UCHAR p_card)
#endif
{
   USHORT TimeOutLoop;
	UCHAR sPhase;

   PSCCB currSCCB;

   currSCCB = BL_Card[p_card].currentSCCB;


   if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
       (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
      return;
      }



   if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT)
      {

      currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt-1);

      currSCCB->Sccb_XferCnt = 1;

      currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
      WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00);
      WR_HARPOON(port+hp_xferstat, 0x00);
      }

   else
      {

      currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;

      currSCCB->Sccb_XferCnt = 0;
      }

   if ((RDW_HARPOON((port+hp_intstat)) & PARITY) &&
      (currSCCB->HostStatus == SCCB_COMPLETE)) {

      currSCCB->HostStatus = SCCB_PARITY_ERR;
      WRW_HARPOON((port+hp_intstat), PARITY);
      }


   hostDataXferAbort(port,p_card,currSCCB);


   while (RD_HARPOON(port+hp_scsisig) & SCSI_ACK) {}

   TimeOutLoop = 0;

   while(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)
      {
      if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) {
	      return;
   	   }
      if (RD_HARPOON(port+hp_offsetctr) & (UCHAR)0x1F) {
	      break;
   	   }
      if (RDW_HARPOON((port+hp_intstat)) & RESET) {
	      return;
   	   }
      if ((RD_HARPOON(port+hp_scsisig) & SCSI_REQ) || (TimeOutLoop++>0x3000) )
   	   break;
      }

	sPhase = RD_HARPOON(port+hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
   if ((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY))                     ||
      (RD_HARPOON(port+hp_offsetctr) & (UCHAR)0x1F)                       ||
      (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
      (sPhase == (SCSI_BSY | S_DATAI_PH)))
      {

	   WR_HARPOON(port+hp_portctrl_0, SCSI_PORT);

	   if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED))
         {
	      if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
	         phaseDataIn(port,p_card);
	      	}

	   	else {
	       phaseDataOut(port,p_card);
	       	}
	   	}
		else
      	{
	   	sxfrp(port,p_card);
	   	if (!(RDW_HARPOON((port+hp_intstat)) &
		      (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET)))
         {
   		WRW_HARPOON((port+hp_intstat), AUTO_INT);
		   phaseDecode(port,p_card);
		   }
	   }

   }

   else {
      WR_HARPOON(port+hp_portctrl_0, 0x00);
      }
}


/*---------------------------------------------------------------------
 *
 * Function: sinits
 *
 * Description: Setup SCCB manager fields in this SCCB.
 *
 *---------------------------------------------------------------------*/

void sinits(PSCCB p_sccb, UCHAR p_card)
{
   PSCCBMgr_tar_info currTar_Info;

	if((p_sccb->TargID > MAX_SCSI_TAR) || (p_sccb->Lun > MAX_LUN))
	{
		return;
	}
   currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];

   p_sccb->Sccb_XferState     = 0x00;
   p_sccb->Sccb_XferCnt       = p_sccb->DataLength;

   if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
      (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {

      p_sccb->Sccb_SGoffset   = 0;
      p_sccb->Sccb_XferState  = F_SG_XFER;
      p_sccb->Sccb_XferCnt    = 0x00;
      }

   if (p_sccb->DataLength == 0x00)

      p_sccb->Sccb_XferState |= F_ALL_XFERRED;

   if (p_sccb->ControlByte & F_USE_CMD_Q)
      {
      if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
         p_sccb->ControlByte &= ~F_USE_CMD_Q;

      else
	      currTar_Info->TarStatus |= TAG_Q_TRYING;
      }

/*      For !single SCSI device in system  & device allow Disconnect
	or command is tag_q type then send Cmd with Disconnect Enable
	else send Cmd with Disconnect Disable */

/*
   if (((!(BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
      (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
      (currTar_Info->TarStatus & TAG_Q_TRYING)) {
*/
   if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
      (currTar_Info->TarStatus & TAG_Q_TRYING)) {
      p_sccb->Sccb_idmsg      = (UCHAR)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
      }

   else {

      p_sccb->Sccb_idmsg      = (UCHAR)SMIDENT | p_sccb->Lun;
      }

   p_sccb->HostStatus         = 0x00;
   p_sccb->TargetStatus       = 0x00;
   p_sccb->Sccb_tag           = 0x00;
   p_sccb->Sccb_MGRFlags      = 0x00;
   p_sccb->Sccb_sgseg         = 0x00;
   p_sccb->Sccb_ATC           = 0x00;
   p_sccb->Sccb_savedATC      = 0x00;
/*
   p_sccb->SccbVirtDataPtr    = 0x00;
   p_sccb->Sccb_forwardlink   = NULL;
   p_sccb->Sccb_backlink      = NULL;
 */
   p_sccb->Sccb_scsistat      = BUS_FREE_ST;
   p_sccb->SccbStatus         = SCCB_IN_PROCESS;
   p_sccb->Sccb_scsimsg       = SMNO_OP;

}


#ident "$Id: phase.c 1.11 1997/01/31 02:08:49 mohan Exp $"
/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   phase.c  $
 *
 *   Description:  Functions to intially handle the SCSI bus phase when
 *                 the target asserts request (and the automation is not
 *                 enabled to handle the situation).
 *
 *   $Date: 1997/01/31 02:08:49 $
 *
 *   $Revision: 1.11 $
 *
 *----------------------------------------------------------------------*/

/*#include <globals.h>*/

#if (FW_TYPE==_UCB_MGR_)
	/*#include <budi.h>*/
#endif

/*#include <sccbmgr.h>*/
/*#include <blx30.h>*/
/*#include <target.h>*/
/*#include <scsi2.h>*/
/*#include <harpoon.h>*/


/*
extern SCCBCARD BL_Card[MAX_CARDS];
extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];

#if defined(OS2)
   extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR);
#else
   #if defined(DOS)
      extern void (*s_PhaseTbl[8]) (USHORT, UCHAR);
   #else
      extern void (*s_PhaseTbl[8]) (ULONG, UCHAR);
   #endif
#endif
*/

/*---------------------------------------------------------------------
 *
 * Function: Phase Decode
 *
 * Description: Determine the phase and call the appropriate function.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void phaseDecode(USHORT p_port, UCHAR p_card)
#else
void phaseDecode(ULONG p_port, UCHAR p_card)
#endif
{
   unsigned char phase_ref;
#if defined(OS2)
   void (far *phase) (ULONG, UCHAR);
#else
   #if defined(DOS)
      void (*phase) (USHORT, UCHAR);
   #else
      void (*phase) (ULONG, UCHAR);
   #endif
#endif


   DISABLE_AUTO(p_port);

   phase_ref = (UCHAR) (RD_HARPOON(p_port+hp_scsisig) & S_SCSI_PHZ);

   phase = s_PhaseTbl[phase_ref];

   (*phase)(p_port, p_card);           /* Call the correct phase func */
}



/*---------------------------------------------------------------------
 *
 * Function: Data Out Phase
 *
 * Description: Start up both the BusMaster and Xbow.
 *
 *---------------------------------------------------------------------*/

#if defined(OS2)
void far phaseDataOut(ULONG port, UCHAR p_card)
#else
#if defined(DOS)
void phaseDataOut(USHORT port, UCHAR p_card)
#else
void phaseDataOut(ULONG port, UCHAR p_card)
#endif
#endif
{

   PSCCB currSCCB;

   currSCCB = BL_Card[p_card].currentSCCB;
   if (currSCCB == NULL)
      {
      return;  /* Exit if No SCCB record */
      }

   currSCCB->Sccb_scsistat = DATA_OUT_ST;
   currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);

   WR_HARPOON(port+hp_portctrl_0, SCSI_PORT);

   WRW_HARPOON((port+hp_intstat), XFER_CNT_0);

   WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START));

   dataXferProcessor(port, &BL_Card[p_card]);

#if defined(NOBUGBUG)
   if (RDW_HARPOON((port+hp_intstat)) & XFER_CNT_0)
      WRW_HARPOON((port+hp_intstat), XFER_CNT_0);

#endif


   if (currSCCB->Sccb_XferCnt == 0) {


      if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
	 (currSCCB->HostStatus == SCCB_COMPLETE))
	 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;

      sxfrp(port,p_card);
      if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET)))
	    phaseDecode(port,p_card);
      }
}


/*---------------------------------------------------------------------
 *
 * Function: Data In Phase
 *
 * Description: Startup the BusMaster and the XBOW.
 *
 *---------------------------------------------------------------------*/

#if defined(OS2)
void far phaseDataIn(ULONG port, UCHAR p_card)
#else
#if defined(DOS)
void phaseDataIn(USHORT port, UCHAR p_card)
#else
void phaseDataIn(ULONG port, UCHAR p_card)
#endif
#endif
{

   PSCCB currSCCB;

   currSCCB = BL_Card[p_card].currentSCCB;

   if (currSCCB == NULL)
      {
      return;  /* Exit if No SCCB record */
      }


   currSCCB->Sccb_scsistat = DATA_IN_ST;
   currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
   currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;

   WR_HARPOON(port+hp_portctrl_0, SCSI_PORT);

   WRW_HARPOON((port+hp_intstat), XFER_CNT_0);

   WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START));

   dataXferProcessor(port, &BL_Card[p_card]);

   if (currSCCB->Sccb_XferCnt == 0) {


      if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
	 (currSCCB->HostStatus == SCCB_COMPLETE))
	 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;

      sxfrp(port,p_card);
      if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET)))
	    phaseDecode(port,p_card);

      }
}

/*---------------------------------------------------------------------
 *
 * Function: Command Phase
 *
 * Description: Load the CDB into the automation and start it up.
 *
 *---------------------------------------------------------------------*/

#if defined(OS2)
void far phaseCommand(ULONG p_port, UCHAR p_card)
#else
#if defined(DOS)
void phaseCommand(USHORT p_port, UCHAR p_card)
#else
void phaseCommand(ULONG p_port, UCHAR p_card)
#endif
#endif
{
   PSCCB currSCCB;
#if defined(DOS)
   USHORT cdb_reg;
#else
   ULONG cdb_reg;
#endif
   UCHAR i;

   currSCCB = BL_Card[p_card].currentSCCB;

   if (currSCCB->OperationCode == RESET_COMMAND) {

      currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
      currSCCB->CdbLength = SIX_BYTE_CMD;
      }

   WR_HARPOON(p_port+hp_scsisig, 0x00);

   ARAM_ACCESS(p_port);


   cdb_reg = p_port + CMD_STRT;

   for (i=0; i < currSCCB->CdbLength; i++) {

      if (currSCCB->OperationCode == RESET_COMMAND)

	 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));

      else
	 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
      cdb_reg +=2;
      }

   if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
      WRW_HARPOON(cdb_reg, (BRH_OP+ALWAYS+    NP));

   WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT));

   currSCCB->Sccb_scsistat = COMMAND_ST;

   WR_HARPOON(p_port+hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
   SGRAM_ACCESS(p_port);
}


/*---------------------------------------------------------------------
 *
 * Function: Status phase
 *
 * Description: Bring in the status and command complete message bytes
 *
 *---------------------------------------------------------------------*/

#if defined(OS2)
void far phaseStatus(ULONG port, UCHAR p_card)
#else
#if defined(DOS)
void phaseStatus(USHORT port, UCHAR p_card)
#else
void phaseStatus(ULONG port, UCHAR p_card)
#endif
#endif
{
   /* Start-up the automation to finish off this command and let the
      isr handle the interrupt for command complete when it comes in.
      We could wait here for the interrupt to be generated?
    */

   WR_HARPOON(port+hp_scsisig, 0x00);

   WR_HARPOON(port+hp_autostart_0, (AUTO_IMMED+END_DATA_START));
}


/*---------------------------------------------------------------------
 *
 * Function: Phase Message Out
 *
 * Description: Send out our message (if we have one) and handle whatever
 *              else is involed.
 *
 *---------------------------------------------------------------------*/

#if defined(OS2)
void far phaseMsgOut(ULONG port, UCHAR p_card)
#else
#if defined(DOS)
void phaseMsgOut(USHORT port, UCHAR p_card)
#else
void phaseMsgOut(ULONG port, UCHAR p_card)
#endif
#endif
{
	UCHAR message,scsiID;
	PSCCB currSCCB;
	PSCCBMgr_tar_info currTar_Info;

	currSCCB = BL_Card[p_card].currentSCCB;

	if (currSCCB != NULL) {

		message = currSCCB->Sccb_scsimsg;
		scsiID = currSCCB->TargID;

		if (message == SMDEV_RESET) 
		{


			currTar_Info = &sccbMgrTbl[p_card][scsiID];
			currTar_Info->TarSyncCtrl = 0;
			sssyncv(port, scsiID, NARROW_SCSI,currTar_Info);

			if (sccbMgrTbl[p_card][scsiID].TarEEValue & EE_SYNC_MASK) 
			{

				sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_SYNC_MASK;

			}

			if (sccbMgrTbl[p_card][scsiID].TarEEValue & EE_WIDE_SCSI) 
			{

				sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_WIDE_MASK;
			}


			queueFlushSccb(p_card,SCCB_COMPLETE);
			SccbMgrTableInitTarget(p_card,scsiID);
		}
		else if (currSCCB->Sccb_scsistat == ABORT_ST)
		{
			currSCCB->HostStatus = SCCB_COMPLETE;
			if(BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] != NULL)
			{
				BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
				sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
			}
					
		}

		else if (currSCCB->Sccb_scsistat < COMMAND_ST) 
		{


			if(message == SMNO_OP)
			{
				currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
		
				ssel(port,p_card);
				return;
			}
		}
		else 
		{


			if (message == SMABORT)

				queueFlushSccb(p_card,SCCB_COMPLETE);
		}

	}
	else 
	{
		message = SMABORT;
	}

	WRW_HARPOON((port+hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));


	WR_HARPOON(port+hp_portctrl_0, SCSI_BUS_EN);

	WR_HARPOON(port+hp_scsidata_0,message);

	WR_HARPOON(port+hp_scsisig, (SCSI_ACK + S_ILL_PH));

	ACCEPT_MSG(port);

	WR_HARPOON(port+hp_portctrl_0, 0x00);

	if ((message == SMABORT) || (message == SMDEV_RESET) || 
				(message == SMABORT_TAG) ) 
	{

		while(!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | PHASE))) {}

		if (RDW_HARPOON((port+hp_intstat)) & BUS_FREE) 
		{
			WRW_HARPOON((port+hp_intstat), BUS_FREE);

			if (currSCCB != NULL) 
			{

				if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
					((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
					sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
				else
					sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;

				queueCmdComplete(&BL_Card[p_card],currSCCB, p_card);
			}

			else 
			{
				BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
			}
		}

		else 
		{

			sxfrp(port,p_card);
		}
	}

	else 
	{

		if(message == SMPARITY)
		{
			currSCCB->Sccb_scsimsg = SMNO_OP;
			WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
		}
		else
		{
			sxfrp(port,p_card);
		}
	}
}


/*---------------------------------------------------------------------
 *
 * Function: Message In phase
 *
 * Description: Bring in the message and determine what to do with it.
 *
 *---------------------------------------------------------------------*/

#if defined(OS2)
void far phaseMsgIn(ULONG port, UCHAR p_card)
#else
#if defined(DOS)
void phaseMsgIn(USHORT port, UCHAR p_card)
#else
void phaseMsgIn(ULONG port, UCHAR p_card)
#endif
#endif
{
	UCHAR message;
	PSCCB currSCCB;

	currSCCB = BL_Card[p_card].currentSCCB;

	if (BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) 
	{

		phaseChkFifo(port, p_card);
	}

	message = RD_HARPOON(port+hp_scsidata_0);
	if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) 
	{

		WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+END_DATA_START));

	}

	else 
	{

		message = sfm(port,currSCCB);
		if (message) 
		{


			sdecm(message,port,p_card);

		}
		else
		{
			if(currSCCB->Sccb_scsimsg != SMPARITY)
				ACCEPT_MSG(port);
			WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
		}
	}

}


/*---------------------------------------------------------------------
 *
 * Function: Illegal phase
 *
 * Description: Target switched to some illegal phase, so all we can do
 *              is report an error back to the host (if that is possible)
 *              and send an ABORT message to the misbehaving target.
 *
 *---------------------------------------------------------------------*/

#if defined(OS2)
void far phaseIllegal(ULONG port, UCHAR p_card)
#else
#if defined(DOS)
void phaseIllegal(USHORT port, UCHAR p_card)
#else
void phaseIllegal(ULONG port, UCHAR p_card)
#endif
#endif
{
   PSCCB currSCCB;

   currSCCB = BL_Card[p_card].currentSCCB;

   WR_HARPOON(port+hp_scsisig, RD_HARPOON(port+hp_scsisig));
   if (currSCCB != NULL) {

      currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
      currSCCB->Sccb_scsistat = ABORT_ST;
      currSCCB->Sccb_scsimsg = SMABORT;
      }

   ACCEPT_MSG_ATN(port);
}



/*---------------------------------------------------------------------
 *
 * Function: Phase Check FIFO
 *
 * Description: Make sure data has been flushed from both FIFOs and abort
 *              the operations if necessary.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void phaseChkFifo(USHORT port, UCHAR p_card)
#else
void phaseChkFifo(ULONG port, UCHAR p_card)
#endif
{
   ULONG xfercnt;
   PSCCB currSCCB;

   currSCCB = BL_Card[p_card].currentSCCB;

   if (currSCCB->Sccb_scsistat == DATA_IN_ST)
      {

      while((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) &&
	      (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY)) {}


      if (!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY))
         {
	      currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;

	      currSCCB->Sccb_XferCnt = 0;

	      if ((RDW_HARPOON((port+hp_intstat)) & PARITY) &&
	            (currSCCB->HostStatus == SCCB_COMPLETE))
            {
	         currSCCB->HostStatus = SCCB_PARITY_ERR;
	         WRW_HARPOON((port+hp_intstat), PARITY);
	         }

	      hostDataXferAbort(port,p_card,currSCCB);

	      dataXferProcessor(port, &BL_Card[p_card]);

	      while((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) &&
	         (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY)) {}

	      }
      }  /*End Data In specific code. */



#if defined(DOS)
   asm { mov dx,port;
      add dx,hp_xfercnt_2;
      in  al,dx;
      dec dx;
      xor ah,ah;
      mov word ptr xfercnt+2,ax;
      in  al,dx;
      dec dx;
      mov ah,al;
      in  al,dx;
      mov word ptr xfercnt,ax;
      }
#else
   GET_XFER_CNT(port,xfercnt);
#endif


   WR_HARPOON(port+hp_xfercnt_0, 0x00);


   WR_HARPOON(port+hp_portctrl_0, 0x00);

   currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);

   currSCCB->Sccb_XferCnt = xfercnt;

   if ((RDW_HARPOON((port+hp_intstat)) & PARITY) &&
      (currSCCB->HostStatus == SCCB_COMPLETE)) {

      currSCCB->HostStatus = SCCB_PARITY_ERR;
      WRW_HARPOON((port+hp_intstat), PARITY);
      }


   hostDataXferAbort(port,p_card,currSCCB);


   WR_HARPOON(port+hp_fifowrite, 0x00);
   WR_HARPOON(port+hp_fiforead, 0x00);
   WR_HARPOON(port+hp_xferstat, 0x00);

   WRW_HARPOON((port+hp_intstat), XFER_CNT_0);
}


/*---------------------------------------------------------------------
 *
 * Function: Phase Bus Free
 *
 * Description: We just went bus free so figure out if it was
 *              because of command complete or from a disconnect.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void phaseBusFree(USHORT port, UCHAR p_card)
#else
void phaseBusFree(ULONG port, UCHAR p_card)
#endif
{
   PSCCB currSCCB;

   currSCCB = BL_Card[p_card].currentSCCB;

   if (currSCCB != NULL)
      {

      DISABLE_AUTO(port);


      if (currSCCB->OperationCode == RESET_COMMAND)
         {

			if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
				((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
	   		 sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
			else
		   	 sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;

	      queueCmdComplete(&BL_Card[p_card], currSCCB, p_card);

	      queueSearchSelect(&BL_Card[p_card],p_card);

	      }

      else if(currSCCB->Sccb_scsistat == SELECT_SN_ST)
	      {
	      sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
			         (UCHAR)SYNC_SUPPORTED;
	      sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK;
	      }

      else if(currSCCB->Sccb_scsistat == SELECT_WN_ST)
	      {
	      sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
		            (sccbMgrTbl[p_card][currSCCB->TargID].
		   TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;

	      sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI;
	      }

#if !defined(DOS)
      else if(currSCCB->Sccb_scsistat == SELECT_Q_ST)
	      {
	      /* Make sure this is not a phony BUS_FREE.  If we were
	      reselected or if BUSY is NOT on then this is a
	      valid BUS FREE.  SRR Wednesday, 5/10/1995.     */

	      if ((!(RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ||
	         (RDW_HARPOON((port+hp_intstat)) & RSEL))
	         {
	         sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_TAG_Q_MASK;
	         sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= TAG_Q_REJECT;
	         }

	      else
            {
	         return;
	         }
         }
#endif

      else
	      {

	      currSCCB->Sccb_scsistat = BUS_FREE_ST;

         if (!currSCCB->HostStatus)
	         {
	         currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
	         }

			if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
				((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
	   		 sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
			else
		   	 sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;

	      queueCmdComplete(&BL_Card[p_card], currSCCB, p_card);
	      return;
	      }


      BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;

      } /*end if !=null */
}




#ident "$Id: automate.c 1.14 1997/01/31 02:11:46 mohan Exp $"
/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   automate.c  $
 *
 *   Description:  Functions relating to programming the automation of
 *                 the HARPOON.
 *
 *   $Date: 1997/01/31 02:11:46 $
 *
 *   $Revision: 1.14 $
 *
 *----------------------------------------------------------------------*/

/*#include <globals.h>*/

#if (FW_TYPE==_UCB_MGR_)
	/*#include <budi.h>*/
#endif

/*#include <sccbmgr.h>*/
/*#include <blx30.h>*/
/*#include <target.h>*/
/*#include <scsi2.h>*/
/*#include <harpoon.h>*/

/*
extern SCCBCARD BL_Card[MAX_CARDS];
extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
extern SCCBCARD BL_Card[MAX_CARDS];
*/

/*---------------------------------------------------------------------
 *
 * Function: Auto Load Default Map
 *
 * Description: Load the Automation RAM with the defualt map values.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void autoLoadDefaultMap(USHORT p_port)
#else
void autoLoadDefaultMap(ULONG p_port)
#endif
{
#if defined(DOS)
   USHORT map_addr;
#else
   ULONG map_addr;
#endif

   ARAM_ACCESS(p_port);
   map_addr = p_port + hp_aramBase;

   WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0xC0));  /*ID MESSAGE */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0x20));  /*SIMPLE TAG QUEUEING MSG */
   map_addr +=2;
   WRW_HARPOON(map_addr, RAT_OP);                   /*RESET ATTENTION */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+AMSG_OUT+ 0x00));  /*TAG ID MSG */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 0 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 1 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 2 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 3 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 4 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 5 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 6 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 7 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 8 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 9 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 10 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MPM_OP+ACOMMAND+ 0x00));  /*CDB BYTE 11 */
   map_addr +=2;
   WRW_HARPOON(map_addr, (CPE_OP+ADATA_OUT+ DINT)); /*JUMP IF DATA OUT */
   map_addr +=2;
   WRW_HARPOON(map_addr, (TCB_OP+FIFO_0+ DI));     /*JUMP IF NO DATA IN FIFO */
   map_addr +=2;                                   /*This means AYNC DATA IN */
   WRW_HARPOON(map_addr, (SSI_OP+   SSI_IDO_STRT)); /*STOP AND INTERRUPT */
   map_addr +=2;
   WRW_HARPOON(map_addr, (CPE_OP+ADATA_IN+DINT));   /*JUMP IF NOT DATA IN PHZ */
   map_addr +=2;
   WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+  ST));    /*IF NOT MSG IN CHECK 4 DATA IN */
   map_addr +=2;
   WRW_HARPOON(map_addr, (CRD_OP+SDATA+    0x02));  /*SAVE DATA PTR MSG? */
   map_addr +=2;
   WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+   DC));    /*GO CHECK FOR DISCONNECT MSG */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MRR_OP+SDATA+    D_AR1)); /*SAVE DATA PTRS MSG */
   map_addr +=2;
   WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+  ST));    /*IF NOT MSG IN CHECK DATA IN */
   map_addr +=2;
   WRW_HARPOON(map_addr, (CRD_OP+SDATA+    0x04));  /*DISCONNECT MSG? */
   map_addr +=2;
   WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+   UNKNWN));/*UKNKNOWN MSG */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MRR_OP+SDATA+    D_BUCKET));/*XFER DISCONNECT MSG */
   map_addr +=2;
   WRW_HARPOON(map_addr, (SSI_OP+          SSI_ITAR_DISC));/*STOP AND INTERRUPT */
   map_addr +=2;
   WRW_HARPOON(map_addr, (CPN_OP+ASTATUS+  UNKNWN));/*JUMP IF NOT STATUS PHZ. */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MRR_OP+SDATA+  D_AR0));   /*GET STATUS BYTE */
   map_addr +=2;
   WRW_HARPOON(map_addr, (CPN_OP+AMSG_IN+  CC));    /*ERROR IF NOT MSG IN PHZ */
   map_addr +=2;
   WRW_HARPOON(map_addr, (CRD_OP+SDATA+    0x00));  /*CHECK FOR CMD COMPLETE MSG. */
   map_addr +=2;
   WRW_HARPOON(map_addr, (BRH_OP+NOT_EQ+   CC));    /*ERROR IF NOT CMD COMPLETE MSG. */
   map_addr +=2;
   WRW_HARPOON(map_addr, (MRR_OP+SDATA+  D_BUCKET));/*GET CMD COMPLETE MSG */
   map_addr +=2;
   WRW_HARPOON(map_addr, (SSI_OP+       SSI_ICMD_COMP));/*END OF COMMAND */
   map_addr +=2;

   WRW_HARPOON(map_addr, (SSI_OP+ SSI_IUNKWN));  /*RECEIVED UNKNOWN MSG BYTE */
   map_addr +=2;
   WRW_HARPOON(map_addr, (SSI_OP+ SSI_INO_CC));  /*NO COMMAND COMPLETE AFTER STATUS */
   map_addr +=2;
   WRW_HARPOON(map_addr, (SSI_OP+ SSI_ITICKLE)); /*BIOS Tickled the Mgr */
   map_addr +=2;
   WRW_HARPOON(map_addr, (SSI_OP+ SSI_IRFAIL));  /*EXPECTED ID/TAG MESSAGES AND */
   map_addr +=2;                             /* DIDN'T GET ONE */
   WRW_HARPOON(map_addr, (CRR_OP+AR3+  S_IDREG)); /* comp SCSI SEL ID & AR3*/
   map_addr +=2;
   WRW_HARPOON(map_addr, (BRH_OP+EQUAL+   0x00));    /*SEL ID OK then Conti. */
   map_addr +=2;
   WRW_HARPOON(map_addr, (SSI_OP+ SSI_INO_CC));  /*NO COMMAND COMPLETE AFTER STATUS */



   SGRAM_ACCESS(p_port);
}

/*---------------------------------------------------------------------
 *
 * Function: Auto Command Complete
 *
 * Description: Post command back to host and find another command
 *              to execute.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void autoCmdCmplt(USHORT p_port, UCHAR p_card)
#else
void autoCmdCmplt(ULONG p_port, UCHAR p_card)
#endif
{
   PSCCB currSCCB;
   UCHAR status_byte;

   currSCCB = BL_Card[p_card].currentSCCB;

   status_byte = RD_HARPOON(p_port+hp_gp_reg_0);

   sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = FALSE;

   if (status_byte != SSGOOD) {

      if (status_byte == SSQ_FULL) {


			if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
				((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
			{
	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
				if(BL_Card[p_card].discQCount != 0)
					BL_Card[p_card].discQCount--;
				BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
			}
			else
			{
	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
				if(currSCCB->Sccb_tag)
				{
					if(BL_Card[p_card].discQCount != 0)
						BL_Card[p_card].discQCount--;
					BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
				}else
				{
					if(BL_Card[p_card].discQCount != 0)
						BL_Card[p_card].discQCount--;
					BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
				}
			}

         currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;

         queueSelectFail(&BL_Card[p_card],p_card);

         return;
         }

      if(currSCCB->Sccb_scsistat == SELECT_SN_ST)
         {
         sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
            (UCHAR)SYNC_SUPPORTED;

	      sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK;
         BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;

			if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
				((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
			{
	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
				if(BL_Card[p_card].discQCount != 0)
					BL_Card[p_card].discQCount--;
				BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
			}
			else
			{
	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
				if(currSCCB->Sccb_tag)
				{
					if(BL_Card[p_card].discQCount != 0)
						BL_Card[p_card].discQCount--;
					BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
				}else
				{
					if(BL_Card[p_card].discQCount != 0)
						BL_Card[p_card].discQCount--;
					BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
				}
			}
         return;

         }

      if(currSCCB->Sccb_scsistat == SELECT_WN_ST)
         {

	      sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
	         (sccbMgrTbl[p_card][currSCCB->TargID].
	         TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;

	      sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI;
         BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;

			if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
				((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
			{
	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
				if(BL_Card[p_card].discQCount != 0)
					BL_Card[p_card].discQCount--;
				BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
			}
			else
			{
	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
				if(currSCCB->Sccb_tag)
				{
					if(BL_Card[p_card].discQCount != 0)
						BL_Card[p_card].discQCount--;
					BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
				}else
				{
					if(BL_Card[p_card].discQCount != 0)
						BL_Card[p_card].discQCount--;
					BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
				}
			}
         return;
      
         }
     
	   if (status_byte == SSCHECK) 
		{
			if(BL_Card[p_card].globalFlags & F_DO_RENEGO)
			{
				if (sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_SYNC_MASK)
				{
					sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_SYNC_MASK;
				}
				if (sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_WIDE_SCSI)
				{
					sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_WIDE_MASK;
				}
			}
		}

      if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {

         currSCCB->SccbStatus = SCCB_ERROR;
         currSCCB->TargetStatus = status_byte;

         if (status_byte == SSCHECK) {

            sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA
               = TRUE;
     

#if (FW_TYPE==_SCCB_MGR_)
            if (currSCCB->RequestSenseLength != NO_AUTO_REQUEST_SENSE) {

               if (currSCCB->RequestSenseLength == 0)
                  currSCCB->RequestSenseLength = 14;

               ssenss(&BL_Card[p_card]);
               BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;

 					if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
						((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
					{
			         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
						if(BL_Card[p_card].discQCount != 0)
							BL_Card[p_card].discQCount--;
						BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
					}
					else
					{
	   		      sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
						if(currSCCB->Sccb_tag)
						{
							if(BL_Card[p_card].discQCount != 0)
								BL_Card[p_card].discQCount--;
							BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
						}else
						{
							if(BL_Card[p_card].discQCount != 0)
								BL_Card[p_card].discQCount--;
							BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
						}
					}
               return;
               }
#else
				   if ((!(currSCCB->Sccb_ucb_ptr->UCB_opcode & OPC_NO_AUTO_SENSE)) &&
			   		(currSCCB->RequestSenseLength))
				   {
				   	ssenss(&BL_Card[p_card]);
				      BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;

						if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
							((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
						{
	      			   sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
							if(BL_Card[p_card].discQCount != 0)
								BL_Card[p_card].discQCount--;
							BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
						}
						else
						{
	      			   sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
							if(currSCCB->Sccb_tag)
							{
								if(BL_Card[p_card].discQCount != 0)
									BL_Card[p_card].discQCount--;
								BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
							}else
							{
								if(BL_Card[p_card].discQCount != 0)
									BL_Card[p_card].discQCount--;
								BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
							}
						}
				      return;
				   }

#endif
            }
         }
      }


	if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
		((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
	   sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
	else
	   sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;


   queueCmdComplete(&BL_Card[p_card], currSCCB, p_card);
}
#ident "$Id: busmstr.c 1.8 1997/01/31 02:10:27 mohan Exp $"
/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   busmstr.c  $
 *
 *   Description:  Functions to start, stop, and abort BusMaster operations.
 *
 *   $Date: 1997/01/31 02:10:27 $
 *
 *   $Revision: 1.8 $
 *
 *----------------------------------------------------------------------*/

/*#include <globals.h>*/

#if (FW_TYPE==_UCB_MGR_)
	/*#include <budi.h>*/
#endif

/*#include <sccbmgr.h>*/
/*#include <blx30.h>*/
/*#include <target.h>*/
/*#include <scsi2.h>*/
/*#include <harpoon.h>*/


/*
extern SCCBCARD BL_Card[MAX_CARDS];
extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
*/

#define SHORT_WAIT   0x0000000F
#define LONG_WAIT    0x0000FFFFL

#if defined(BUGBUG)
void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
#endif

/*---------------------------------------------------------------------
 *
 * Function: Data Transfer Processor
 *
 * Description: This routine performs two tasks.
 *              (1) Start data transfer by calling HOST_DATA_XFER_START
 *              function.  Once data transfer is started, (2) Depends
 *              on the type of data transfer mode Scatter/Gather mode
 *              or NON Scatter/Gather mode.  In NON Scatter/Gather mode,
 *              this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
 *              data transfer done.  In Scatter/Gather mode, this routine
 *              checks bus master command complete and dual rank busy
 *              bit to keep chaining SC transfer command.  Similarly,
 *              in Scatter/Gather mode, it checks Sccb_MGRFlag
 *              (F_HOST_XFER_ACT bit) for data transfer done.
 *              
 *---------------------------------------------------------------------*/

#if defined(DOS)
void dataXferProcessor(USHORT port, PSCCBcard pCurrCard)
#else
void dataXferProcessor(ULONG port, PSCCBcard pCurrCard)
#endif
{
   PSCCB currSCCB;

   currSCCB = pCurrCard->currentSCCB;

      if (currSCCB->Sccb_XferState & F_SG_XFER)
			{
			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)

				{
		   	currSCCB->Sccb_sgseg += (UCHAR)SG_BUF_CNT;
         	currSCCB->Sccb_SGoffset = 0x00; 
 				}
			pCurrCard->globalFlags |= F_HOST_XFER_ACT;
         
         busMstrSGDataXferStart(port, currSCCB);
			}

      else
			{
			if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT))
				{
				pCurrCard->globalFlags |= F_HOST_XFER_ACT;
         
         	busMstrDataXferStart(port, currSCCB);
         	}
			}
}


/*---------------------------------------------------------------------
 *
 * Function: BusMaster Scatter Gather Data Transfer Start
 *
 * Description:
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void busMstrSGDataXferStart(USHORT p_port, PSCCB pcurrSCCB)
#else
void busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
#endif
{
   ULONG count,addr,tmpSGCnt;
   UINT sg_index;
   UCHAR sg_count, i;
#if defined(DOS)
   USHORT reg_offset;
#else
   ULONG reg_offset;
#endif


   if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {

      count =  ((ULONG) HOST_RD_CMD)<<24;
      }

   else {
      count =  ((ULONG) HOST_WRT_CMD)<<24;
      }

   sg_count = 0;
   tmpSGCnt = 0;
   sg_index = pcurrSCCB->Sccb_sgseg;
   reg_offset = hp_aramBase;


	i = (UCHAR) (RD_HARPOON(p_port+hp_page_ctrl) & ~(SGRAM_ARAM|SCATTER_EN));


	WR_HARPOON(p_port+hp_page_ctrl, i);

   while ((sg_count < (UCHAR)SG_BUF_CNT) &&
      ((ULONG)(sg_index * (UINT)SG_ELEMENT_SIZE) < pcurrSCCB->DataLength) ) {

#if defined(COMPILER_16_BIT) && !defined(DOS)
      tmpSGCnt += *(((ULONG far *)pcurrSCCB->DataPointer)+
         (sg_index * 2));

      count |= *(((ULONG far *)pcurrSCCB->DataPointer)+
         (sg_index * 2));

      addr = *(((ULONG far *)pcurrSCCB->DataPointer)+
         ((sg_index * 2) + 1));

#else
      tmpSGCnt += *(((ULONG *)pcurrSCCB->DataPointer)+
         (sg_index * 2));

      count |= *(((ULONG *)pcurrSCCB->DataPointer)+
         (sg_index * 2));

      addr = *(((ULONG *)pcurrSCCB->DataPointer)+
         ((sg_index * 2) + 1));
#endif


      if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {

         addr += ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
         count = (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;

         tmpSGCnt = count & 0x00FFFFFFL;
         }

      WR_HARP32(p_port,reg_offset,addr);
      reg_offset +=4;

      WR_HARP32(p_port,reg_offset,count);
      reg_offset +=4;

      count &= 0xFF000000L;
      sg_index++;
      sg_count++;

      } /*End While */

   pcurrSCCB->Sccb_XferCnt = tmpSGCnt;

   WR_HARPOON(p_port+hp_sg_addr,(sg_count<<4));

   if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {

      WR_HARP32(p_port,hp_xfercnt_0,tmpSGCnt);


      WR_HARPOON(p_port+hp_portctrl_0,(DMA_PORT | SCSI_PORT | SCSI_INBIT));
      WR_HARPOON(p_port+hp_scsisig, S_DATAI_PH);
      }

   else {


      if ((!(RD_HARPOON(p_port+hp_synctarg_0) & NARROW_SCSI)) &&
         (tmpSGCnt & 0x000000001))
         {

         pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
         tmpSGCnt--;
         }


      WR_HARP32(p_port,hp_xfercnt_0,tmpSGCnt);

      WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT | DMA_PORT | DMA_RD));
      WR_HARPOON(p_port+hp_scsisig, S_DATAO_PH);
      }


   WR_HARPOON(p_port+hp_page_ctrl, (UCHAR) (i | SCATTER_EN));

}


/*---------------------------------------------------------------------
 *
 * Function: BusMaster Data Transfer Start
 *
 * Description: 
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void busMstrDataXferStart(USHORT p_port, PSCCB pcurrSCCB)
#else
void busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
#endif
{
   ULONG addr,count;

   if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {

      count = pcurrSCCB->Sccb_XferCnt;

      addr = (ULONG) pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
      }

   else {
      addr = pcurrSCCB->SensePointer;
      count = pcurrSCCB->RequestSenseLength;

      }

#if defined(DOS)
   asm { mov dx,p_port;
         mov ax,word ptr count;
         add dx,hp_xfer_cnt_lo;
         out dx,al;
         inc dx;
         xchg ah,al
         out dx,al;
         inc dx;
         mov ax,word ptr count+2;
         out dx,al;
         inc dx;
         inc dx;
         mov ax,word ptr addr;
         out dx,al;
         inc dx;
         xchg ah,al
         out dx,al;
         inc dx;
         mov ax,word ptr addr+2;
         out dx,al;
         inc dx;
         xchg ah,al
         out dx,al;
         }

   WR_HARP32(p_port,hp_xfercnt_0,count);

#else
   HP_SETUP_ADDR_CNT(p_port,addr,count);
#endif


   if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {

      WR_HARPOON(p_port+hp_portctrl_0,(DMA_PORT | SCSI_PORT | SCSI_INBIT));
      WR_HARPOON(p_port+hp_scsisig, S_DATAI_PH);

      WR_HARPOON(p_port+hp_xfer_cmd,
         (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
      }

   else {

      WR_HARPOON(p_port+hp_portctrl_0,(SCSI_PORT | DMA_PORT | DMA_RD));
      WR_HARPOON(p_port+hp_scsisig, S_DATAO_PH);

      WR_HARPOON(p_port+hp_xfer_cmd,
         (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));

      }
}


/*---------------------------------------------------------------------
 *
 * Function: BusMaster Timeout Handler
 *
 * Description: This function is called after a bus master command busy time
 *               out is detected.  This routines issue halt state machine
 *               with a software time out for command busy.  If command busy
 *               is still asserted at the end of the time out, it issues
 *               hard abort with another software time out.  It hard abort
 *               command busy is also time out, it'll just give up.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
UCHAR busMstrTimeOut(USHORT p_port)
#else
UCHAR busMstrTimeOut(ULONG p_port)
#endif
{
   ULONG timeout;

   timeout = LONG_WAIT;

   WR_HARPOON(p_port+hp_sys_ctrl, HALT_MACH);

   while ((!(RD_HARPOON(p_port+hp_ext_status) & CMD_ABORTED)) && timeout--) {}

   
   
   if (RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) {
      WR_HARPOON(p_port+hp_sys_ctrl, HARD_ABORT);

      timeout = LONG_WAIT;
      while ((RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {}
      }

   RD_HARPOON(p_port+hp_int_status);           /*Clear command complete */

   if (RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) {
      return(TRUE);
      }

   else {
      return(FALSE);
      }
}


/*---------------------------------------------------------------------
 *
 * Function: Host Data Transfer Abort
 *
 * Description: Abort any in progress transfer.
 *
 *---------------------------------------------------------------------*/
#if defined(DOS)
void hostDataXferAbort(USHORT port, UCHAR p_card, PSCCB pCurrSCCB)
#else
void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
#endif
{

   ULONG timeout;
   ULONG remain_cnt;
   UINT sg_ptr;

   BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;

   if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {


      if (!(RD_HARPOON(port+hp_int_status) & INT_CMD_COMPL)) {

         WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) | FLUSH_XFER_CNTR));
         timeout = LONG_WAIT;

         while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {}

         WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) & ~FLUSH_XFER_CNTR));

         if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) {

            if (busMstrTimeOut(port)) {

               if (pCurrSCCB->HostStatus == 0x00)

                  pCurrSCCB->HostStatus = SCCB_BM_ERR;

               }

            if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) 

               if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) 

                  if (pCurrSCCB->HostStatus == 0x00)

                     {
                     pCurrSCCB->HostStatus = SCCB_BM_ERR;
#if defined(BUGBUG)
                     WR_HARPOON(port+hp_dual_addr_lo,
                        RD_HARPOON(port+hp_ext_status));
#endif
                     }
            }
         }
      }

   else if (pCurrSCCB->Sccb_XferCnt) {

      if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {


              WR_HARPOON(port+hp_page_ctrl, (RD_HARPOON(port+hp_page_ctrl) &
            ~SCATTER_EN));

         WR_HARPOON(port+hp_sg_addr,0x00);

         sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;

         if (sg_ptr > (UINT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE)) {

            sg_ptr = (UINT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE);
            }

         remain_cnt = pCurrSCCB->Sccb_XferCnt;

         while (remain_cnt < 0x01000000L) {

            sg_ptr--;

#if defined(COMPILER_16_BIT) && !defined(DOS)
            if (remain_cnt > (ULONG)(*(((ULONG far *)pCurrSCCB->
               DataPointer) + (sg_ptr * 2)))) {

               remain_cnt -= (ULONG)(*(((ULONG far *)pCurrSCCB->
                  DataPointer) + (sg_ptr * 2)));
               }

#else
            if (remain_cnt > (ULONG)(*(((ULONG *)pCurrSCCB->
               DataPointer) + (sg_ptr * 2)))) {

               remain_cnt -= (ULONG)(*(((ULONG *)pCurrSCCB->
                  DataPointer) + (sg_ptr * 2)));
               }
#endif

            else {

               break;
               }
            }



         if (remain_cnt < 0x01000000L) {


            pCurrSCCB->Sccb_SGoffset = remain_cnt;

            pCurrSCCB->Sccb_sgseg = (USHORT)sg_ptr;


            if ((ULONG)(sg_ptr * SG_ELEMENT_SIZE) == pCurrSCCB->DataLength 
                && (remain_cnt == 0))

               pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
            }

         else {


            if (pCurrSCCB->HostStatus == 0x00) {

               pCurrSCCB->HostStatus = SCCB_GROSS_FW_ERR;
               }
            }
         }


      if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {


         if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) {

            busMstrTimeOut(port);
            }

         else {

            if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) {

               if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) {

                  if (pCurrSCCB->HostStatus == 0x00) {

                     pCurrSCCB->HostStatus = SCCB_BM_ERR;
#if defined(BUGBUG)
                     WR_HARPOON(port+hp_dual_addr_lo,
                        RD_HARPOON(port+hp_ext_status));
#endif
                     }
                  }
               }

            }
         }

      else {


         if ((RD_HARPOON(port+hp_fifo_cnt)) >= BM_THRESHOLD) {

            timeout = SHORT_WAIT;

            while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) &&
               ((RD_HARPOON(port+hp_fifo_cnt)) >= BM_THRESHOLD) &&
               timeout--) {}
            }

         if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) {

            WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) |
               FLUSH_XFER_CNTR));

            timeout = LONG_WAIT;

            while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) &&
               timeout--) {}

            WR_HARPOON(port+hp_bm_ctrl, (RD_HARPOON(port+hp_bm_ctrl) &
               ~FLUSH_XFER_CNTR));


            if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) {

               if (pCurrSCCB->HostStatus == 0x00) {

                  pCurrSCCB->HostStatus = SCCB_BM_ERR;
                  }

               busMstrTimeOut(port);
               }
            }

         if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) {

            if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) {

               if (pCurrSCCB->HostStatus == 0x00) {

                  pCurrSCCB->HostStatus = SCCB_BM_ERR;
#if defined(BUGBUG)
                  WR_HARPOON(port+hp_dual_addr_lo,
                     RD_HARPOON(port+hp_ext_status));
#endif
                  }
               }
            }
         }

      }

   else {


      if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) {

         timeout = LONG_WAIT;

         while ((RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) && timeout--) {}

         if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) {

            if (pCurrSCCB->HostStatus == 0x00) {

               pCurrSCCB->HostStatus = SCCB_BM_ERR;
               }

            busMstrTimeOut(port);
            }
         }


      if (RD_HARPOON(port+hp_int_status) & INT_EXT_STATUS) {

         if (RD_HARPOON(port+hp_ext_status) & BAD_EXT_STATUS) {

            if (pCurrSCCB->HostStatus == 0x00) {

               pCurrSCCB->HostStatus = SCCB_BM_ERR;
#if defined(BUGBUG)
               WR_HARPOON(port+hp_dual_addr_lo,
                  RD_HARPOON(port+hp_ext_status));
#endif
               }
            }

         }

      if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {

         WR_HARPOON(port+hp_page_ctrl, (RD_HARPOON(port+hp_page_ctrl) &
                 ~SCATTER_EN));

         WR_HARPOON(port+hp_sg_addr,0x00);

         pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;

         pCurrSCCB->Sccb_SGoffset = 0x00; 


         if ((ULONG)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >=
            pCurrSCCB->DataLength) {

            pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;

            pCurrSCCB->Sccb_sgseg = (USHORT)(pCurrSCCB->DataLength / SG_ELEMENT_SIZE);

            }
         }

      else {

         if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))

            pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
         }
      }

   WR_HARPOON(port+hp_int_mask,(INT_CMD_COMPL | SCSI_INTERRUPT));
}



/*---------------------------------------------------------------------
 *
 * Function: Host Data Transfer Restart
 *
 * Description: Reset the available count due to a restore data
 *              pointers message.
 *
 *---------------------------------------------------------------------*/
void hostDataXferRestart(PSCCB currSCCB)
{
   ULONG data_count;
   UINT  sg_index;
#if defined(COMPILER_16_BIT) && !defined(DOS)
   ULONG far *sg_ptr;
#else
   ULONG *sg_ptr;
#endif

   if (currSCCB->Sccb_XferState & F_SG_XFER) {

      currSCCB->Sccb_XferCnt = 0;

      sg_index = 0xffff;         /*Index by long words into sg list. */
      data_count = 0;            /*Running count of SG xfer counts. */

#if defined(COMPILER_16_BIT) && !defined(DOS)
      sg_ptr = (ULONG far *)currSCCB->DataPointer;
#else
      sg_ptr = (ULONG *)currSCCB->DataPointer;
#endif

      while (data_count < currSCCB->Sccb_ATC) {

         sg_index++;
         data_count += *(sg_ptr+(sg_index * 2));
         }

      if (data_count == currSCCB->Sccb_ATC) {

         currSCCB->Sccb_SGoffset = 0;
         sg_index++;
         }

      else {
         currSCCB->Sccb_SGoffset = data_count - currSCCB->Sccb_ATC;
         }

      currSCCB->Sccb_sgseg = (USHORT)sg_index;
      }

   else {
      currSCCB->Sccb_XferCnt = currSCCB->DataLength - currSCCB->Sccb_ATC;
      }
}
#ident "$Id: scam.c 1.17 1997/03/20 23:49:37 mohan Exp $"
/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   scam.c  $
 *
 *   Description:  Functions relating to handling of the SCAM selection
 *                 and the determination of the SCSI IDs to be assigned
 *                 to all perspective SCSI targets.
 *
 *   $Date: 1997/03/20 23:49:37 $
 *
 *   $Revision: 1.17 $
 *
 *----------------------------------------------------------------------*/

/*#include <globals.h>*/

#if (FW_TYPE==_UCB_MGR_)
	/*#include <budi.h>*/
#endif

/*#include <sccbmgr.h>*/
/*#include <blx30.h>*/
/*#include <target.h>*/
/*#include <scsi2.h>*/
/*#include <eeprom.h>*/
/*#include <harpoon.h>*/



/*
extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
extern SCCBCARD BL_Card[MAX_CARDS];
extern SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR];
extern NVRAMINFO nvRamInfo[MAX_MB_CARDS];
#if defined(DOS) || defined(OS2)
extern UCHAR temp_id_string[ID_STRING_LENGTH];
#endif
extern UCHAR scamHAString[];
*/
/*---------------------------------------------------------------------
 *
 * Function: scini
 *
 * Description: Setup all data structures necessary for SCAM selection.
 *
 *---------------------------------------------------------------------*/

void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up)
{

#if defined(SCAM_LEV_2)
   UCHAR loser,assigned_id;
#endif
#if defined(DOS)

   USHORT p_port;
#else
   ULONG p_port;
#endif

   UCHAR i,k,ScamFlg ;
   PSCCBcard currCard;
	PNVRamInfo pCurrNvRam;

   currCard = &BL_Card[p_card];
   p_port = currCard->ioPort;
	pCurrNvRam = currCard->pNvRamInfo;


	if(pCurrNvRam){
		ScamFlg = pCurrNvRam->niScamConf;
		i = pCurrNvRam->niSysConf;
	}
	else{
	   ScamFlg = (UCHAR) utilEERead(p_port, SCAM_CONFIG/2);
	   i = (UCHAR)(utilEERead(p_port, (SYSTEM_CONFIG/2)));
	}
	if(!(i & 0x02))	/* check if reset bus in AutoSCSI parameter set */
		return;

   inisci(p_card,p_port, p_our_id);

   /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
      too slow to return to SCAM selection */

   /* if (p_power_up)
         Wait1Second(p_port);
      else
         Wait(p_port, TO_250ms); */

   Wait1Second(p_port);

#if defined(SCAM_LEV_2)

   if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
      {
      while (!(scarb(p_port,INIT_SELTD))) {}

      scsel(p_port);

      do {
         scxferc(p_port,SYNC_PTRN);
         scxferc(p_port,DOM_MSTR);
         loser = scsendi(p_port,&scamInfo[p_our_id].id_string[0]);
         } while ( loser == 0xFF );

      scbusf(p_port);

      if ((p_power_up) && (!loser))
         {
         sresb(p_port,p_card);
         Wait(p_port, TO_250ms);

         while (!(scarb(p_port,INIT_SELTD))) {}

         scsel(p_port);

         do {
            scxferc(p_port, SYNC_PTRN);
            scxferc(p_port, DOM_MSTR);
            loser = scsendi(p_port,&scamInfo[p_our_id].
               id_string[0]);
            } while ( loser == 0xFF );

         scbusf(p_port);
         }
      }

   else
      {
      loser = FALSE;
      }


   if (!loser)
      {

#endif  /* SCAM_LEV_2 */

      scamInfo[p_our_id].state = ID_ASSIGNED;


		if (ScamFlg & SCAM_ENABLED)
		{

	      for (i=0; i < MAX_SCSI_TAR; i++)
  		   {
      	   if ((scamInfo[i].state == ID_UNASSIGNED) ||
  	      	   (scamInfo[i].state == ID_UNUSED))
	  	      {
   	     	   if (scsell(p_port,i))
      	  	   {
            	   scamInfo[i].state = LEGACY;
  	            	if ((scamInfo[i].id_string[0] != 0xFF) ||
     	            	(scamInfo[i].id_string[1] != 0xFA))
	     	         {

   	        	      scamInfo[i].id_string[0] = 0xFF;
      	        	   scamInfo[i].id_string[1] = 0xFA;
							if(pCurrNvRam == NULL)
	         	         currCard->globalFlags |= F_UPDATE_EEPROM;
               	}
	  	         }
   	  	   }
      	}

	      sresb(p_port,p_card);
      	Wait1Second(p_port);
         while (!(scarb(p_port,INIT_SELTD))) {}
         scsel(p_port);
         scasid(p_card, p_port);
         }

#if defined(SCAM_LEV_2)

      }

   else if ((loser) && (ScamFlg & SCAM_ENABLED))
      {
      scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
      assigned_id = FALSE;
      scwtsel(p_port);

      do {
         while (scxferc(p_port,0x00) != SYNC_PTRN) {}

         i = scxferc(p_port,0x00);
         if (i == ASSIGN_ID)
            {
            if (!(scsendi(p_port,&scamInfo[p_our_id].id_string[0])))
                  {
                  i = scxferc(p_port,0x00);
                  if (scvalq(i))
                     {
                     k = scxferc(p_port,0x00);

                     if (scvalq(k))
                        {
                        currCard->ourId =
                           ((UCHAR)(i<<3)+(k & (UCHAR)7)) & (UCHAR) 0x3F;
                        inisci(p_card, p_port, p_our_id);
                        scamInfo[currCard->ourId].state = ID_ASSIGNED;
                        scamInfo[currCard->ourId].id_string[0]
                           = SLV_TYPE_CODE0;
                        assigned_id = TRUE;
                        }
                     }
                  }
            }

         else if (i == SET_P_FLAG)
            {
               if (!(scsendi(p_port,
                        &scamInfo[p_our_id].id_string[0])))
                        scamInfo[p_our_id].id_string[0] |= 0x80;
            }
         }while (!assigned_id);

      while (scxferc(p_port,0x00) != CFG_CMPLT) {}
      }

#endif   /* SCAM_LEV_2 */
   if (ScamFlg & SCAM_ENABLED)
      {
      scbusf(p_port);
      if (currCard->globalFlags & F_UPDATE_EEPROM)
         {
         scsavdi(p_card, p_port);
         currCard->globalFlags &= ~F_UPDATE_EEPROM;
         }
      }


#if defined(DOS)
   for (i=0; i < MAX_SCSI_TAR; i++)
   {
     	if (((ScamFlg & SCAM_ENABLED) && (scamInfo[i].state == LEGACY))
			|| (i != p_our_id))
        	{
         scsellDOS(p_port,i);
  	      }
  	}
#endif

/*
   for (i=0,k=0; i < MAX_SCSI_TAR; i++)
      {
      if ((scamInfo[i].state == ID_ASSIGNED) ||
         (scamInfo[i].state == LEGACY))
         k++;
      }

   if (k==2)
      currCard->globalFlags |= F_SINGLE_DEVICE;
   else
      currCard->globalFlags &= ~F_SINGLE_DEVICE;
*/
}


/*---------------------------------------------------------------------
 *
 * Function: scarb
 *
 * Description: Gain control of the bus and wait SCAM select time (250ms)
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
int scarb(USHORT p_port, UCHAR p_sel_type)
#else
int scarb(ULONG p_port, UCHAR p_sel_type)
#endif
{
   if (p_sel_type == INIT_SELTD)
      {

      while (RD_HARPOON(p_port+hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {}


      if (RD_HARPOON(p_port+hp_scsisig) & SCSI_SEL)
         return(FALSE);

      if (RD_HARPOON(p_port+hp_scsidata_0) != 00)
         return(FALSE);

      WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_BSY));

      if (RD_HARPOON(p_port+hp_scsisig) & SCSI_SEL) {

         WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) &
            ~SCSI_BSY));
         return(FALSE);
         }


      WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_SEL));

      if (RD_HARPOON(p_port+hp_scsidata_0) != 00) {

         WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) &
            ~(SCSI_BSY | SCSI_SEL)));
         return(FALSE);
         }
      }


   WR_HARPOON(p_port+hp_clkctrl_0, (RD_HARPOON(p_port+hp_clkctrl_0)
      & ~ACTdeassert));
   WR_HARPOON(p_port+hp_scsireset, SCAM_EN);
   WR_HARPOON(p_port+hp_scsidata_0, 0x00);
#if defined(WIDE_SCSI)
   WR_HARPOON(p_port+hp_scsidata_1, 0x00);
#endif
   WR_HARPOON(p_port+hp_portctrl_0, SCSI_BUS_EN);

   WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_MSG));

   WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig)
      & ~SCSI_BSY));

   Wait(p_port,TO_250ms);

   return(TRUE);
}


/*---------------------------------------------------------------------
 *
 * Function: scbusf
 *
 * Description: Release the SCSI bus and disable SCAM selection.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void scbusf(USHORT p_port)
#else
void scbusf(ULONG p_port)
#endif
{
   WR_HARPOON(p_port+hp_page_ctrl,
      (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE));


   WR_HARPOON(p_port+hp_scsidata_0, 0x00);

   WR_HARPOON(p_port+hp_portctrl_0, (RD_HARPOON(p_port+hp_portctrl_0)
      & ~SCSI_BUS_EN));

   WR_HARPOON(p_port+hp_scsisig, 0x00);


   WR_HARPOON(p_port+hp_scsireset,  (RD_HARPOON(p_port+hp_scsireset)
      & ~SCAM_EN));

   WR_HARPOON(p_port+hp_clkctrl_0, (RD_HARPOON(p_port+hp_clkctrl_0)
      | ACTdeassert));

#if defined(SCAM_LEV_2)
   WRW_HARPOON((p_port+hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
#else
   WRW_HARPOON((p_port+hp_intstat), (BUS_FREE | AUTO_INT));
#endif

   WR_HARPOON(p_port+hp_page_ctrl,
      (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));
}



/*---------------------------------------------------------------------
 *
 * Function: scasid
 *
 * Description: Assign an ID to all the SCAM devices.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void scasid(UCHAR p_card, USHORT p_port)
#else
void scasid(UCHAR p_card, ULONG p_port)
#endif
{
#if defined(DOS) || defined(OS2)
   /* Use external defined in global space area, instead of Stack
      space. WIN/95 DOS doesnot work TINY mode. The OS doesnot intialize
      SS equal to DS. Thus the array allocated on stack doesnot get
      access correctly */
#else
   UCHAR temp_id_string[ID_STRING_LENGTH];
#endif

   UCHAR i,k,scam_id;
	UCHAR crcBytes[3];
	PNVRamInfo pCurrNvRam;
	ushort_ptr pCrcBytes;

	pCurrNvRam = BL_Card[p_card].pNvRamInfo;

   i=FALSE;

   while (!i)
      {

      for (k=0; k < ID_STRING_LENGTH; k++)
         {
         temp_id_string[k] = (UCHAR) 0x00;
         }

      scxferc(p_port,SYNC_PTRN);
      scxferc(p_port,ASSIGN_ID);

      if (!(sciso(p_port,&temp_id_string[0])))
         {
			if(pCurrNvRam){
				pCrcBytes = (ushort_ptr)&crcBytes[0];
				*pCrcBytes = CalcCrc16(&temp_id_string[0]);
				crcBytes[2] = CalcLrc(&temp_id_string[0]);
				temp_id_string[1] = crcBytes[2];
				temp_id_string[2] = crcBytes[0];
				temp_id_string[3] = crcBytes[1];
				for(k = 4; k < ID_STRING_LENGTH; k++)
					temp_id_string[k] = (UCHAR) 0x00;
			}
         i = scmachid(p_card,temp_id_string);

         if (i == CLR_PRIORITY)
            {
            scxferc(p_port,MISC_CODE);
            scxferc(p_port,CLR_P_FLAG);
            i = FALSE;  /*Not the last ID yet. */
            }

         else if (i != NO_ID_AVAIL)
            {
            if (i < 8 )
               scxferc(p_port,ID_0_7);
            else
               scxferc(p_port,ID_8_F);

            scam_id = (i & (UCHAR) 0x07);


            for (k=1; k < 0x08; k <<= 1)
               if (!( k & i ))
                  scam_id += 0x08;        /*Count number of zeros in DB0-3. */

            scxferc(p_port,scam_id);

            i = FALSE;  /*Not the last ID yet. */
            }
         }

      else
         {
         i = TRUE;
         }

      }  /*End while */

   scxferc(p_port,SYNC_PTRN);
   scxferc(p_port,CFG_CMPLT);
}





/*---------------------------------------------------------------------
 *
 * Function: scsel
 *
 * Description: Select all the SCAM devices.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void scsel(USHORT p_port)
#else
void scsel(ULONG p_port)
#endif
{

   WR_HARPOON(p_port+hp_scsisig, SCSI_SEL);
   scwiros(p_port, SCSI_MSG);

   WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY));


   WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
   WR_HARPOON(p_port+hp_scsidata_0, (UCHAR)(RD_HARPOON(p_port+hp_scsidata_0) |
      (UCHAR)(BIT(7)+BIT(6))));


   WR_HARPOON(p_port+hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
   scwiros(p_port, SCSI_SEL);

   WR_HARPOON(p_port+hp_scsidata_0, (UCHAR)(RD_HARPOON(p_port+hp_scsidata_0) &
      ~(UCHAR)BIT(6)));
   scwirod(p_port, BIT(6));

   WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
}



/*---------------------------------------------------------------------
 *
 * Function: scxferc
 *
 * Description: Handshake the p_data (DB4-0) across the bus.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
UCHAR scxferc(USHORT p_port, UCHAR p_data)
#else
UCHAR scxferc(ULONG p_port, UCHAR p_data)
#endif
{
   UCHAR curr_data, ret_data;

   curr_data = p_data | BIT(7) | BIT(5);   /*Start with DB7 & DB5 asserted. */

   WR_HARPOON(p_port+hp_scsidata_0, curr_data);

   curr_data &= ~BIT(7);

   WR_HARPOON(p_port+hp_scsidata_0, curr_data);

   scwirod(p_port,BIT(7));              /*Wait for DB7 to be released. */
	while (!(RD_HARPOON(p_port+hp_scsidata_0) & BIT(5)));

   ret_data = (RD_HARPOON(p_port+hp_scsidata_0) & (UCHAR) 0x1F);

   curr_data |= BIT(6);

   WR_HARPOON(p_port+hp_scsidata_0, curr_data);

   curr_data &= ~BIT(5);

   WR_HARPOON(p_port+hp_scsidata_0, curr_data);

   scwirod(p_port,BIT(5));              /*Wait for DB5 to be released. */

   curr_data &= ~(BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0)); /*Release data bits */
   curr_data |= BIT(7);

   WR_HARPOON(p_port+hp_scsidata_0, curr_data);

   curr_data &= ~BIT(6);

   WR_HARPOON(p_port+hp_scsidata_0, curr_data);

   scwirod(p_port,BIT(6));              /*Wait for DB6 to be released. */

   return(ret_data);
}


/*---------------------------------------------------------------------
 *
 * Function: scsendi
 *
 * Description: Transfer our Identification string to determine if we
 *              will be the dominant master.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
UCHAR scsendi(USHORT p_port, UCHAR p_id_string[])
#else
UCHAR scsendi(ULONG p_port, UCHAR p_id_string[])
#endif
{
   UCHAR ret_data,byte_cnt,bit_cnt,defer;

   defer = FALSE;

   for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {

      for (bit_cnt = 0x80; bit_cnt != 0 ; bit_cnt >>= 1) {

         if (defer)
            ret_data = scxferc(p_port,00);

         else if (p_id_string[byte_cnt] & bit_cnt)

               ret_data = scxferc(p_port,02);

            else {

               ret_data = scxferc(p_port,01);
               if (ret_data & 02)
                  defer = TRUE;
               }

         if ((ret_data & 0x1C) == 0x10)
            return(0x00);  /*End of isolation stage, we won! */

         if (ret_data & 0x1C)
            return(0xFF);

         if ((defer) && (!(ret_data & 0x1F)))
            return(0x01);  /*End of isolation stage, we lost. */

         } /*bit loop */

      } /*byte loop */

   if (defer)
      return(0x01);  /*We lost */
   else
      return(0);  /*We WON! Yeeessss! */
}



/*---------------------------------------------------------------------
 *
 * Function: sciso
 *
 * Description: Transfer the Identification string.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
UCHAR sciso(USHORT p_port, UCHAR p_id_string[])
#else
UCHAR sciso(ULONG p_port, UCHAR p_id_string[])
#endif
{
   UCHAR ret_data,the_data,byte_cnt,bit_cnt;

   the_data = 0;

   for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {

      for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {

         ret_data = scxferc(p_port,0);

         if (ret_data & 0xFC)
            return(0xFF);

         else {

            the_data <<= 1;
            if (ret_data & BIT(1)) {
               the_data |= 1;
               }
            }

         if ((ret_data & 0x1F) == 0)
	   {
/*
				if(bit_cnt != 0 || bit_cnt != 8)
				{
					byte_cnt = 0;
					bit_cnt = 0;
					scxferc(p_port, SYNC_PTRN);
					scxferc(p_port, ASSIGN_ID);
					continue;
				}
*/
            if (byte_cnt)
               return(0x00);
            else
               return(0xFF);
	   }

         } /*bit loop */

      p_id_string[byte_cnt] = the_data;

      } /*byte loop */

   return(0);
}



/*---------------------------------------------------------------------
 *
 * Function: scwirod
 *
 * Description: Sample the SCSI data bus making sure the signal has been
 *              deasserted for the correct number of consecutive samples.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void scwirod(USHORT p_port, UCHAR p_data_bit)
#else
void scwirod(ULONG p_port, UCHAR p_data_bit)
#endif
{
   UCHAR i;

   i = 0;
   while ( i < MAX_SCSI_TAR ) {

      if (RD_HARPOON(p_port+hp_scsidata_0) & p_data_bit)

         i = 0;

      else

         i++;

      }
}



/*---------------------------------------------------------------------
 *
 * Function: scwiros
 *
 * Description: Sample the SCSI Signal lines making sure the signal has been
 *              deasserted for the correct number of consecutive samples.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void scwiros(USHORT p_port, UCHAR p_data_bit)
#else
void scwiros(ULONG p_port, UCHAR p_data_bit)
#endif
{
   UCHAR i;

   i = 0;
   while ( i < MAX_SCSI_TAR ) {

      if (RD_HARPOON(p_port+hp_scsisig) & p_data_bit)

         i = 0;

      else

         i++;

      }
}


/*---------------------------------------------------------------------
 *
 * Function: scvalq
 *
 * Description: Make sure we received a valid data byte.
 *
 *---------------------------------------------------------------------*/

UCHAR scvalq(UCHAR p_quintet)
{
   UCHAR count;

   for (count=1; count < 0x08; count<<=1) {
      if (!(p_quintet & count))
         p_quintet -= 0x80;
      }

   if (p_quintet & 0x18)
      return(FALSE);

   else
      return(TRUE);
}


/*---------------------------------------------------------------------
 *
 * Function: scsell
 *
 * Description: Select the specified device ID using a selection timeout
 *              less than 4ms.  If somebody responds then it is a legacy
 *              drive and this ID must be marked as such.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
UCHAR scsell(USHORT p_port, UCHAR targ_id)
#else
UCHAR scsell(ULONG p_port, UCHAR targ_id)
#endif
{
#if defined(DOS)
   USHORT i;
#else
   ULONG i;
#endif

   WR_HARPOON(p_port+hp_page_ctrl,
      (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE));

   ARAM_ACCESS(p_port);

   WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) | SCAM_TIMER));
   WR_HARPOON(p_port+hp_seltimeout,TO_4ms);


   for (i = p_port+CMD_STRT; i < p_port+CMD_STRT+12; i+=2) {
      WRW_HARPOON(i, (MPM_OP+ACOMMAND));
      }
   WRW_HARPOON(i, (BRH_OP+ALWAYS+    NP));

   WRW_HARPOON((p_port+hp_intstat),
	       (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));

   WR_HARPOON(p_port+hp_select_id, targ_id);

   WR_HARPOON(p_port+hp_portctrl_0, SCSI_PORT);
   WR_HARPOON(p_port+hp_autostart_3, (SELECT | CMD_ONLY_STRT));
   WR_HARPOON(p_port+hp_scsictrl_0, (SEL_TAR | ENA_RESEL));


   while (!(RDW_HARPOON((p_port+hp_intstat)) &
	    (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {}

   if (RDW_HARPOON((p_port+hp_intstat)) & RESET)
         Wait(p_port, TO_250ms);

   DISABLE_AUTO(p_port);

   WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) & ~SCAM_TIMER));
   WR_HARPOON(p_port+hp_seltimeout,TO_290ms);

   SGRAM_ACCESS(p_port);

   if (RDW_HARPOON((p_port+hp_intstat)) & (RESET | TIMEOUT) ) {

      WRW_HARPOON((p_port+hp_intstat),
		  (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));

      WR_HARPOON(p_port+hp_page_ctrl,
         (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));

      return(FALSE);  /*No legacy device */
      }

   else {

      while(!(RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE)) {
				if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ)
					{
					WR_HARPOON(p_port+hp_scsisig, (SCSI_ACK + S_ILL_PH));
      			ACCEPT_MSG(p_port);
					}
		}

      WRW_HARPOON((p_port+hp_intstat), CLR_ALL_INT_1);

      WR_HARPOON(p_port+hp_page_ctrl,
         (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));

      return(TRUE);  /*Found one of them oldies! */
      }
}

#if defined(DOS)
/*---------------------------------------------------------------------
 *
 * Function: scsell for DOS
 *
 * Description: Select the specified device ID using a selection timeout
 *              less than 2ms.  This was specially required to solve
 *              the problem with Plextor 12X CD-ROM drive. This drive
 *					 was responding the Selection at the end of 4ms and 
 *					 hanging the system.
 *
 *---------------------------------------------------------------------*/

UCHAR scsellDOS(USHORT p_port, UCHAR targ_id)
{
   USHORT i;

   WR_HARPOON(p_port+hp_page_ctrl,
      (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE));

   ARAM_ACCESS(p_port);

   WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) | SCAM_TIMER));
   WR_HARPOON(p_port+hp_seltimeout,TO_2ms);


   for (i = p_port+CMD_STRT; i < p_port+CMD_STRT+12; i+=2) {
      WRW_HARPOON(i, (MPM_OP+ACOMMAND));
      }
   WRW_HARPOON(i, (BRH_OP+ALWAYS+    NP));

   WRW_HARPOON((p_port+hp_intstat),
	       (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));

   WR_HARPOON(p_port+hp_select_id, targ_id);

   WR_HARPOON(p_port+hp_portctrl_0, SCSI_PORT);
   WR_HARPOON(p_port+hp_autostart_3, (SELECT | CMD_ONLY_STRT));
   WR_HARPOON(p_port+hp_scsictrl_0, (SEL_TAR | ENA_RESEL));


   while (!(RDW_HARPOON((p_port+hp_intstat)) &
	    (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {}

   if (RDW_HARPOON((p_port+hp_intstat)) & RESET)
         Wait(p_port, TO_250ms);

   DISABLE_AUTO(p_port);

   WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) & ~SCAM_TIMER));
   WR_HARPOON(p_port+hp_seltimeout,TO_290ms);

   SGRAM_ACCESS(p_port);

   if (RDW_HARPOON((p_port+hp_intstat)) & (RESET | TIMEOUT) ) {

      WRW_HARPOON((p_port+hp_intstat),
		  (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));

      WR_HARPOON(p_port+hp_page_ctrl,
         (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));

      return(FALSE);  /*No legacy device */
      }

   else {

      while(!(RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE)) {
				if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ)
					{
					WR_HARPOON(p_port+hp_scsisig, (SCSI_ACK + S_ILL_PH));
      			ACCEPT_MSG(p_port);
					}
		}

      WRW_HARPOON((p_port+hp_intstat), CLR_ALL_INT_1);

      WR_HARPOON(p_port+hp_page_ctrl,
         (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));

      return(TRUE);  /*Found one of them oldies! */
      }
}
#endif  /* DOS */

/*---------------------------------------------------------------------
 *
 * Function: scwtsel
 *
 * Description: Wait to be selected by another SCAM initiator.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void scwtsel(USHORT p_port)
#else
void scwtsel(ULONG p_port)
#endif
{
   while(!(RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) {}
}


/*---------------------------------------------------------------------
 *
 * Function: inisci
 *
 * Description: Setup the data Structure with the info from the EEPROM.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void inisci(UCHAR p_card, USHORT p_port, UCHAR p_our_id)
#else
void inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id)
#endif
{
   UCHAR i,k,max_id;
   USHORT ee_data;
	PNVRamInfo pCurrNvRam;

	pCurrNvRam = BL_Card[p_card].pNvRamInfo;

   if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD)
      max_id = 0x08;

   else
      max_id = 0x10;

	if(pCurrNvRam){
		for(i = 0; i < max_id; i++){

			for(k = 0; k < 4; k++)
				scamInfo[i].id_string[k] = pCurrNvRam->niScamTbl[i][k];
			for(k = 4; k < ID_STRING_LENGTH; k++)
				scamInfo[i].id_string[k] = (UCHAR) 0x00;

	      if(scamInfo[i].id_string[0] == 0x00)
      	   scamInfo[i].state = ID_UNUSED;  /*Default to unused ID. */
	      else
   	      scamInfo[i].state = ID_UNASSIGNED;  /*Default to unassigned ID. */

		}
	}else {
	   for (i=0; i < max_id; i++)
   	   {
      	for (k=0; k < ID_STRING_LENGTH; k+=2)
	         {
   	      ee_data = utilEERead(p_port, (USHORT)((EE_SCAMBASE/2) +
      	     (USHORT) (i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2)));
         	scamInfo[i].id_string[k] = (UCHAR) ee_data;
	         ee_data >>= 8;
   	      scamInfo[i].id_string[k+1] = (UCHAR) ee_data;
      	   }

	      if ((scamInfo[i].id_string[0] == 0x00) ||
   	       (scamInfo[i].id_string[0] == 0xFF))

      	   scamInfo[i].state = ID_UNUSED;  /*Default to unused ID. */

	      else
   	      scamInfo[i].state = ID_UNASSIGNED;  /*Default to unassigned ID. */

      	}
	}
	for(k = 0; k < ID_STRING_LENGTH; k++)
		scamInfo[p_our_id].id_string[k] = scamHAString[k];

}

/*---------------------------------------------------------------------
 *
 * Function: scmachid
 *
 * Description: Match the Device ID string with our values stored in
 *              the EEPROM.
 *
 *---------------------------------------------------------------------*/

UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[])
{

   UCHAR i,k,match;


   for (i=0; i < MAX_SCSI_TAR; i++) {

#if !defined(SCAM_LEV_2)
      if (scamInfo[i].state == ID_UNASSIGNED)
         {
#endif
         match = TRUE;

         for (k=0; k < ID_STRING_LENGTH; k++)
            {
            if (p_id_string[k] != scamInfo[i].id_string[k])
               match = FALSE;
            }

         if (match)
            {
            scamInfo[i].state = ID_ASSIGNED;
            return(i);
            }

#if !defined(SCAM_LEV_2)
         }
#endif

      }



   if (p_id_string[0] & BIT(5))
      i = 8;
   else
      i = MAX_SCSI_TAR;

   if (((p_id_string[0] & 0x06) == 0x02) || ((p_id_string[0] & 0x06) == 0x04))
      match = p_id_string[1] & (UCHAR) 0x1F;
   else
      match = 7;

   while (i > 0)
      {
      i--;

      if (scamInfo[match].state == ID_UNUSED)
         {
         for (k=0; k < ID_STRING_LENGTH; k++)
            {
            scamInfo[match].id_string[k] = p_id_string[k];
            }

         scamInfo[match].state = ID_ASSIGNED;

			if(BL_Card[p_card].pNvRamInfo == NULL)
	         BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM;
         return(match);

         }


      match--;

      if (match == 0xFF)
	{
         if (p_id_string[0] & BIT(5))
            match = 7;
         else
            match = MAX_SCSI_TAR-1;
	}
      }



   if (p_id_string[0] & BIT(7))
      {
      return(CLR_PRIORITY);
      }


   if (p_id_string[0] & BIT(5))
      i = 8;
   else
      i = MAX_SCSI_TAR;

   if (((p_id_string[0] & 0x06) == 0x02) || ((p_id_string[0] & 0x06) == 0x04))
      match = p_id_string[1] & (UCHAR) 0x1F;
   else
      match = 7;

   while (i > 0)
      {

      i--;

      if (scamInfo[match].state == ID_UNASSIGNED)
         {
         for (k=0; k < ID_STRING_LENGTH; k++)
            {
            scamInfo[match].id_string[k] = p_id_string[k];
            }

         scamInfo[match].id_string[0] |= BIT(7);
         scamInfo[match].state = ID_ASSIGNED;
			if(BL_Card[p_card].pNvRamInfo == NULL)
	         BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM;
         return(match);

         }


      match--;

      if (match == 0xFF)
	{
         if (p_id_string[0] & BIT(5))
            match = 7;
         else
            match = MAX_SCSI_TAR-1;
	}
      }

   return(NO_ID_AVAIL);
}


/*---------------------------------------------------------------------
 *
 * Function: scsavdi
 *
 * Description: Save off the device SCAM ID strings.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void scsavdi(UCHAR p_card, USHORT p_port)
#else
void scsavdi(UCHAR p_card, ULONG p_port)
#endif
{
   UCHAR i,k,max_id;
   USHORT ee_data,sum_data;


   sum_data = 0x0000;

   for (i = 1; i < EE_SCAMBASE/2; i++)
      {
      sum_data += utilEERead(p_port, i);
      }


   utilEEWriteOnOff(p_port,1);   /* Enable write access to the EEPROM */

   if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD)
      max_id = 0x08;

   else
      max_id = 0x10;

   for (i=0; i < max_id; i++)
      {

      for (k=0; k < ID_STRING_LENGTH; k+=2)
         {
         ee_data = scamInfo[i].id_string[k+1];
         ee_data <<= 8;
         ee_data |= scamInfo[i].id_string[k];
         sum_data += ee_data;
         utilEEWrite(p_port, ee_data, (USHORT)((EE_SCAMBASE/2) +
            (USHORT)(i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2)));
         }
      }


   utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM/2);
   utilEEWriteOnOff(p_port,0);   /* Turn off write access */
}
#ident "$Id: diagnose.c 1.10 1997/06/10 16:51:47 mohan Exp $"
/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   diagnose.c  $
 *
 *   Description:  Diagnostic funtions for testing the integrity of
 *                 the HARPOON.
 *
 *   $Date: 1997/06/10 16:51:47 $
 *
 *   $Revision: 1.10 $
 *
 *----------------------------------------------------------------------*/

/*#include <globals.h>*/

#if (FW_TYPE==_UCB_MGR_)
	/*#include <budi.h>*/
#endif

/*#include <sccbmgr.h>*/
/*#include <blx30.h>*/
/*#include <target.h>*/
/*#include <eeprom.h>*/
/*#include <harpoon.h>*/

/*---------------------------------------------------------------------
 *
 * Function: XbowInit
 *
 * Description: Setup the Xbow for normal operation.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void XbowInit(USHORT port, UCHAR ScamFlg)
#else
void XbowInit(ULONG port, UCHAR ScamFlg)
#endif
{
UCHAR i;

	i = RD_HARPOON(port+hp_page_ctrl);
	WR_HARPOON(port+hp_page_ctrl, (UCHAR) (i | G_INT_DISABLE));

   WR_HARPOON(port+hp_scsireset,0x00);
   WR_HARPOON(port+hp_portctrl_1,HOST_MODE8);

   WR_HARPOON(port+hp_scsireset,(DMA_RESET | HPSCSI_RESET | PROG_RESET | \
				 FIFO_CLR));

   WR_HARPOON(port+hp_scsireset,SCSI_INI);

   WR_HARPOON(port+hp_clkctrl_0,CLKCTRL_DEFAULT);

   WR_HARPOON(port+hp_scsisig,0x00);         /*  Clear any signals we might */
   WR_HARPOON(port+hp_scsictrl_0,ENA_SCAM_SEL);

   WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);

#if defined(SCAM_LEV_2)
   default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
		    BUS_FREE | XFER_CNT_0 | AUTO_INT;

   if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
		default_intena |= SCAM_SEL;

#else
   default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
		    BUS_FREE | XFER_CNT_0 | AUTO_INT;
#endif
   WRW_HARPOON((port+hp_intena), default_intena);

   WR_HARPOON(port+hp_seltimeout,TO_290ms);

   /* Turn on SCSI_MODE8 for narrow cards to fix the
      strapping issue with the DUAL CHANNEL card */
   if (RD_HARPOON(port+hp_page_ctrl) & NARROW_SCSI_CARD)
      WR_HARPOON(port+hp_addstat,SCSI_MODE8);

#if defined(NO_BIOS_OPTION)

   WR_HARPOON(port+hp_synctarg_0,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_1,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_2,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_3,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_4,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_5,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_6,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_7,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_8,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_9,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_10,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_11,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_12,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_13,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_14,NARROW_SCSI);
   WR_HARPOON(port+hp_synctarg_15,NARROW_SCSI);

#endif
	WR_HARPOON(port+hp_page_ctrl, i);

}


/*---------------------------------------------------------------------
 *
 * Function: BusMasterInit
 *
 * Description: Initialize the BusMaster for normal operations.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void BusMasterInit(USHORT p_port)
#else
void BusMasterInit(ULONG p_port)
#endif
{


   WR_HARPOON(p_port+hp_sys_ctrl, DRVR_RST);
   WR_HARPOON(p_port+hp_sys_ctrl, 0x00);

   WR_HARPOON(p_port+hp_host_blk_cnt, XFER_BLK64);


   WR_HARPOON(p_port+hp_bm_ctrl, (BMCTRL_DEFAULT));

   WR_HARPOON(p_port+hp_ee_ctrl, (SCSI_TERM_ENA_H));


#if defined(NT)

   WR_HARPOON(p_port+hp_pci_cmd_cfg, (RD_HARPOON(p_port+hp_pci_cmd_cfg)
      & ~MEM_SPACE_ENA));

#endif

   RD_HARPOON(p_port+hp_int_status);        /*Clear interrupts. */
   WR_HARPOON(p_port+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
   WR_HARPOON(p_port+hp_page_ctrl, (RD_HARPOON(p_port+hp_page_ctrl) &
      ~SCATTER_EN));
}


/*---------------------------------------------------------------------
 *
 * Function: DiagXbow
 *
 * Description: Test Xbow integrity.  Non-zero return indicates an error.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
int DiagXbow(USHORT port)
#else
int DiagXbow(ULONG port)
#endif
{
   unsigned char fifo_cnt,loop_cnt;

   unsigned char fifodata[5];
   fifodata[0] = 0x00;
   fifodata[1] = 0xFF;
   fifodata[2] = 0x55;
   fifodata[3] = 0xAA;
   fifodata[4] = 0x00;


   WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);
   WRW_HARPOON((port+hp_intena), 0x0000);

   WR_HARPOON(port+hp_seltimeout,TO_5ms);

   WR_HARPOON(port+hp_portctrl_0,START_TO);


   for(fifodata[4] = 0x01; fifodata[4] != (UCHAR) 0; fifodata[4] = fifodata[4] << 1) {

      WR_HARPOON(port+hp_selfid_0,fifodata[4]);
      WR_HARPOON(port+hp_selfid_1,fifodata[4]);

      if ((RD_HARPOON(port+hp_selfid_0) != fifodata[4]) ||
          (RD_HARPOON(port+hp_selfid_1) != fifodata[4]))
         return(1);
      }


   for(loop_cnt = 0; loop_cnt < 4; loop_cnt++) {

      WR_HARPOON(port+hp_portctrl_0,(HOST_PORT | HOST_WRT | START_TO));


      for (fifo_cnt = 0; fifo_cnt < FIFO_LEN; fifo_cnt++) {

         WR_HARPOON(port+hp_fifodata_0, fifodata[loop_cnt]);
         }


      if (!(RD_HARPOON(port+hp_xferstat) & FIFO_FULL))
         return(1);


      WR_HARPOON(port+hp_portctrl_0,(HOST_PORT | START_TO));

      for (fifo_cnt = 0; fifo_cnt < FIFO_LEN; fifo_cnt++) {

         if (RD_HARPOON(port+hp_fifodata_0) != fifodata[loop_cnt])
            return(1);
         }


      if (!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY))
         return(1);
      }


   while(!(RDW_HARPOON((port+hp_intstat)) & TIMEOUT)) {}


   WR_HARPOON(port+hp_seltimeout,TO_290ms);

   WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);

   WRW_HARPOON((port+hp_intena), default_intena);

   return(0);
}


/*---------------------------------------------------------------------
 *
 * Function: DiagBusMaster
 *
 * Description: Test BusMaster integrity.  Non-zero return indicates an
 *              error.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
int DiagBusMaster(USHORT port)
#else
int DiagBusMaster(ULONG port)
#endif
{
   UCHAR testdata;

   for(testdata = (UCHAR) 1; testdata != (UCHAR)0; testdata = testdata << 1) {

      WR_HARPOON(port+hp_xfer_cnt_lo,testdata);
      WR_HARPOON(port+hp_xfer_cnt_mi,testdata);
      WR_HARPOON(port+hp_xfer_cnt_hi,testdata);
      WR_HARPOON(port+hp_host_addr_lo,testdata);
      WR_HARPOON(port+hp_host_addr_lmi,testdata);
      WR_HARPOON(port+hp_host_addr_hmi,testdata);
      WR_HARPOON(port+hp_host_addr_hi,testdata);

      if ((RD_HARPOON(port+hp_xfer_cnt_lo) != testdata)   ||
          (RD_HARPOON(port+hp_xfer_cnt_mi) != testdata)   ||
          (RD_HARPOON(port+hp_xfer_cnt_hi) != testdata)   ||
          (RD_HARPOON(port+hp_host_addr_lo) != testdata)  ||
          (RD_HARPOON(port+hp_host_addr_lmi) != testdata) ||
          (RD_HARPOON(port+hp_host_addr_hmi) != testdata) ||
          (RD_HARPOON(port+hp_host_addr_hi) != testdata))

         return(1);
      }
   RD_HARPOON(port+hp_int_status);        /*Clear interrupts. */
   return(0);
}



/*---------------------------------------------------------------------
 *
 * Function: DiagEEPROM
 *
 * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
 *              neccessary.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void DiagEEPROM(USHORT p_port)
#else
void DiagEEPROM(ULONG p_port)
#endif

{
   USHORT index,temp,max_wd_cnt;

   if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD)
      max_wd_cnt = EEPROM_WD_CNT;
   else
      max_wd_cnt = EEPROM_WD_CNT * 2;

   temp = utilEERead(p_port, FW_SIGNATURE/2);

   if (temp == 0x4641) {

      for (index = 2; index < max_wd_cnt; index++) {

         temp += utilEERead(p_port, index);

         }

      if (temp == utilEERead(p_port, EEPROM_CHECK_SUM/2)) {

         return;          /*EEPROM is Okay so return now! */
         }
      }


   utilEEWriteOnOff(p_port,(UCHAR)1);

   for (index = 0; index < max_wd_cnt; index++) {

      utilEEWrite(p_port, 0x0000, index);
      }

   temp = 0;

   utilEEWrite(p_port, 0x4641, FW_SIGNATURE/2);
   temp += 0x4641;
   utilEEWrite(p_port, 0x3920, MODEL_NUMB_0/2);
   temp += 0x3920;
   utilEEWrite(p_port, 0x3033, MODEL_NUMB_2/2);
   temp += 0x3033;
   utilEEWrite(p_port, 0x2020, MODEL_NUMB_4/2);
   temp += 0x2020;
   utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG/2);
   temp += 0x70D3;
   utilEEWrite(p_port, 0x0010, BIOS_CONFIG/2);
   temp += 0x0010;
   utilEEWrite(p_port, 0x0003, SCAM_CONFIG/2);
   temp += 0x0003;
   utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID/2);
   temp += 0x0007;

   utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN/2);
   temp += 0x0000;
   utilEEWrite(p_port, 0x0000, SEND_START_ENA/2);
   temp += 0x0000;
   utilEEWrite(p_port, 0x0000, DEVICE_ENABLE/2);
   temp += 0x0000;

   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01/2);
   temp += 0x4242;
   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23/2);
   temp += 0x4242;
   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45/2);
   temp += 0x4242;
   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67/2);
   temp += 0x4242;
   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89/2);
   temp += 0x4242;
   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab/2);
   temp += 0x4242;
   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd/2);
   temp += 0x4242;
   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef/2);
   temp += 0x4242;


   utilEEWrite(p_port, 0x6C46, 64/2);  /*PRODUCT ID */
   temp += 0x6C46;
   utilEEWrite(p_port, 0x7361, 66/2);  /* FlashPoint LT   */
   temp += 0x7361;
   utilEEWrite(p_port, 0x5068, 68/2);
   temp += 0x5068;
   utilEEWrite(p_port, 0x696F, 70/2);
   temp += 0x696F;
   utilEEWrite(p_port, 0x746E, 72/2);
   temp += 0x746E;
   utilEEWrite(p_port, 0x4C20, 74/2);
   temp += 0x4C20;
   utilEEWrite(p_port, 0x2054, 76/2);
   temp += 0x2054;
   utilEEWrite(p_port, 0x2020, 78/2);
   temp += 0x2020;

   index = ((EE_SCAMBASE/2)+(7*16));
   utilEEWrite(p_port, (0x0700+TYPE_CODE0), index);
   temp += (0x0700+TYPE_CODE0);
   index++;
   utilEEWrite(p_port, 0x5542, index);            /*Vendor ID code */
   temp += 0x5542;                                /* BUSLOGIC      */
   index++;
   utilEEWrite(p_port, 0x4C53, index);
   temp += 0x4C53;
   index++;
   utilEEWrite(p_port, 0x474F, index);
   temp += 0x474F;
   index++;
   utilEEWrite(p_port, 0x4349, index);
   temp += 0x4349;
   index++;
   utilEEWrite(p_port, 0x5442, index);            /*Vendor unique code */
   temp += 0x5442;                         /* BT- 930           */
   index++;
   utilEEWrite(p_port, 0x202D, index);
   temp += 0x202D;
   index++;
   utilEEWrite(p_port, 0x3339, index);
   temp += 0x3339;
   index++;                                 /*Serial #          */
   utilEEWrite(p_port, 0x2030, index);             /* 01234567         */
   temp += 0x2030;
   index++;
   utilEEWrite(p_port, 0x5453, index);
   temp += 0x5453;
   index++;
   utilEEWrite(p_port, 0x5645, index);
   temp += 0x5645;
   index++;
   utilEEWrite(p_port, 0x2045, index);
   temp += 0x2045;
   index++;
   utilEEWrite(p_port, 0x202F, index);
   temp += 0x202F;
   index++;
   utilEEWrite(p_port, 0x4F4A, index);
   temp += 0x4F4A;
   index++;
   utilEEWrite(p_port, 0x204E, index);
   temp += 0x204E;
   index++;
   utilEEWrite(p_port, 0x3539, index);
   temp += 0x3539;



   utilEEWrite(p_port, temp, EEPROM_CHECK_SUM/2);

   utilEEWriteOnOff(p_port,(UCHAR)0);

}

#ident "$Id: utility.c 1.23 1997/06/10 16:55:06 mohan Exp $"
/*----------------------------------------------------------------------
 *
 *
 *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
 *
 *   This file is available under both the GNU General Public License
 *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
 *
 *   $Workfile:   utility.c  $
 *
 *   Description:  Utility functions relating to queueing and EEPROM
 *                 manipulation and any other garbage functions.
 *
 *   $Date: 1997/06/10 16:55:06 $
 *
 *   $Revision: 1.23 $
 *
 *----------------------------------------------------------------------*/
/*#include <globals.h>*/

#if (FW_TYPE==_UCB_MGR_)
	/*#include <budi.h>*/
#endif

/*#include <sccbmgr.h>*/
/*#include <blx30.h>*/
/*#include <target.h>*/
/*#include <scsi2.h>*/
/*#include <harpoon.h>*/


/*
extern SCCBCARD BL_Card[MAX_CARDS];
extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
extern unsigned int SccbGlobalFlags;
*/

/*---------------------------------------------------------------------
 *
 * Function: Queue Search Select
 *
 * Description: Try to find a new command to execute.
 *
 *---------------------------------------------------------------------*/

void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card)
{
   UCHAR scan_ptr, lun;
   PSCCBMgr_tar_info currTar_Info;
	PSCCB pOldSccb;

   scan_ptr = pCurrCard->scanIndex;
	do 
	{
		currTar_Info = &sccbMgrTbl[p_card][scan_ptr];
		if((pCurrCard->globalFlags & F_CONLUN_IO) && 
			((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
		{
			if (currTar_Info->TarSelQ_Cnt != 0)
			{

				scan_ptr++;
				if (scan_ptr == MAX_SCSI_TAR)
					scan_ptr = 0;
				
				for(lun=0; lun < MAX_LUN; lun++)
				{
					if(currTar_Info->TarLUNBusy[lun] == FALSE)
					{

						pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head;
						pOldSccb = NULL;

						while((pCurrCard->currentSCCB != NULL) &&
								 (lun != pCurrCard->currentSCCB->Lun))
						{
							pOldSccb = pCurrCard->currentSCCB;
							pCurrCard->currentSCCB = (PSCCB)(pCurrCard->currentSCCB)->
																	Sccb_forwardlink;
						}
						if(pCurrCard->currentSCCB == NULL)
							continue;
						if(pOldSccb != NULL)
						{
							pOldSccb->Sccb_forwardlink = (PSCCB)(pCurrCard->currentSCCB)->
																	Sccb_forwardlink;
							pOldSccb->Sccb_backlink = (PSCCB)(pCurrCard->currentSCCB)->
																	Sccb_backlink;
							currTar_Info->TarSelQ_Cnt--;
						}
						else
						{
							currTar_Info->TarSelQ_Head = (PSCCB)(pCurrCard->currentSCCB)->Sccb_forwardlink;
					
							if (currTar_Info->TarSelQ_Head == NULL)
							{
								currTar_Info->TarSelQ_Tail = NULL;
								currTar_Info->TarSelQ_Cnt = 0;
							}
							else
							{
								currTar_Info->TarSelQ_Cnt--;
								currTar_Info->TarSelQ_Head->Sccb_backlink = (PSCCB)NULL;
							}
						}
					pCurrCard->scanIndex = scan_ptr;

					pCurrCard->globalFlags |= F_NEW_SCCB_CMD;

					break;
					}
				}
			}

			else 
			{
				scan_ptr++;
				if (scan_ptr == MAX_SCSI_TAR) {
					scan_ptr = 0;
				}
			}

		}
		else
		{
			if ((currTar_Info->TarSelQ_Cnt != 0) &&
				(currTar_Info->TarLUNBusy[0] == FALSE))
			{

				pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head;

				currTar_Info->TarSelQ_Head = (PSCCB)(pCurrCard->currentSCCB)->Sccb_forwardlink;

				if (currTar_Info->TarSelQ_Head == NULL)
				{
					currTar_Info->TarSelQ_Tail = NULL;
					currTar_Info->TarSelQ_Cnt = 0;
				}
				else
				{
					currTar_Info->TarSelQ_Cnt--;
					currTar_Info->TarSelQ_Head->Sccb_backlink = (PSCCB)NULL;
				}

				scan_ptr++;
				if (scan_ptr == MAX_SCSI_TAR)
					scan_ptr = 0;

				pCurrCard->scanIndex = scan_ptr;

				pCurrCard->globalFlags |= F_NEW_SCCB_CMD;

				break;
			}

			else 
			{
				scan_ptr++;
				if (scan_ptr == MAX_SCSI_TAR) 
				{
					scan_ptr = 0;
				}
			}
		}
	} while (scan_ptr != pCurrCard->scanIndex);
}


/*---------------------------------------------------------------------
 *
 * Function: Queue Select Fail
 *
 * Description: Add the current SCCB to the head of the Queue.
 *
 *---------------------------------------------------------------------*/

void queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card)
{
   UCHAR thisTarg;
   PSCCBMgr_tar_info currTar_Info;

   if (pCurrCard->currentSCCB != NULL)
	  {
	  thisTarg = (UCHAR)(((PSCCB)(pCurrCard->currentSCCB))->TargID);
      currTar_Info = &sccbMgrTbl[p_card][thisTarg];

      pCurrCard->currentSCCB->Sccb_backlink = (PSCCB)NULL;

      pCurrCard->currentSCCB->Sccb_forwardlink = currTar_Info->TarSelQ_Head;

	  if (currTar_Info->TarSelQ_Cnt == 0)
		 {
		 currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
		 }

	  else
		 {
		 currTar_Info->TarSelQ_Head->Sccb_backlink = pCurrCard->currentSCCB;
		 }


	  currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;

	  pCurrCard->currentSCCB = NULL;
	  currTar_Info->TarSelQ_Cnt++;
	  }
}
/*---------------------------------------------------------------------
 *
 * Function: Queue Command Complete
 *
 * Description: Call the callback function with the current SCCB.
 *
 *---------------------------------------------------------------------*/

void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, UCHAR p_card)
{

#if (FW_TYPE==_UCB_MGR_)

   u08bits SCSIcmd;
   CALL_BK_FN callback;
   PSCCBMgr_tar_info currTar_Info;

   PUCB p_ucb;
   p_ucb=p_sccb->Sccb_ucb_ptr;

   SCSIcmd = p_sccb->Cdb[0];


   if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED))
   {

      if ((p_ucb->UCB_opcode & OPC_CHK_UNDER_OVER_RUN)                     &&
         (p_sccb->HostStatus == SCCB_COMPLETE)                             &&
         (p_sccb->TargetStatus != SSCHECK))

         if ((SCSIcmd == SCSI_READ)             ||
             (SCSIcmd == SCSI_WRITE)            ||
             (SCSIcmd == SCSI_READ_EXTENDED)    ||
             (SCSIcmd == SCSI_WRITE_EXTENDED)   ||
             (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
             (SCSIcmd == SCSI_START_STOP_UNIT)  ||
             (pCurrCard->globalFlags & F_NO_FILTER)
            )
               p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
   }

   p_ucb->UCB_status=SCCB_SUCCESS;

   if ((p_ucb->UCB_hbastat=p_sccb->HostStatus) || (p_ucb->UCB_scsistat=p_sccb->TargetStatus))
   {
      p_ucb->UCB_status=SCCB_ERROR;
   }

   if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
      (p_sccb->OperationCode == RESIDUAL_COMMAND))
   {

         utilUpdateResidual(p_sccb);

         p_ucb->UCB_datalen=p_sccb->DataLength;
   }

   pCurrCard->cmdCounter--;
   if (!pCurrCard->cmdCounter)
   {

      if (pCurrCard->globalFlags & F_GREEN_PC)
      {
         WR_HARPOON(pCurrCard->ioPort+hp_clkctrl_0,(PWR_DWN | CLKCTRL_DEFAULT));
         WR_HARPOON(pCurrCard->ioPort+hp_sys_ctrl, STOP_CLK);
      }

      WR_HARPOON(pCurrCard->ioPort+hp_semaphore,
      (RD_HARPOON(pCurrCard->ioPort+hp_semaphore) & ~SCCB_MGR_ACTIVE));
   }

	if(pCurrCard->discQCount != 0)
	{
      currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];
		if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
			((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
		{
			pCurrCard->discQCount--;
			pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = NULL;
		}
		else
		{
			if(p_sccb->Sccb_tag)
			{
				pCurrCard->discQCount--;
				pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
			}else
			{
				pCurrCard->discQCount--;
				pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL;
			}
		}

	}
   callback = (CALL_BK_FN)p_ucb->UCB_callback;
   callback(p_ucb);
   pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
   pCurrCard->currentSCCB = NULL;
}




#else

   UCHAR i, SCSIcmd;
   CALL_BK_FN callback;
   PSCCBMgr_tar_info currTar_Info;

   SCSIcmd = p_sccb->Cdb[0];


   if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {

	  if ((p_sccb->ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN)) &&
		 (p_sccb->HostStatus == SCCB_COMPLETE)                             &&
		 (p_sccb->TargetStatus != SSCHECK))

		 if ((SCSIcmd == SCSI_READ)             ||
			 (SCSIcmd == SCSI_WRITE)            ||
			 (SCSIcmd == SCSI_READ_EXTENDED)    ||
			 (SCSIcmd == SCSI_WRITE_EXTENDED)   ||
			 (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
			 (SCSIcmd == SCSI_START_STOP_UNIT)  ||
			 (pCurrCard->globalFlags & F_NO_FILTER)
			)
			   p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
	  }


	if(p_sccb->SccbStatus == SCCB_IN_PROCESS)
	{
	   if (p_sccb->HostStatus || p_sccb->TargetStatus)
		  p_sccb->SccbStatus = SCCB_ERROR;
	   else
		  p_sccb->SccbStatus = SCCB_SUCCESS;
	}

   if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {

	  p_sccb->CdbLength = p_sccb->Save_CdbLen;
	  for (i=0; i < 6; i++) {
		 p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
		 }
	  }

   if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
	  (p_sccb->OperationCode == RESIDUAL_COMMAND)) {

		 utilUpdateResidual(p_sccb);
		 }

   pCurrCard->cmdCounter--;
   if (!pCurrCard->cmdCounter) {

	  if (pCurrCard->globalFlags & F_GREEN_PC) {
		 WR_HARPOON(pCurrCard->ioPort+hp_clkctrl_0,(PWR_DWN | CLKCTRL_DEFAULT));
		 WR_HARPOON(pCurrCard->ioPort+hp_sys_ctrl, STOP_CLK);
		 }

	  WR_HARPOON(pCurrCard->ioPort+hp_semaphore,
	  (RD_HARPOON(pCurrCard->ioPort+hp_semaphore) & ~SCCB_MGR_ACTIVE));

	  }

	if(pCurrCard->discQCount != 0)
	{
      currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];
		if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
			((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
		{
			pCurrCard->discQCount--;
			pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = NULL;
		}
		else
		{
			if(p_sccb->Sccb_tag)
			{
				pCurrCard->discQCount--;
				pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
			}else
			{
				pCurrCard->discQCount--;
				pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL;
			}
		}

	}

	callback = (CALL_BK_FN)p_sccb->SccbCallback;
   callback(p_sccb);
   pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
   pCurrCard->currentSCCB = NULL;
}
#endif /* ( if FW_TYPE==...) */


/*---------------------------------------------------------------------
 *
 * Function: Queue Disconnect
 *
 * Description: Add SCCB to our disconnect array.
 *
 *---------------------------------------------------------------------*/
void queueDisconnect(PSCCB p_sccb, UCHAR p_card)
{
   PSCCBMgr_tar_info currTar_Info;

	currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];

	if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
		((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
	{
		BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = p_sccb;
	}
	else
	{
		if (p_sccb->Sccb_tag)
		{
			BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] = p_sccb;
			sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] = FALSE;
			sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
		}else
		{
			BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = p_sccb;
		}
	}
	BL_Card[p_card].currentSCCB = NULL;
}


/*---------------------------------------------------------------------
 *
 * Function: Queue Flush SCCB
 *
 * Description: Flush all SCCB's back to the host driver for this target.
 *
 *---------------------------------------------------------------------*/

void  queueFlushSccb(UCHAR p_card, UCHAR error_code)
{
   UCHAR qtag,thisTarg;
   PSCCB currSCCB;
   PSCCBMgr_tar_info currTar_Info;

   currSCCB = BL_Card[p_card].currentSCCB;
	if(currSCCB != NULL)
	{
	   thisTarg = (UCHAR)currSCCB->TargID;
   	currTar_Info = &sccbMgrTbl[p_card][thisTarg];

	   for (qtag=0; qtag<QUEUE_DEPTH; qtag++) {

		  if (BL_Card[p_card].discQ_Tbl[qtag] && 
					(BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg))
			 {

			 BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code;
			
			 queueCmdComplete(&BL_Card[p_card],BL_Card[p_card].discQ_Tbl[qtag], p_card);

			 BL_Card[p_card].discQ_Tbl[qtag] = NULL;
			 currTar_Info->TarTagQ_Cnt--;

			 }
		  }
	}

}

/*---------------------------------------------------------------------
 *
 * Function: Queue Flush Target SCCB
 *
 * Description: Flush all SCCB's back to the host driver for this target.
 *
 *---------------------------------------------------------------------*/

void  queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code)
{
   UCHAR qtag;
   PSCCBMgr_tar_info currTar_Info;

   currTar_Info = &sccbMgrTbl[p_card][thisTarg];

   for (qtag=0; qtag<QUEUE_DEPTH; qtag++) {

	  if (BL_Card[p_card].discQ_Tbl[qtag] && 
				(BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg))
		 {

		 BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code;

		 queueCmdComplete(&BL_Card[p_card],BL_Card[p_card].discQ_Tbl[qtag], p_card);

		 BL_Card[p_card].discQ_Tbl[qtag] = NULL;
		 currTar_Info->TarTagQ_Cnt--;

		 }
	  }

}





void queueAddSccb(PSCCB p_SCCB, UCHAR p_card)
{
   PSCCBMgr_tar_info currTar_Info;
   currTar_Info = &sccbMgrTbl[p_card][p_SCCB->TargID];

   p_SCCB->Sccb_forwardlink = NULL;

   p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;

   if (currTar_Info->TarSelQ_Cnt == 0) {

	  currTar_Info->TarSelQ_Head = p_SCCB;
	  }

   else {

	  currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
	  }


   currTar_Info->TarSelQ_Tail = p_SCCB;
   currTar_Info->TarSelQ_Cnt++;
}


/*---------------------------------------------------------------------
 *
 * Function: Queue Find SCCB
 *
 * Description: Search the target select Queue for this SCCB, and
 *              remove it if found.
 *
 *---------------------------------------------------------------------*/

UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card)
{
   PSCCB q_ptr;
   PSCCBMgr_tar_info currTar_Info;

   currTar_Info = &sccbMgrTbl[p_card][p_SCCB->TargID];

   q_ptr = currTar_Info->TarSelQ_Head;

   while(q_ptr != NULL) {

	  if (q_ptr == p_SCCB) {


		 if (currTar_Info->TarSelQ_Head == q_ptr) {

			currTar_Info->TarSelQ_Head = q_ptr->Sccb_forwardlink;
			}

		 if (currTar_Info->TarSelQ_Tail == q_ptr) {

			currTar_Info->TarSelQ_Tail = q_ptr->Sccb_backlink;
			}

		 if (q_ptr->Sccb_forwardlink != NULL) {
			q_ptr->Sccb_forwardlink->Sccb_backlink = q_ptr->Sccb_backlink;
			}

		 if (q_ptr->Sccb_backlink != NULL) {
			q_ptr->Sccb_backlink->Sccb_forwardlink = q_ptr->Sccb_forwardlink;
			}

		 currTar_Info->TarSelQ_Cnt--;

		 return(TRUE);
		 }

	  else {
		 q_ptr = q_ptr->Sccb_forwardlink;
		 }
	  }


   return(FALSE);

}


/*---------------------------------------------------------------------
 *
 * Function: Utility Update Residual Count
 *
 * Description: Update the XferCnt to the remaining byte count.
 *              If we transferred all the data then just write zero.
 *              If Non-SG transfer then report Total Cnt - Actual Transfer
 *              Cnt.  For SG transfers add the count fields of all
 *              remaining SG elements, as well as any partial remaining
 *              element.
 *
 *---------------------------------------------------------------------*/

void  utilUpdateResidual(PSCCB p_SCCB)
{
   ULONG partial_cnt;
   UINT  sg_index;
#if defined(COMPILER_16_BIT) && !defined(DOS)
   ULONG far *sg_ptr;
#else
   ULONG *sg_ptr;
#endif

   if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {

	  p_SCCB->DataLength = 0x0000;
	  }

   else if (p_SCCB->Sccb_XferState & F_SG_XFER) {

		 partial_cnt = 0x0000;

		 sg_index = p_SCCB->Sccb_sgseg;

#if defined(COMPILER_16_BIT) && !defined(DOS)
		 sg_ptr = (ULONG far *)p_SCCB->DataPointer;
#else
		 sg_ptr = (ULONG *)p_SCCB->DataPointer;
#endif

		 if (p_SCCB->Sccb_SGoffset) {

			partial_cnt = p_SCCB->Sccb_SGoffset;
			sg_index++;
			}

		 while ( ((ULONG)sg_index * (ULONG)SG_ELEMENT_SIZE) <
			p_SCCB->DataLength ) {

			partial_cnt += *(sg_ptr+(sg_index * 2));
			sg_index++;
			}

		 p_SCCB->DataLength = partial_cnt;
		 }

	  else {

		 p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
		 }
}


/*---------------------------------------------------------------------
 *
 * Function: Wait 1 Second
 *
 * Description: Wait for 1 second.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void Wait1Second(USHORT p_port)
#else
void Wait1Second(ULONG p_port)
#endif
{
   UCHAR i;

   for(i=0; i < 4; i++) {

	  Wait(p_port, TO_250ms);

	  if ((RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST))
		 break;

	  if((RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL))
		 break;
	  }
}


/*---------------------------------------------------------------------
 *
 * Function: Wait
 *
 * Description: Wait the desired delay.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void Wait(USHORT p_port, UCHAR p_delay)
#else
void Wait(ULONG p_port, UCHAR p_delay)
#endif
{
   UCHAR old_timer;
   UCHAR green_flag;

   old_timer = RD_HARPOON(p_port+hp_seltimeout);

   green_flag=RD_HARPOON(p_port+hp_clkctrl_0);
   WR_HARPOON(p_port+hp_clkctrl_0, CLKCTRL_DEFAULT);

   WR_HARPOON(p_port+hp_seltimeout,p_delay);
   WRW_HARPOON((p_port+hp_intstat), TIMEOUT);
   WRW_HARPOON((p_port+hp_intena), (default_intena & ~TIMEOUT));


   WR_HARPOON(p_port+hp_portctrl_0,
	  (RD_HARPOON(p_port+hp_portctrl_0) | START_TO));

   while (!(RDW_HARPOON((p_port+hp_intstat)) & TIMEOUT)) {

	  if ((RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST))
		 break;

	  if ((RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL))
		 break;
	  }

   WR_HARPOON(p_port+hp_portctrl_0,
	  (RD_HARPOON(p_port+hp_portctrl_0) & ~START_TO));

   WRW_HARPOON((p_port+hp_intstat), TIMEOUT);
   WRW_HARPOON((p_port+hp_intena), default_intena);

   WR_HARPOON(p_port+hp_clkctrl_0,green_flag);

   WR_HARPOON(p_port+hp_seltimeout,old_timer);
}


/*---------------------------------------------------------------------
 *
 * Function: Enable/Disable Write to EEPROM
 *
 * Description: The EEPROM must first be enabled for writes
 *              A total of 9 clocks are needed.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void utilEEWriteOnOff(USHORT p_port,UCHAR p_mode)
#else
void utilEEWriteOnOff(ULONG p_port,UCHAR p_mode)
#endif
{
   UCHAR ee_value;

   ee_value = (UCHAR)(RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H));

   if (p_mode)

	  utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);

   else


	  utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);

   WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
   WR_HARPOON(p_port+hp_ee_ctrl, ee_value);       /*Turn off Master Select */
}


/*---------------------------------------------------------------------
 *
 * Function: Write EEPROM
 *
 * Description: Write a word to the EEPROM at the specified
 *              address.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void utilEEWrite(USHORT p_port, USHORT ee_data, USHORT ee_addr)
#else
void utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr)
#endif
{

   UCHAR ee_value;
   USHORT i;

   ee_value = (UCHAR)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))|
		   (SEE_MS | SEE_CS));



   utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);


   ee_value |= (SEE_MS + SEE_CS);

   for(i = 0x8000; i != 0; i>>=1) {

	  if (i & ee_data)
	 ee_value |= SEE_DO;
	  else
	 ee_value &= ~SEE_DO;

	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  ee_value |= SEE_CLK;          /* Clock  data! */
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  ee_value &= ~SEE_CLK;
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  }
   ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
   WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS));

   Wait(p_port, TO_10ms);

   WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */
   WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS));       /* Turn off CS */
   WR_HARPOON(p_port+hp_ee_ctrl, ee_value);       /* Turn off Master Select */
}

/*---------------------------------------------------------------------
 *
 * Function: Read EEPROM
 *
 * Description: Read a word from the EEPROM at the desired
 *              address.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
USHORT utilEERead(USHORT p_port, USHORT ee_addr)
#else
USHORT utilEERead(ULONG p_port, USHORT ee_addr)
#endif
{
   USHORT i, ee_data1, ee_data2;

	i = 0;
	ee_data1 = utilEEReadOrg(p_port, ee_addr);
	do
	{
		ee_data2 = utilEEReadOrg(p_port, ee_addr);

		if(ee_data1 == ee_data2)
			return(ee_data1);

		ee_data1 = ee_data2;
		i++;

	}while(i < 4);

	return(ee_data1);
}

/*---------------------------------------------------------------------
 *
 * Function: Read EEPROM Original 
 *
 * Description: Read a word from the EEPROM at the desired
 *              address.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
USHORT utilEEReadOrg(USHORT p_port, USHORT ee_addr)
#else
USHORT utilEEReadOrg(ULONG p_port, USHORT ee_addr)
#endif
{

   UCHAR ee_value;
   USHORT i, ee_data;

   ee_value = (UCHAR)((RD_HARPOON(p_port+hp_ee_ctrl) & (EXT_ARB_ACK | SCSI_TERM_ENA_H))|
		   (SEE_MS | SEE_CS));


   utilEESendCmdAddr(p_port, EE_READ, ee_addr);


   ee_value |= (SEE_MS + SEE_CS);
   ee_data = 0;

   for(i = 1; i <= 16; i++) {

	  ee_value |= SEE_CLK;          /* Clock  data! */
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  ee_value &= ~SEE_CLK;
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);

	  ee_data <<= 1;

	  if (RD_HARPOON(p_port+hp_ee_ctrl) & SEE_DI)
		 ee_data |= 1;
	  }

   ee_value &= ~(SEE_MS + SEE_CS);
   WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
   WR_HARPOON(p_port+hp_ee_ctrl, ee_value);   /*Turn off Master Select */

   return(ee_data);
}


/*---------------------------------------------------------------------
 *
 * Function: Send EE command and Address to the EEPROM
 *
 * Description: Transfers the correct command and sends the address
 *              to the eeprom.
 *
 *---------------------------------------------------------------------*/

#if defined(DOS)
void utilEESendCmdAddr(USHORT p_port, UCHAR ee_cmd, USHORT ee_addr)
#else
void utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr)
#endif
{
   UCHAR ee_value;
   UCHAR narrow_flg;

   USHORT i;


   narrow_flg= (UCHAR)(RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD);


   ee_value = SEE_MS;
   WR_HARPOON(p_port+hp_ee_ctrl, ee_value);

   ee_value |= SEE_CS;                             /* Set CS to EEPROM */
   WR_HARPOON(p_port+hp_ee_ctrl, ee_value);


   for(i = 0x04; i != 0; i>>=1) {

	  if (i & ee_cmd)
		 ee_value |= SEE_DO;
	  else
		 ee_value &= ~SEE_DO;

	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  ee_value |= SEE_CLK;                         /* Clock  data! */
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  ee_value &= ~SEE_CLK;
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  }


   if (narrow_flg)
	  i = 0x0080;

   else
	  i = 0x0200;


   while (i != 0) {

	  if (i & ee_addr)
		 ee_value |= SEE_DO;
	  else
		 ee_value &= ~SEE_DO;

	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  ee_value |= SEE_CLK;                         /* Clock  data! */
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  ee_value &= ~SEE_CLK;
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);
	  WR_HARPOON(p_port+hp_ee_ctrl, ee_value);

	  i >>= 1;
	  }
}

USHORT CalcCrc16(UCHAR buffer[])
{
   USHORT crc=0;
	int i,j;
   USHORT ch;
   for (i=0; i < ID_STRING_LENGTH; i++)
   {
      ch = (USHORT) buffer[i];
	   for(j=0; j < 8; j++)
	   {
		   if ((crc ^ ch) & 1)
            crc = (crc >> 1) ^ CRCMASK;
		   else
            crc >>= 1;
		   ch >>= 1;
	   }
   }
	return(crc);
}

UCHAR CalcLrc(UCHAR buffer[])
{
	int i;
	UCHAR lrc;
	lrc = 0;
	for(i = 0; i < ID_STRING_LENGTH; i++)
		lrc ^= buffer[i];
	return(lrc);
}



/*
  The following inline definitions avoid type conflicts.
*/

static inline unsigned char
FlashPoint__ProbeHostAdapter(FlashPoint_Info_T *FlashPointInfo)
{
  return FlashPoint_ProbeHostAdapter((PSCCBMGR_INFO) FlashPointInfo);
}


static inline FlashPoint_CardHandle_T
FlashPoint__HardwareResetHostAdapter(FlashPoint_Info_T *FlashPointInfo)
{
  return FlashPoint_HardwareResetHostAdapter((PSCCBMGR_INFO) FlashPointInfo);
}

static inline void
FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle)
{
  FlashPoint_ReleaseHostAdapter(CardHandle);
}


static inline void
FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle, BusLogic_CCB_T *CCB)
{
  FlashPoint_StartCCB(CardHandle, (PSCCB) CCB);
}


static inline void
FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle, BusLogic_CCB_T *CCB)
{
  FlashPoint_AbortCCB(CardHandle, (PSCCB) CCB);
}


static inline boolean
FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle)
{
  return FlashPoint_InterruptPending(CardHandle);
}


static inline int
FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
{
  return FlashPoint_HandleInterrupt(CardHandle);
}


#define FlashPoint_ProbeHostAdapter	    FlashPoint__ProbeHostAdapter
#define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
#define FlashPoint_ReleaseHostAdapter	    FlashPoint__ReleaseHostAdapter
#define FlashPoint_StartCCB		    FlashPoint__StartCCB
#define FlashPoint_AbortCCB		    FlashPoint__AbortCCB
#define FlashPoint_InterruptPending	    FlashPoint__InterruptPending
#define FlashPoint_HandleInterrupt	    FlashPoint__HandleInterrupt


/*
  FlashPoint_InquireTargetInfo returns the Synchronous Period, Synchronous
  Offset, and Wide Transfers Active information for TargetID on CardHandle.
*/

void FlashPoint_InquireTargetInfo(FlashPoint_CardHandle_T CardHandle,
				  int TargetID,
				  unsigned char *SynchronousPeriod,
				  unsigned char *SynchronousOffset,
				  unsigned char *WideTransfersActive)
{
  SCCBMGR_TAR_INFO *TargetInfo =
    &sccbMgrTbl[((SCCBCARD *)CardHandle)->cardIndex][TargetID];
  if ((TargetInfo->TarSyncCtrl & SYNC_OFFSET) > 0)
    {
      *SynchronousPeriod = 5 * ((TargetInfo->TarSyncCtrl >> 5) + 1);
      *SynchronousOffset = TargetInfo->TarSyncCtrl & SYNC_OFFSET;
    }
  else
    {
      *SynchronousPeriod = 0;
      *SynchronousOffset = 0;
    }
  *WideTransfersActive = (TargetInfo->TarSyncCtrl & NARROW_SCSI ? 0 : 1);
}


#else  /* CONFIG_SCSI_OMIT_FLASHPOINT */


/*
  Define prototypes for the FlashPoint SCCB Manager Functions.
*/

extern unsigned char FlashPoint_ProbeHostAdapter(FlashPoint_Info_T *);
extern FlashPoint_CardHandle_T
       FlashPoint_HardwareResetHostAdapter(FlashPoint_Info_T *);
extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, BusLogic_CCB_T *);
extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, BusLogic_CCB_T *);
extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
extern void FlashPoint_InquireTargetInfo(FlashPoint_CardHandle_T,
					 int, unsigned char *,
					 unsigned char *, unsigned char *);


#endif /* CONFIG_SCSI_OMIT_FLASHPOINT */
