/*=======================================================/
	  Header file for the Ninja SCSI-3 card

    Ver 1.0.1:
	    yokota@netlab.is.tsukuba.ac.jp <横田 裕思>
    Ver 1.0 : Supports disk change
    Ver 0.4 :
	    yokota@netlab.is.tsukuba.ac.jp <横田 裕思>
    Ver 0.2.1 : Remove unused line by
	    yokota@netlab.is.tsukuba.ac.jp <横田 裕思>
    Ver 0.2   : Adapted for Linux 2.2.x and some fix by
	    y5t0964@students.chiba-u.ac.jp <横田 裕思>
    Ver 0.1   : Original version from Workbit Corp.

	  Copyright (c) 1998 Qvision.
	  All rights reserved.
=========================================================*/

/* $Id: nin_cs.h,v 1.11 2000/06/01 20:14:36 elca Exp $ */

#ifndef  __nin_cs__
#define  __nin_cs__

#define IN
#define OUT

#define USE_DISCONECT
#define USE_INTENTRY
#define RUNPHASE_AUTODIRECTION
#define USE_WRITE_SPECIAL  /* write extended mode */
#define USE_IRQ_MASK 
#define GET_SCSI_INFO
/*#define USE_SLEEP_WAKE*/ /* not yet complete */
/*#define USE_IRQ_HANDLE_PRESENT*/

#define USE_32BITTRANSFER
#define ULTRA /* Ultra SCSI */

/*
#define DBG
#define DBG_PRINT
#define DBG_SHOWCOMMAND
#define PCMCIA_DEBUG
*/

/************************************
 * Some useful macros...
 */
#define Ns3Number(arr) ((int) (sizeof(arr) / sizeof(arr[0])))

/**/
/* Status mask for bus phase.*/
/**/
#define S_PHASE_MASK   ((u_char) 0x3f)

/*
 * SCSI source identifier for host system.
 */
#define SCSI_INITIATOR_ID  7
#define SCSI_IDT_VECTOR    5

#ifdef DBG
	long INT_POLL_SEL = 10;
	long INT_POLL_IRQ = 10;
#else
#       define INT_POLL_SEL 10
#       define INT_POLL_IRQ 10
#endif


/*
//
// Logical Unit states.
//
*/
/*
typedef unsigned char	u_char;
typedef unsigned long	u_long;
*/
#define	IRQCONTROL	0
#define	IRQSTATUS	0
#define	IFSELECT	1
#define	FIFOSTATUS	0x1
#define	INDEXREG	0x2
#define	DATAREG		0x3
#define	FIFODATA	0x4
#define	FIFODATA1	0x5
#define	FIFODATA2	0x6
#define	FIFODATA3	0x7

#define	WFIFODATA	0x4
#define EXTBUSCTRL	0x10
#define CLOCKDIV	0x11

#define TERMPWRCTRL	0x13

#define SCSIIRQMODE	0x15
#define IRQPHASESENCE	0x16
#define TIMERCOUNT	0x17
#define SCSIBUSCTRL	0x18
#define SCSIBUSMON	0x19

#define SETARBIT	0x1A
#define ARBITSTATUS	0x1A

#define PARITYCTRL	0x1B
#define PARITYSTATUS	0x1B

#define COMMANDCTRL	0x1C
#define RESELECTID	0x1C

#define COMMANDDATA	0x1D

#define POINTERCLR	0x1E
#define TRANSFERCOUNT	0x1E

/* #define Reserved3 */
#define TRANSFERMODE	0x20
#define SYNCREG		0x21
#define SCSIDATALATCH	0x22
#define SCSIDATAIN	0x22
#define SCSIDATAWITHACK	0x23
#define SCAMCONTROL	0x24
#define SCAMSTATUS	0x24
#define SCAMDATA	0x25
#define OTHERCONTROL	0x26
#define ACKWIDTH	0x27
#define CLRTESTPNT	0x28
#define ACKCNTLD	0x29
#define REQCNTLD	0x2A
#define HSTCNTLD	0x2B
#define CHECKSUM	0x2C

/*
 * Status Byte
 */
#define	SCSI_OK		0x00
#define	SCSI_CHECK	0x02
#define	SCSI_BUSY	0x08
#define SCSI_INTERM	0x10
#define SCSI_QUEUE_FULL	0x28

/*#endif*/ /*_SCSI_SCSI_ALL_H*/


#define BASE_PORT	0x180
#define NUMBR_PORTS	0x10
#define BASE_WIDTH	0x10
#define SCSI_PORT	0x0

/*
// Input status bit definitions.
*/
#define S_ATN		0x80	/**/
#define S_SELECT	0x40	/**/
#define S_REQUEST	0x20    /* Request line from SCSI bus*/
#define S_ACK		0x10    /* Acknowlege line from SCSI bus*/
#define S_BUSY		0x08    /* Busy line from SCSI bus*/
#define S_CD		0x04    /* Command/Data line from SCSI bus*/
#define S_IO		0x02    /* Input/Output line from SCSI bus*/
#define S_MESSAGE	0x01    /* Message line from SCSI bus*/

/*
// Useful Bus Monitor status combinations.
*/
#define BM_BUS_FREE    0
#define BM_COMMAND     ( S_BUSY | S_CD | S_REQUEST )
#define BM_MESSAGE_IN  ( S_BUSY | S_MESSAGE | S_IO | S_CD | S_REQUEST )
#define BM_MESSAGE_OUT ( S_BUSY | S_MESSAGE | S_CD | S_REQUEST )
#define BM_DATA_IN     ( S_BUSY | S_IO | S_REQUEST )
#define BM_DATA_OUT    ( S_BUSY | S_REQUEST )
#define BM_STATUS      ( S_BUSY | S_IO | S_CD | S_REQUEST )
#define BM_RESELECT    ( S_SELECT | S_IO )

#define BP_COMMAND     ( S_CD )
#define BP_MESSAGE_IN  ( S_MESSAGE | S_IO | S_CD )
#define BP_MESSAGE_OUT ( S_MESSAGE | S_CD )
#define BP_DATA_IN     ( S_IO )
#define BP_DATA_OUT    ( 0 )
#define BP_STATUS      ( S_IO | S_CD )

/*
#define BP_COMMAND     0x04( S_CD )
#define BP_MESSAGE_IN  0x07( S_MESSAGE | S_IO | S_CD )
#define BP_MESSAGE_OUT 0x05( S_MESSAGE | S_CD )
#define BP_DATA_IN     0x02
#define BP_DATA_OUT    0x00
#define BP_STATUS      0x06( S_IO | S_CD )
*/

/**/
/* SCSI Bus Messages*/
/**/

/**/
/* SCSI bus status codes.*/
/**/
/* Status Byte in scsiall.h*/
#define SCSI_CONDITION_MET         0x04
#define SCSI_INTERMEDIATE_COND_MET 0x14
#define SCSI_RESERVATION_CONFLICT  0x18
#define SCSI_COMMAND_TERMINATED    0x22


#define MSG_IDENTIFYFLAG_WITH_DISCON 0xC0

/**/
/* SCSI Extended Message Lengths*/
/**/

#define SCSIMESS_MODIFY_DATA_LENGTH   5
#define SCSIMESS_SYNCH_DATA_LENGTH    3
#define SCSIMESS_WIDE_DATA_LENGTH     2

/**/
/* SCSI Extended Message operation codes*/
/**/

#define SCSIMESS_MODIFY_DATA_POINTER  0X00
#define SCSIMESS_SYNCHRONOUS_DATA_REQ 0X01
#define SCSIMESS_WIDE_DATA_REQUEST    0X03

/* 後で名前を変えよう */
typedef struct _SCSI_EXMSG {
	u_char InitialMessageCode;
	u_char MessageLength;
	u_char MessageType;
	union _EXTENDED_ARGUMENTS {
		struct {
			u_char modifier[4];
		} MODIFY;
		struct {
			u_char TransferPeriod;
			u_char ReqAckOffset;
		} SYNCS;
		struct{
			u_char Width;
		} WIDE;
	}ExArg;
}SCSI_EXMSG, *PSCSI_EXMSG;



/*
BYTE -> u_char
typedef	WORD		char;
typedef	DWORD		long;
PUSHORT -> u_int * 
*/

#define SCSI_IRQ_CONTROL(BASE,VALUE) \
		outb(VALUE,(BASE+IRQCONTROL))

#define SCSI_IRQ_MONITOR(BASE) \
		inb((BASE)+IRQCONTROL)

#define SCSI_IF_SELECT(BASE, VALUE) \
		outb(VALUE,(BASE+IFSELECT))

#define SCSI_FIFO_STATUS(BASE) \
		inb((BASE+FIFOSTATUS))

#define SCSI_READ_FIFO(BASE,BUFFER,COUNT) \
		insb((BASE+FIFODATA), BUFFER, COUNT)

#define SCSI_WRITE_FIFO(BASE,BUFFER,COUNT) \
		outsb((BASE+FIFODATA), BUFFER, COUNT)

#define SCSI_READ_FIFOW(BASE,BUFFER,COUNT) \
	insw((BASE+WFIFODATA), BUFFER, (COUNT >> 1))

#define SCSI_WRITE_FIFOW(BASE,BUFFER,COUNT) \
	outsw((BASE+WFIFODATA ), BUFFER, (COUNT >> 1))

#define SCSI_READ_FIFOD(BASE,BUFFER,COUNT) \
	insl((BASE+WFIFODATA), BUFFER, (COUNT >> 2))

#define SCSI_WRITE_FIFOD(BASE,BUFFER,COUNT) \
	outsl((BASE+WFIFODATA ), BUFFER, (COUNT >> 2))

#define SCSI_READ(ChipAddr,Register) ( \
	outb(Register,ChipAddr+INDEXREG),\
	inb(ChipAddr+DATAREG)\
)

#define SCSI_WRITE(ChipAddr,Register,Value) { \
	outb(Register,ChipAddr+INDEXREG),\
	outb(Value,ChipAddr+DATAREG);\
}

#define READ_XFER_CNT 512
#define WRITE_BURST_CNT 512	/*64*/
#define WRITE_SPOT_CNT 64

#define	ASYNCHRONOUS_OFFSET 0
#define	ASYNCHRONOUS_PERIOD 0
#define SYNCHRONOUS_OFFSET 15

#ifdef ULTRA
#define SYNCHRONOUS_PERIOD 0x0c
#else
#define SYNCHRONOUS_PERIOD 0x19
#endif

#define SYNCHRONOUS_PERIOD_10M 0x19
#define SYNCHRONOUS_PERIOD_20M 0x0c

/* Various timeout values (in microseconds).*/

#define REQUEST_SPIN_WAIT   40000	/* Wait for target to assert REQUEST*/
#define RESET_HOLD_TIME     25		/* Time to hold RESET line to reset bus*/
#define RESET_RECOVER_TIME	2500000
#define BUS_FREE_DELAY      100000  /* Wait for BUS_FREE condition*/


typedef struct _SYNC_TABLE {
	u_char	StartPeriod;
	u_char	EndPeriod;
	u_char	TransferPeriod;
	u_char	AckWidth;
} SYNC_TABLE, *PSYNC_TABLE;

/* for PC CARD*/
typedef struct _PWRENTRY {
	u_char	PowerLevel;
	u_char	ValidSignals;
} PWRENTRY;

typedef struct _ACHARTBL {
	char	AdpCaps;
	long	ActiveHigh;
	long	ActiveLow;
} ACHARTBL;

typedef struct _AINQADAPTOR {
	char	wBufferLength;
	char	wDataLength;
	ACHARTBL CharTable;
	char	wNumPwrEntries;
	PWRENTRY PwrEntry;
} AINQADAPTOR;

typedef struct _SG_TABLE {
	u_long	BlockCount;
	u_long	BufferAddress;
} SG_TABLE, *PSG_TABLE;

typedef struct _FIFO_TEST {
	u_char	XferMode;
	u_char	Rate;
} FIFO_TEST;
typedef FIFO_TEST *PFIFO_TEST;
typedef struct _FAST_MODE {
	u_char	XferMode;
	u_char	Rate;
	u_char	PcicTiming;
	u_char	MemorySpeed;
} FAST_MODE;
typedef FAST_MODE *PFAST_MODE;


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

/*
// Logical Unit states.
*/
typedef enum _SCSI_STATE {
	SC_UNDETERMINED,
	SC_SELECT,
	SC_COMMAND,
	SC_DATA,
	SC_STATUS,
	SC_MSG_IN,
	SC_MSG_OUT,
	SC_COMPLETE,
	SC_COMPLETE_OK,
	SC_BUSFREE,
	SC_DISCONNECT,
	SC_RESELECT
} SCSI_STATE, *PSCSI_STATE;
/**/
typedef	struct _IRQ_STATUS {		/* #0*/
	u_char	ScsiIrqStatus		: 1;
	u_char	ExtIrqStatus		: 1;
	u_char	TimerIrqStatus		: 1;
	u_char	FifoIrqStatus		: 1;
	u_char	ScsiIrqMask		: 1;
	u_char	ExtIrqMask		: 1;
	u_char	TimerIrqMask		: 1;
	u_char	FifoIrqMask		: 1;
} IRQ_STATUS, *PIRQ_STATUS;

typedef	struct _IRQ_CONTROLP {		/* #0*/
	u_char	ReselctIrqClear		: 1;
	u_char	PhaseChgIrqClear	: 1;
	u_char	TimerIrqClear		: 1;
	u_char	FifoIrqClear		: 1;
	u_char	ScsiIrqMask		: 1;
	u_char	ExtIrqMask		: 1;
	u_char	TimerIrqMask		: 1;
	u_char	FifoIrqMask		: 1;
} IRQ_CONTROLP, *PIRQ_CONTROLP;

typedef	struct _IF_SELECT {		/* #1*/ /* spec シートの記述と違う? */
	u_char	IFSelect		: 1;    /* この記述が正しいとすると */
	u_char	Reserved2		: 1;    /* spec シートが間違って */
	u_char	RegSelect		: 1;    /* いる事になる */
	u_char	Reserved3		: 5;
} IF_SELECT, *PIF_SELECT;

typedef	struct _FIFO_STATUS {		/* #1*/
	u_char	ChipRev			: 4;
	u_char	ChipId			: 3;
	u_char	FifoFullEmpty		: 1;
} FIFO_STATUS, *PFIFO_STATUS;

#if 0
typedef	struct _EXT_BUS_CONTROL {      	/* index 10h*/
	u_char	Reserved0		: 4;
	u_char	IOMapConfigration	: 1;
	u_char	ExrdyContrl		: 1;
	u_char	IrqLevel		: 1;
	u_char	Reserved1		: 1;
} EXT_BUS_CONTROL, *PEXT_BUS_CONTROL;
#endif

typedef	struct CLOCK_DIV {		/* index 11h*/
	u_char	ClkDivider		: 2;
	u_char	Reserved6		: 6;
} CLOCK_DIV, *PCLOCK_DIV;

typedef	struct _TermPwrControl {	/* index 13*/
	u_char	TermPowerOn		: 1;
	u_char	Reserved7		: 7;
} TermPwrControl, *PTermPwrControl;

typedef	struct _SCSI_IRQ_MODE {		/* index 15 - rw*/
	u_char	ScsiPhaseChangeEi	: 1;
	u_char	Reserved8		: 3;
	u_char	ReselectIrqEi		: 1;
	u_char	FifoIrqEi		: 1;
	u_char	ScsiResetIrqEi		: 1;
	u_char	Reserved75		: 1;
} SCSI_IRQ_MODE, *PSCSI_IRQ_MODE;

typedef	struct _IRQ_PHASE_SENSE {	/* index 16*/
	u_char	LatchMSG		: 1;
	u_char	LatchI_O		: 1;
	u_char	LatchC_D		: 1;
	u_char	LatchBusFree		: 1;
	u_char	PhaseChgIrq		: 1;
	u_char	ReselectIrq		: 1;
	u_char	FifoIrq			: 1;
	u_char	ScsiResetIrq		: 1;
} IRQ_PHASE_SENSE, *PIRQ_PHASE_SENSE;

typedef	struct SCSI_BUS_CONTROL {	/* index 18 - rw*/
	u_char	ScsiSel			: 1;
	u_char	ScsiRst			: 1;
	u_char	ScsiDataOutEnb		: 1;
	u_char	ScsiATN			: 1;
	u_char	ScsiACK			: 1;
	u_char	ScsiBSY			: 1;
	u_char	AutoDirection		: 1;
	u_char	AckEnb			: 1;
} SCSI_BUS_CONTROL, *PSCSI_BUS_CONTROL;

typedef	struct _SCSI_BUS_MONITOR {      /* index 19 - r */
	u_char	Scsi_MSG		: 1;
	u_char	Scsi_I_O		: 1;
	u_char	Scsi_C_D	        : 1;
	u_char	Scsi_BSY		: 1;
	u_char	Scsi_ACK		: 1;
	u_char	Scsi_REQ		: 1;
	u_char	Scsi_SEL		: 1;
	u_char	Scsi_ATN		: 1;
} SCSI_BUS_MONITOR, *PSCSI_BUS_MONITOR;

typedef	struct _SET_ARBIT {		/* index 1a - w */
	u_char	ArbitGo			: 1;
	u_char	ArbitFlagClear		: 1;
	u_char	Reserved10		: 6;
} SET_ARBIT,*PSET_ARBIT;

typedef	struct _ARBIT_STATUS	{	/* index 1a - r */
	u_char	ArbitGoStatus		: 1;
	u_char	ArbitWin		: 1;
	u_char	ArbitFail		: 1;
	u_char	ReselectFlag		: 1;
	u_char	Reserved11		: 4;
} ARBIT_STATUS, *PARBIT_STATUS;

typedef	struct _PARITY_CONTROL {	/* index 1b*/
	u_char	ParityCheckEnable	: 1;
	u_char	ParityErrorClear	: 1;
	u_char	Reserved12		: 6;
} PARITY_CONTROL, *PPARITY_CONTROL;

typedef	struct _PARITY_STATUS {		/* index 1b*/
	u_char	Reserved15		: 1; /* same as PARITY_CONTROL*/
	u_char	ParityError		: 1;
	u_char	Reserved14		: 2;
	u_char	ReadSource		: 2;
	u_char	Reserved13		: 2;
} PARITY_STATUS, *PPARITY_STATUS;

typedef	struct _COMMAND_CONTROL {	/* index 1c - w */
	u_char	ClrCommandPointer	: 1;
	u_char	AutoCommandGo		: 1;
	u_char	Reserved16		: 6;
} COMMAND_CONTROL, *PCOMMAND_CONTROL;

typedef	struct _POINTER_CLEAR {		/* index 1e - w */
	u_char	PointerClear		: 1;
	u_char	AckCounterClear		: 1;
	u_char	ReqCounterClear		: 1;
	u_char	HostCounterClear	: 1;
	u_char	ReadSourceSet		: 2;
	u_char	Reserved17		: 2;
} POINTER_CLEAR, *PPOINTER_CLEAR;

typedef	struct _TRANSFER_MODE {		/* index 20*/
	u_char	MemMap8			: 1;
	u_char	MemMap16_32		: 1;
	u_char	AdrData24		: 1;
	u_char	AdrData32		: 1;
	u_char	IO8			: 1;
	u_char	IO16_32			: 1;
	u_char	TransferGo		: 1;
	u_char	FifoTest_Braind		: 1;
} TRANSFER_MODE, *PTRANSFER_MODE;

typedef	struct _SYNC_REG	{	 /* index 21*/
	u_char	SyncOffset		 : 4;
	u_char	SyncPeriod		 : 4;
} SYNC_REG, *PSYNC_REG;


typedef	struct _SCAM_CONTROL {		 /* index 24*/
	u_char	ScamMSG			 : 1;
	u_char	ScamI_O			 : 1;
	u_char	ScamC_D			 : 1;
	u_char	ScamBSY			 : 1;
	u_char	ScamSEL			 : 1;
	u_char	ScamXferOn		 : 1;
	u_char	Reserved18		 : 2;
} SCAM_CONTROL, *PSCAM_CONTROL;

typedef	struct _OTHER_CONTROL {		/* index 26*/
	u_char	TplRomWriteEnable	: 1;
	u_char	TermPwrOut		: 1;
	u_char	TermPwrSence		: 1;
	u_char	Reserved19		: 5;
} OTHER_CONTROL, *POTHER_CONTROL;

typedef	struct _ACK_WIDTH {		/* index 27*/
	u_char	AckPulse		: 2;
	u_char	Reserved20		: 6;
} ACK_WIDTH, *PACK_WIDTH;

typedef	struct _CHECK_SUM_CONTROL {	/* index 2c*/
	u_char	CheckSumClear		: 1;
	u_char	ReadPointerClear	: 1;
	u_char	Reserved21		: 6;
} CHECK_SUM_CONTROL, *PCHECK_SUM_CONTROL;


/*
//define adapter type
*/
#define OPT_NON_DISCONECT	0x01
#define OPT_TUNEUP_DI		0x02
#define OPT_PCIC_SPEED		0x04
#define OPT_MMIO_SPEED		0x08
#define OPT_NO_ATN		0x10

/*
// specific per target controller information.
*/
typedef struct _SPECIFIC_TARGET_EXTENSION {
	unsigned char TargetFlags;
	unsigned char SynchronousPeriod;
	unsigned char SynchronousOffset;
	unsigned char AckWidth;
} SPECIFIC_TARGET_EXTENSION, *PSPECIFIC_TARGET_EXTENSION;


/*
// Define target controller specific flags.
*/
#define PD_SYNCHRONOUS_NEGOTIATION_DONE    0x0001
#define PD_DO_NOT_NEGOTIATE                0x0002
#define PD_SYNCHRONOUS_TRANSFER_SENT       0X0004

#define PD_SYNCHRONOUS_TRANSFER_SENT       0X0004
/**/
#ifdef ULTRA
static SYNC_TABLE SyncTable[] = {{0x0c,0x0c,0x1,0},	/* 20MB  50ns*/
				 {0x19,0x19,0x3,1}, 	/* 10MB  100ns*/
				 {0x1a,0x25,0x5,2},	/* 7.5MB 150ns*/
				 {0x26,0x32,0x7,3}};	/* 5MB   200ns*/
#define SYNC_TABLE_MAX 4
#else
 static SYNC_TABLE SyncTable[] = {{0x19,0x19,0x1,0}, 	/* 10MB  100ns*/
				  {0x1a,0x25,0x2,0},	/* 7.5MB 150ns*/
				  {0x26,0x32,0x3,1}};	/* 5MB   200ns*/
#define SYNC_TABLE_MAX 3
#endif


/* ----- OREASAMA ---------------------------------------------------*/
#ifdef DBG_PRINT
/*
 //
 // Globals and externals used for debugging.
 //

 //
 // Ns3Debug affects which debug prints are enabled:
 //
 //     0x001   Arbitration and selection
 //     0x002   Command, status
 //     0x004   Data transfer
 //     0x008   Message in
 //     0x010   Miniport entry points and completion
 //     0x020   Initialization and interrupt
 //     0x040   StatusCheck and WaitForRequest
 //     0x080   Control register manipulation
 //     0x100   Completion
 //     0x200   Phase info
 //     0x400   Temporary
 //     0x800   Panic
 //
*/
	u_long Ns3Debug = ( 0xfff );

/*	u_long Ns3Debug = ( 0x0 ); */
#       define Ns3DebugPrint(MASK, ARGS)\
	if (MASK & Ns3Debug) {\
		printk ARGS;\
	}

#else
#       define Ns3DebugPrint(MASK, ARGS)\
	{\
	}
#endif /* DBG_PRINT */


/*
  typedef int boolean;
  scsiconf.h
*/
typedef	int boolean;
/*
//
// Logical Unit extension
//
*/
typedef struct _SPECIFIC_LU_EXTENSION {
	SCSI_STATE	   LuState;		/* State information.*/
	char*		   SavedDataPointer;	/* Current data pointer.*/
	unsigned long 	   SavedDataLength;	/* Current data lenght.*/
	Scsi_Cmnd	   *ActiveCommand;    	/* Active Srb for this LUN.*/
	unsigned long	   PhaseWaitCounter;
	unsigned long	   TransferedLength;
	unsigned long	   AckCounter;
	unsigned long	   HostCounter;

	void	(*pXferRead)(int, char* Buffer,	unsigned long Length);
	void	(*pXferWrite)(int, char* Buffer, unsigned long Length);

	unsigned long				SG_Count;
} SPECIFIC_LU_EXTENSION, *PSPECIFIC_LU_EXTENSION;


/**/
static	FIFO_TEST DefaultOk[] = {{ 0x4, 0},	/* 24bit         */
				 { 0x2, 0},	/* Mem32         */
				 {0x20, 0},	/* IO32          */
				 { 0x1, 0},	/* MEM8          */
				 {0x10, 0},	/* IO8           */
				 {   0, 0}}; 	/* test priority */

/*
 * struct  nin_softc;
 * typedef nin_softc *pnin_softc;
 *
 * Device extension
 *
 */
/*
struct  _SPECIFIC_DEVICE_EXTENSION;
typedef struct _SPECIFIC_DEVICE_EXTENSION nin_softc, *pnin_softc;
*/
typedef struct _SPECIFIC_DEVICE_EXTENSION {
	SCSI_STATE	ScsiState;
	char*		CurDataPointer;   /* Current pointer for active LUN.*/
	unsigned long   CurDataLength;    /* Bytes left to xfer to this LUN.*/
	PSPECIFIC_LU_EXTENSION  ActiveUnit;  /* Currently active LUN.*/
	/*unsigned char	PathId;*/
	boolean		InterruptPending;   /* Waiting for interrupt.*/
	boolean		DmaPending;         /* Waiting for DMA setup.*/
	unsigned char	DeviceType[8];	    /* inquiry data save*/
	SPECIFIC_TARGET_EXTENSION TargetState[8];
	unsigned char	TimerCycle;
	unsigned char	TimerCount;
	unsigned char	TransferMode;
	/*boolean		Write24BitEnable;*/
	unsigned char	MessageBuffer[8];
	unsigned long	MessageCount;

	/*unsigned long	SmitBuffer;*/
	unsigned char	TargetId;
	unsigned char	TargetLun;	     /* LUN for reselection*/
	unsigned char	IrqMaskData;
	unsigned char	ScsiPrePhase;

	u_short		AdapterOption;

	void	(*pXferRead)(int, char* Buffer,	unsigned long Length);
	void	(*pXferWrite)(int, char* Buffer, unsigned long Length);

	FIFO_TEST      CanTransMode[Ns3Number(DefaultOk)]; /* can transfer-mode*/
	boolean	       IntWait;		     /* wait in int-routine?*/
	boolean	       ScsiCable;	  /* funny cable ? or FifoTest all NG*/
	unsigned long  SSEntry;		  /* Socket Service Entry Point*/
	unsigned char  WindowHandle;	  /* Socket memory-win-handle*/
#ifdef ULTRA
	unsigned char  SynchronousPeriod;
#endif

	int	       BaseAddress;        /* Port address of adapter.*/
	int            NumAddress;         /* Number of ports */
	/*int	       unit;*/
	int            IrqNumber;          /* IRQ number */
	int            HostId;             /* Host SCSI ID = 7 */
	int            ChipID;
	int            ChipRev;
} nin_softc, *pnin_softc;


static boolean Ns3Initialize(void);
static u_char Ns3FifoTest(IN PFIFO_TEST pTestMode);
static void Ns3ResetScsiBus( pnin_softc DevExt );

static PSPECIFIC_LU_EXTENSION ScsiPortGetLogicalUnit(unsigned char TargetId,unsigned char Lun);
static void ScsiPortFreeLogicalUnit(unsigned char TargetId,unsigned char Lun);
static void Ns3StartExecution(IN pnin_softc	         DevExt,
			      IN PSPECIFIC_LU_EXTENSION LuExtension,
			      IN Scsi_Cmnd              *Srb );

/*static void Ns3IrqPolling ( void );*/

static boolean Ns3Select( IN pnin_softc DevExt,
		      Scsi_Cmnd	 *srb);
static void Ns3NotifyCompletion( IN pnin_softc DevExt,
				 IN boolean NextReq );
static void Ns3SetTransferMode( IN pnin_softc DevExt );
static void Ns3RunPhase( IN pnin_softc DevExt,
			 IN IRQ_PHASE_SENSE IrqPhase );
static void Ns3DataInPhase( IN pnin_softc DevExt );
static void Ns3DataOutPhase( IN pnin_softc DevExt );

static void Ns3SendCDB( IN pnin_softc DevExt );
static void Ns3MessageOut( IN pnin_softc DevExt );
static void Ns3MessageIn( IN pnin_softc DevExt );
static void Ns3Status( IN pnin_softc DevExt );
static boolean Ns3WaitForAckOff( pnin_softc DevExt );
static boolean Ns3WaitForReqOff( pnin_softc DevExt );


/*static void mmio32_datain  (int, char*  ,	u_long );
static void mmio32_dataout (IN int, char*  ,	u_long );
static void mmio24_dataout (IN int, char*  ,	u_long );
static void mmio8_datain   (IN int, char*  ,	u_long );
static void mmio8_dataout  (IN int, char*  ,	u_long );*/
static void pio8_datain    (IN int, char*  ,	u_long );
static void pio8_dataout   (IN int, char*  ,	u_long );
static void pio32_datain   (IN int DevExt ,
			    char*  Buffer,
			    u_long Length );
static void pio32_dataout  (IN int DevExt ,
			    char*  Buffer,
			    u_long Length );


static u_long read_ack_count ( IN pnin_softc DevExt );
static void Ns3BurstRead ( IN pnin_softc DevExt );
static void Ns3BurstWrite( IN pnin_softc DevExt );
static void Ns3SpotRead  ( IN pnin_softc DevExt );
static void Ns3SpotWrite ( IN pnin_softc DevExt );
static void Ns3SlowRead  ( IN pnin_softc DevExt );
static void Ns3SlowWrite ( IN pnin_softc DevExt );

static boolean Ns3ProcessReselection( IN pnin_softc DevExt );
static boolean	Ns3MessageDecode( IN pnin_softc DevExt );

static boolean Ns3DecodeSynchronousRequest(IN pnin_softc DevExt,
					   PSPECIFIC_TARGET_EXTENSION TargetState,
					   IN u_char TargetID,
					   IN boolean ResponseExpected  );

#ifdef DBG_SHOWCOMMAND
static void show_command(Scsi_Cmnd *ptr);
#endif /* DBG_SHOWCOMMAND */

/*aha152x.h*/
enum {
	not_issued   = 0x0001,
	in_selection = 0x0002,
	disconnected = 0x0004,
	aborted      = 0x0008,
	sent_ident   = 0x0010,
	in_other     = 0x0020,
	in_sync      = 0x0040,
	sync_ok      = 0x0080,
};

/* bits and bitmasks to ports */

/* SCSI sequence control */
#define TEMODEO      0x80
#define ENSELO       0x40
#define ENSELI       0x20
#define ENRESELI     0x10
#define ENAUTOATNO   0x08
#define ENAUTOATNI   0x04
#define ENAUTOATNP   0x02
#define SCSIRSTO     0x01

/* SCSI transfer control 0 */
#define SCSIEN       0x80
#define DMAEN        0x40
#define CH1          0x20
#define CLRSTCNT     0x10
#define SPIOEN       0x08
#define CLRCH1       0x02

/* SCSI transfer control 1 */
#define BITBUCKET    0x80
#define SWRAPEN      0x40
#define ENSPCHK      0x20
#define STIMESEL     0x18    /* mask */
#define STIMESEL_    3
#define ENSTIMER     0x04
#define BYTEALIGN    0x02

/* SCSI signal IN */
#define CDI          0x80
#define IOI          0x40
#define MSGI         0x20
#define ATNI         0x10
#define SELI         0x08
#define BSYI         0x04
#define REQI         0x02
#define ACKI         0x01

/* SCSI Phases */
#define P_MASK       (MSGI|CDI|IOI)
#define P_DATAO      (0)
#define P_DATAI      (IOI)
#define P_CMD        (CDI)
#define P_STATUS     (CDI|IOI)
#define P_MSGO       (MSGI|CDI)
#define P_MSGI       (MSGI|CDI|IOI)

/* SCSI signal OUT */
#define CDO          0x80
#define IOO          0x40
#define MSGO         0x20
#define ATNO         0x10
#define SELO         0x08
#define BSYO         0x04
#define REQO         0x02
#define ACKO         0x01

/* SCSI rate control */
#define SXFR         0x70    /* mask */
#define SXFR_        4
#define SOFS         0x0f    /* mask */

/* SCSI ID */
#define OID          0x70
#define OID_         4
#define TID          0x07

/* SCSI interrupt status */
#define TARGET       0x80
#define SELDO        0x40
#define SELDI        0x20
#define SELINGO      0x10
#define SWRAP        0x08
#define SDONE        0x04
#define SPIORDY      0x02
#define DMADONE      0x01

#define SETSDONE     0x80
#define CLRSELDO     0x40
#define CLRSELDI     0x20
#define CLRSELINGO   0x10
#define CLRSWRAP     0x08
#define CLRSDONE     0x04
#define CLRSPIORDY   0x02
#define CLRDMADONE   0x01

/* SCSI status 1 */
#define SELTO        0x80
#define ATNTARG      0x40
#define SCSIRSTI     0x20
#define PHASEMIS     0x10
#define BUSFREE      0x08
#define SCSIPERR     0x04
#define PHASECHG     0x02
#define REQINIT      0x01

#define CLRSELTIMO   0x80
#define CLRATNO      0x40
#define CLRSCSIRSTI  0x20
#define CLRBUSFREE   0x08
#define CLRSCSIPERR  0x04
#define CLRPHASECHG  0x02
#define CLRREQINIT   0x01

/* SCSI status 2 */
#define SOFFSET      0x20
#define SEMPTY       0x10
#define SFULL        0x08
#define SFCNT        0x07    /* mask */

/* SCSI status 3 */
#define SCSICNT      0xf0    /* mask */
#define SCSICNT_     4
#define OFFCNT       0x0f    /* mask */

/* SCSI TEST control */
#define SCTESTU      0x08
#define SCTESTD      0x04
#define STCTEST      0x01

/* SCSI status 4 */
#define SYNCERR      0x04
#define FWERR        0x02
#define FRERR        0x01

#define CLRSYNCERR   0x04
#define CLRFWERR     0x02
#define CLRFRERR     0x01

/* SCSI interrupt mode 0 */
#define ENSELDO      0x40
#define ENSELDI      0x20
#define ENSELINGO    0x10
#define ENSWRAP      0x08
#define ENSDONE      0x04
#define ENSPIORDY    0x02
#define ENDMADONE    0x01

/* SCSI interrupt mode 1 */
#define ENSELTIMO    0x80
#define ENATNTARG    0x40
#define ENSCSIRST    0x20
#define ENPHASEMIS   0x10
#define ENBUSFREE    0x08
#define ENSCSIPERR   0x04
#define ENPHASECHG   0x02
#define ENREQINIT    0x01

/*aha152x.h*/


/* scsi_message.h */
/* Messages (1 byte) */		     /* I/T (M)andatory or (O)ptional */
#define MSG_CMDCOMPLETE		0x00 /* M/M */
#define MSG_EXTENDED		0x01 /* O/O */
#define MSG_SAVEDATAPOINTER	0x02 /* O/O */
#define MSG_RESTOREPOINTERS	0x03 /* O/O */
#define MSG_DISCONNECT		0x04 /* O/O */
#define MSG_INITIATOR_DET_ERR	0x05 /* M/M */
#define MSG_ABORT		0x06 /* O/M */
#define MSG_MESSAGE_REJECT	0x07 /* M/M */
#define MSG_NOOP		0x08 /* M/M */
#define MSG_PARITY_ERROR	0x09 /* M/M */
#define MSG_LINK_CMD_COMPLETE	0x0a /* O/O */
#define MSG_LINK_CMD_COMPLETEF	0x0b /* O/O */
#define MSG_BUS_DEV_RESET	0x0c /* O/M */
#define MSG_ABORT_TAG		0x0d /* O/O */
#define MSG_CLEAR_QUEUE		0x0e /* O/O */
#define MSG_INIT_RECOVERY	0x0f /* O/O */
#define MSG_REL_RECOVERY	0x10 /* O/O */
#define MSG_TERM_IO_PROC	0x11 /* O/O */

/* Messages (2 byte) */
#define MSG_SIMPLE_Q_TAG	0x20 /* O/O */
#define MSG_HEAD_OF_Q_TAG	0x21 /* O/O */
#define MSG_ORDERED_Q_TAG	0x22 /* O/O */
#define MSG_IGN_WIDE_RESIDUE	0x23 /* O/O */

/* Identify message */		     /* M/M */	
#define MSG_IDENTIFYFLAG	0x80 
#define MSG_IDENTIFY(lun, disc)	(((disc) ? 0xc0 : MSG_IDENTIFYFLAG) | (lun))
#define MSG_ISIDENTIFY(m)	((m) & MSG_IDENTIFYFLAG)

/* Extended messages (opcode and length) */
#define MSG_EXT_SDTR		0x01
#define MSG_EXT_SDTR_LEN	0x03

#define MSG_EXT_WDTR		0x03
#define MSG_EXT_WDTR_LEN	0x02

/* scsi_message.h */
static void ninintr(void);
static void Ns3ResetScsiBus( pnin_softc DevExt );
static boolean Ns3Initialize(void);

#endif  /*__nin_cs__*/
