xref: /openbmc/linux/drivers/scsi/FlashPoint.c (revision df561f6688fef775baa341a0f5d960becd248b11)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds 
31da177e4SLinus Torvalds   FlashPoint.c -- FlashPoint SCCB Manager for Linux
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds   This file contains the FlashPoint SCCB Manager from BusLogic's FlashPoint
61da177e4SLinus Torvalds   Driver Developer's Kit, with minor modifications by Leonard N. Zubkoff for
71da177e4SLinus Torvalds   Linux compatibility.  It was provided by BusLogic in the form of 16 separate
81da177e4SLinus Torvalds   source files, which would have unnecessarily cluttered the scsi directory, so
91da177e4SLinus Torvalds   the individual files have been combined into this single file.
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
121da177e4SLinus Torvalds 
131da177e4SLinus Torvalds   This file is available under both the GNU General Public License
141da177e4SLinus Torvalds   and a BSD-style copyright; see LICENSE.FlashPoint for details.
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds */
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds 
1978b4b05dSMatthew Wilcox #ifdef CONFIG_SCSI_FLASHPOINT
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds #define MAX_CARDS	8
221da177e4SLinus Torvalds #undef BUSTYPE_PCI
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds #define CRCMASK	0xA001
251da177e4SLinus Torvalds 
261da177e4SLinus Torvalds #define FAILURE         0xFFFFFFFFL
271da177e4SLinus Torvalds 
2869eb2ea4SAlexey Dobriyan struct sccb;
2969eb2ea4SAlexey Dobriyan typedef void (*CALL_BK_FN) (struct sccb *);
301da177e4SLinus Torvalds 
317f101662SAlexey Dobriyan struct sccb_mgr_info {
32391e2f25SKhalid Aziz 	u32 si_baseaddr;
33db038cf8SAlexey Dobriyan 	unsigned char si_present;
34db038cf8SAlexey Dobriyan 	unsigned char si_intvect;
35db038cf8SAlexey Dobriyan 	unsigned char si_id;
36db038cf8SAlexey Dobriyan 	unsigned char si_lun;
37391e2f25SKhalid Aziz 	u16 si_fw_revision;
38391e2f25SKhalid Aziz 	u16 si_per_targ_init_sync;
39391e2f25SKhalid Aziz 	u16 si_per_targ_fast_nego;
40391e2f25SKhalid Aziz 	u16 si_per_targ_ultra_nego;
41391e2f25SKhalid Aziz 	u16 si_per_targ_no_disc;
42391e2f25SKhalid Aziz 	u16 si_per_targ_wide_nego;
43391e2f25SKhalid Aziz 	u16 si_flags;
44db038cf8SAlexey Dobriyan 	unsigned char si_card_family;
45db038cf8SAlexey Dobriyan 	unsigned char si_bustype;
46db038cf8SAlexey Dobriyan 	unsigned char si_card_model[3];
47db038cf8SAlexey Dobriyan 	unsigned char si_relative_cardnum;
48db038cf8SAlexey Dobriyan 	unsigned char si_reserved[4];
49391e2f25SKhalid Aziz 	u32 si_OS_reserved;
50db038cf8SAlexey Dobriyan 	unsigned char si_XlatInfo[4];
51391e2f25SKhalid Aziz 	u32 si_reserved2[5];
52391e2f25SKhalid Aziz 	u32 si_secondary_range;
537f101662SAlexey Dobriyan };
541da177e4SLinus Torvalds 
551da177e4SLinus Torvalds #define SCSI_PARITY_ENA		  0x0001
561da177e4SLinus Torvalds #define LOW_BYTE_TERM		  0x0010
571da177e4SLinus Torvalds #define HIGH_BYTE_TERM		  0x0020
581da177e4SLinus Torvalds #define BUSTYPE_PCI	  0x3
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds #define SUPPORT_16TAR_32LUN	  0x0002
611da177e4SLinus Torvalds #define SOFT_RESET		  0x0004
621da177e4SLinus Torvalds #define EXTENDED_TRANSLATION	  0x0008
631da177e4SLinus Torvalds #define POST_ALL_UNDERRRUNS	  0x0040
641da177e4SLinus Torvalds #define FLAG_SCAM_ENABLED	  0x0080
651da177e4SLinus Torvalds #define FLAG_SCAM_LEVEL2	  0x0100
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds #define HARPOON_FAMILY        0x02
681da177e4SLinus Torvalds 
6932357988SAlexey Dobriyan /* SCCB struct used for both SCCB and UCB manager compiles!
701da177e4SLinus Torvalds  * The UCB Manager treats the SCCB as it's 'native hardware structure'
711da177e4SLinus Torvalds  */
721da177e4SLinus Torvalds 
73391e2f25SKhalid Aziz /*#pragma pack(1)*/
7469eb2ea4SAlexey Dobriyan struct sccb {
75db038cf8SAlexey Dobriyan 	unsigned char OperationCode;
76db038cf8SAlexey Dobriyan 	unsigned char ControlByte;
77db038cf8SAlexey Dobriyan 	unsigned char CdbLength;
78db038cf8SAlexey Dobriyan 	unsigned char RequestSenseLength;
79391e2f25SKhalid Aziz 	u32 DataLength;
80391e2f25SKhalid Aziz 	void *DataPointer;
81db038cf8SAlexey Dobriyan 	unsigned char CcbRes[2];
82db038cf8SAlexey Dobriyan 	unsigned char HostStatus;
83db038cf8SAlexey Dobriyan 	unsigned char TargetStatus;
84db038cf8SAlexey Dobriyan 	unsigned char TargID;
85db038cf8SAlexey Dobriyan 	unsigned char Lun;
86db038cf8SAlexey Dobriyan 	unsigned char Cdb[12];
87db038cf8SAlexey Dobriyan 	unsigned char CcbRes1;
88db038cf8SAlexey Dobriyan 	unsigned char Reserved1;
89391e2f25SKhalid Aziz 	u32 Reserved2;
90391e2f25SKhalid Aziz 	u32 SensePointer;
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds 	CALL_BK_FN SccbCallback;	/* VOID (*SccbCallback)(); */
93391e2f25SKhalid Aziz 	u32 SccbIOPort;			/* Identifies board base port */
94db038cf8SAlexey Dobriyan 	unsigned char SccbStatus;
95db038cf8SAlexey Dobriyan 	unsigned char SCCBRes2;
96391e2f25SKhalid Aziz 	u16 SccbOSFlags;
971da177e4SLinus Torvalds 
98391e2f25SKhalid Aziz 	u32 Sccb_XferCnt;	/* actual transfer count */
99391e2f25SKhalid Aziz 	u32 Sccb_ATC;
100391e2f25SKhalid Aziz 	u32 SccbVirtDataPtr;	/* virtual addr for OS/2 */
101391e2f25SKhalid Aziz 	u32 Sccb_res1;
102391e2f25SKhalid Aziz 	u16 Sccb_MGRFlags;
103391e2f25SKhalid Aziz 	u16 Sccb_sgseg;
104db038cf8SAlexey Dobriyan 	unsigned char Sccb_scsimsg;	/* identify msg for selection */
105db038cf8SAlexey Dobriyan 	unsigned char Sccb_tag;
106db038cf8SAlexey Dobriyan 	unsigned char Sccb_scsistat;
107db038cf8SAlexey Dobriyan 	unsigned char Sccb_idmsg;	/* image of last msg in */
10869eb2ea4SAlexey Dobriyan 	struct sccb *Sccb_forwardlink;
10969eb2ea4SAlexey Dobriyan 	struct sccb *Sccb_backlink;
110391e2f25SKhalid Aziz 	u32 Sccb_savedATC;
111db038cf8SAlexey Dobriyan 	unsigned char Save_Cdb[6];
112db038cf8SAlexey Dobriyan 	unsigned char Save_CdbLen;
113db038cf8SAlexey Dobriyan 	unsigned char Sccb_XferState;
114391e2f25SKhalid Aziz 	u32 Sccb_SGoffset;
11569eb2ea4SAlexey Dobriyan };
1161da177e4SLinus Torvalds 
1171da177e4SLinus Torvalds #pragma pack()
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds #define SCATTER_GATHER_COMMAND    0x02
1201da177e4SLinus Torvalds #define RESIDUAL_COMMAND          0x03
1211da177e4SLinus Torvalds #define RESIDUAL_SG_COMMAND       0x04
1221da177e4SLinus Torvalds #define RESET_COMMAND             0x81
1231da177e4SLinus Torvalds 
1241da177e4SLinus Torvalds #define F_USE_CMD_Q              0x20	/*Inidcates TAGGED command. */
1251da177e4SLinus Torvalds #define TAG_TYPE_MASK            0xC0	/*Type of tag msg to send. */
1261da177e4SLinus Torvalds #define SCCB_DATA_XFER_OUT       0x10	/* Write */
1271da177e4SLinus Torvalds #define SCCB_DATA_XFER_IN        0x08	/* Read */
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds #define NO_AUTO_REQUEST_SENSE    0x01	/* No Request Sense Buffer */
1301da177e4SLinus Torvalds 
1311da177e4SLinus Torvalds #define BUS_FREE_ST     0
1321da177e4SLinus Torvalds #define SELECT_ST       1
1331da177e4SLinus Torvalds #define SELECT_BDR_ST   2	/* Select w\ Bus Device Reset */
1341da177e4SLinus Torvalds #define SELECT_SN_ST    3	/* Select w\ Sync Nego */
1351da177e4SLinus Torvalds #define SELECT_WN_ST    4	/* Select w\ Wide Data Nego */
1361da177e4SLinus Torvalds #define SELECT_Q_ST     5	/* Select w\ Tagged Q'ing */
1371da177e4SLinus Torvalds #define COMMAND_ST      6
1381da177e4SLinus Torvalds #define DATA_OUT_ST     7
1391da177e4SLinus Torvalds #define DATA_IN_ST      8
1401da177e4SLinus Torvalds #define DISCONNECT_ST   9
1411da177e4SLinus Torvalds #define ABORT_ST        11
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds #define F_HOST_XFER_DIR                0x01
1441da177e4SLinus Torvalds #define F_ALL_XFERRED                  0x02
1451da177e4SLinus Torvalds #define F_SG_XFER                      0x04
1461da177e4SLinus Torvalds #define F_AUTO_SENSE                   0x08
1471da177e4SLinus Torvalds #define F_ODD_BALL_CNT                 0x10
1481da177e4SLinus Torvalds #define F_NO_DATA_YET                  0x80
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds #define F_STATUSLOADED                 0x01
1511da177e4SLinus Torvalds #define F_DEV_SELECTED                 0x04
1521da177e4SLinus Torvalds 
1531da177e4SLinus Torvalds #define SCCB_COMPLETE               0x00	/* SCCB completed without error */
1541da177e4SLinus Torvalds #define SCCB_DATA_UNDER_RUN         0x0C
1551da177e4SLinus Torvalds #define SCCB_SELECTION_TIMEOUT      0x11	/* Set SCSI selection timed out */
1561da177e4SLinus Torvalds #define SCCB_DATA_OVER_RUN          0x12
1571da177e4SLinus Torvalds #define SCCB_PHASE_SEQUENCE_FAIL    0x14	/* Target bus phase sequence failure */
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds #define SCCB_GROSS_FW_ERR           0x27	/* Major problem! */
1601da177e4SLinus Torvalds #define SCCB_BM_ERR                 0x30	/* BusMaster error. */
1611da177e4SLinus Torvalds #define SCCB_PARITY_ERR             0x34	/* SCSI parity error */
1621da177e4SLinus Torvalds 
1631da177e4SLinus Torvalds #define SCCB_IN_PROCESS            0x00
1641da177e4SLinus Torvalds #define SCCB_SUCCESS               0x01
1651da177e4SLinus Torvalds #define SCCB_ABORT                 0x02
1661da177e4SLinus Torvalds #define SCCB_ERROR                 0x04
1671da177e4SLinus Torvalds 
1681da177e4SLinus Torvalds #define  ORION_FW_REV      3110
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds #define QUEUE_DEPTH     254+1	/*1 for Normal disconnect 32 for Q'ing. */
1711da177e4SLinus Torvalds 
1721da177e4SLinus Torvalds #define	MAX_MB_CARDS	4	/* Max. no of cards suppoerted on Mother Board */
1731da177e4SLinus Torvalds 
1741da177e4SLinus Torvalds #define MAX_SCSI_TAR    16
1751da177e4SLinus Torvalds #define MAX_LUN         32
1761da177e4SLinus Torvalds #define LUN_MASK			0x1f
1771da177e4SLinus Torvalds 
1781da177e4SLinus Torvalds #define SG_BUF_CNT      16	/*Number of prefetched elements. */
1791da177e4SLinus Torvalds 
1801da177e4SLinus Torvalds #define SG_ELEMENT_SIZE 8	/*Eight byte per element. */
1811da177e4SLinus Torvalds 
182ad0e1d9fSAlexey Dobriyan #define RD_HARPOON(ioport)          inb((u32)ioport)
183ad0e1d9fSAlexey Dobriyan #define RDW_HARPOON(ioport)         inw((u32)ioport)
184ad0e1d9fSAlexey Dobriyan #define RD_HARP32(ioport,offset,data) (data = inl((u32)(ioport + offset)))
185ad0e1d9fSAlexey Dobriyan #define WR_HARPOON(ioport,val)      outb((u8) val, (u32)ioport)
186ad0e1d9fSAlexey Dobriyan #define WRW_HARPOON(ioport,val)       outw((u16)val, (u32)ioport)
187ad0e1d9fSAlexey Dobriyan #define WR_HARP32(ioport,offset,data)  outl(data, (u32)(ioport + offset))
1881da177e4SLinus Torvalds 
1891da177e4SLinus Torvalds #define  TAR_SYNC_MASK     (BIT(7)+BIT(6))
1901da177e4SLinus Torvalds #define  SYNC_TRYING               BIT(6)
1911da177e4SLinus Torvalds #define  SYNC_SUPPORTED    (BIT(7)+BIT(6))
1921da177e4SLinus Torvalds 
1931da177e4SLinus Torvalds #define  TAR_WIDE_MASK     (BIT(5)+BIT(4))
1941da177e4SLinus Torvalds #define  WIDE_ENABLED              BIT(4)
1951da177e4SLinus Torvalds #define  WIDE_NEGOCIATED   BIT(5)
1961da177e4SLinus Torvalds 
1971da177e4SLinus Torvalds #define  TAR_TAG_Q_MASK    (BIT(3)+BIT(2))
1981da177e4SLinus Torvalds #define  TAG_Q_TRYING              BIT(2)
1991da177e4SLinus Torvalds #define  TAG_Q_REJECT      BIT(3)
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds #define  TAR_ALLOW_DISC    BIT(0)
2021da177e4SLinus Torvalds 
2031da177e4SLinus Torvalds #define  EE_SYNC_MASK      (BIT(0)+BIT(1))
2041da177e4SLinus Torvalds #define  EE_SYNC_5MB       BIT(0)
2051da177e4SLinus Torvalds #define  EE_SYNC_10MB      BIT(1)
2061da177e4SLinus Torvalds #define  EE_SYNC_20MB      (BIT(0)+BIT(1))
2071da177e4SLinus Torvalds 
2081da177e4SLinus Torvalds #define  EE_WIDE_SCSI      BIT(7)
2091da177e4SLinus Torvalds 
210f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info {
2111da177e4SLinus Torvalds 
21269eb2ea4SAlexey Dobriyan 	struct sccb *TarSelQ_Head;
21369eb2ea4SAlexey Dobriyan 	struct sccb *TarSelQ_Tail;
214db038cf8SAlexey Dobriyan 	unsigned char TarLUN_CA;	/*Contingent Allgiance */
215db038cf8SAlexey Dobriyan 	unsigned char TarTagQ_Cnt;
216db038cf8SAlexey Dobriyan 	unsigned char TarSelQ_Cnt;
217db038cf8SAlexey Dobriyan 	unsigned char TarStatus;
218db038cf8SAlexey Dobriyan 	unsigned char TarEEValue;
219db038cf8SAlexey Dobriyan 	unsigned char TarSyncCtrl;
220db038cf8SAlexey Dobriyan 	unsigned char TarReserved[2];	/* for alignment */
221db038cf8SAlexey Dobriyan 	unsigned char LunDiscQ_Idx[MAX_LUN];
222db038cf8SAlexey Dobriyan 	unsigned char TarLUNBusy[MAX_LUN];
223f31dc0cdSAlexey Dobriyan };
2241da177e4SLinus Torvalds 
22568d0c1aeSAlexey Dobriyan struct nvram_info {
226db038cf8SAlexey Dobriyan 	unsigned char niModel;		/* Model No. of card */
227db038cf8SAlexey Dobriyan 	unsigned char niCardNo;		/* Card no. */
228391e2f25SKhalid Aziz 	u32 niBaseAddr;			/* Port Address of card */
229391e2f25SKhalid Aziz 	unsigned char niSysConf;	/* Adapter Configuration byte -
230391e2f25SKhalid Aziz 					   Byte 16 of eeprom map */
231391e2f25SKhalid Aziz 	unsigned char niScsiConf;	/* SCSI Configuration byte -
232391e2f25SKhalid Aziz 					   Byte 17 of eeprom map */
233391e2f25SKhalid Aziz 	unsigned char niScamConf;	/* SCAM Configuration byte -
234391e2f25SKhalid Aziz 					   Byte 20 of eeprom map */
235391e2f25SKhalid Aziz 	unsigned char niAdapId;		/* Host Adapter ID -
236391e2f25SKhalid Aziz 					   Byte 24 of eerpom map */
237391e2f25SKhalid Aziz 	unsigned char niSyncTbl[MAX_SCSI_TAR / 2];	/* Sync/Wide byte
238391e2f25SKhalid Aziz 							   of targets */
239391e2f25SKhalid Aziz 	unsigned char niScamTbl[MAX_SCSI_TAR][4];	/* Compressed Scam name
240391e2f25SKhalid Aziz 							   string of Targets */
24168d0c1aeSAlexey Dobriyan };
2421da177e4SLinus Torvalds 
2431da177e4SLinus Torvalds #define	MODEL_LT		1
2441da177e4SLinus Torvalds #define	MODEL_DL		2
2451da177e4SLinus Torvalds #define	MODEL_LW		3
2461da177e4SLinus Torvalds #define	MODEL_DW		4
2471da177e4SLinus Torvalds 
24813e6851aSAlexey Dobriyan struct sccb_card {
24969eb2ea4SAlexey Dobriyan 	struct sccb *currentSCCB;
2507f101662SAlexey Dobriyan 	struct sccb_mgr_info *cardInfo;
2511da177e4SLinus Torvalds 
252391e2f25SKhalid Aziz 	u32 ioPort;
2531da177e4SLinus Torvalds 
254c823feebSAlexey Dobriyan 	unsigned short cmdCounter;
255db038cf8SAlexey Dobriyan 	unsigned char discQCount;
256db038cf8SAlexey Dobriyan 	unsigned char tagQ_Lst;
257db038cf8SAlexey Dobriyan 	unsigned char cardIndex;
258db038cf8SAlexey Dobriyan 	unsigned char scanIndex;
259db038cf8SAlexey Dobriyan 	unsigned char globalFlags;
260db038cf8SAlexey Dobriyan 	unsigned char ourId;
26168d0c1aeSAlexey Dobriyan 	struct nvram_info *pNvRamInfo;
26269eb2ea4SAlexey Dobriyan 	struct sccb *discQ_Tbl[QUEUE_DEPTH];
2631da177e4SLinus Torvalds 
26413e6851aSAlexey Dobriyan };
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds #define F_TAG_STARTED		0x01
2671da177e4SLinus Torvalds #define F_CONLUN_IO			0x02
2681da177e4SLinus Torvalds #define F_DO_RENEGO			0x04
2691da177e4SLinus Torvalds #define F_NO_FILTER			0x08
2701da177e4SLinus Torvalds #define F_GREEN_PC			0x10
2711da177e4SLinus Torvalds #define F_HOST_XFER_ACT		0x20
2721da177e4SLinus Torvalds #define F_NEW_SCCB_CMD		0x40
2731da177e4SLinus Torvalds #define F_UPDATE_EEPROM		0x80
2741da177e4SLinus Torvalds 
2751da177e4SLinus Torvalds #define  ID_STRING_LENGTH  32
2761da177e4SLinus Torvalds #define  TYPE_CODE0        0x63	/*Level2 Mstr (bits 7-6),  */
2771da177e4SLinus Torvalds 
2781da177e4SLinus Torvalds #define  SLV_TYPE_CODE0    0xA3	/*Priority Bit set (bits 7-6),  */
2791da177e4SLinus Torvalds 
2801da177e4SLinus Torvalds #define  ASSIGN_ID   0x00
2811da177e4SLinus Torvalds #define  SET_P_FLAG  0x01
2821da177e4SLinus Torvalds #define  CFG_CMPLT   0x03
2831da177e4SLinus Torvalds #define  DOM_MSTR    0x0F
2841da177e4SLinus Torvalds #define  SYNC_PTRN   0x1F
2851da177e4SLinus Torvalds 
2861da177e4SLinus Torvalds #define  ID_0_7      0x18
2871da177e4SLinus Torvalds #define  ID_8_F      0x11
2881da177e4SLinus Torvalds #define  MISC_CODE   0x14
2891da177e4SLinus Torvalds #define  CLR_P_FLAG  0x18
2901da177e4SLinus Torvalds 
2911da177e4SLinus Torvalds #define  INIT_SELTD  0x01
2921da177e4SLinus Torvalds #define  LEVEL2_TAR  0x02
2931da177e4SLinus Torvalds 
2945c04a7b8SAlexey Dobriyan enum scam_id_st { ID0, ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10, ID11,
2955c04a7b8SAlexey Dobriyan 	    ID12,
2961da177e4SLinus Torvalds 	ID13, ID14, ID15, ID_UNUSED, ID_UNASSIGNED, ID_ASSIGNED, LEGACY,
2975c04a7b8SAlexey Dobriyan 	CLR_PRIORITY, NO_ID_AVAIL
2985c04a7b8SAlexey Dobriyan };
2991da177e4SLinus Torvalds 
3001da177e4SLinus Torvalds typedef struct SCCBscam_info {
3011da177e4SLinus Torvalds 
302db038cf8SAlexey Dobriyan 	unsigned char id_string[ID_STRING_LENGTH];
3031da177e4SLinus Torvalds 	enum scam_id_st state;
3041da177e4SLinus Torvalds 
30585ae97d8SAlexey Dobriyan } SCCBSCAM_INFO;
3061da177e4SLinus Torvalds 
3071da177e4SLinus Torvalds #define  SCSI_REQUEST_SENSE      0x03
3081da177e4SLinus Torvalds #define  SCSI_READ               0x08
3091da177e4SLinus Torvalds #define  SCSI_WRITE              0x0A
3101da177e4SLinus Torvalds #define  SCSI_START_STOP_UNIT    0x1B
3111da177e4SLinus Torvalds #define  SCSI_READ_EXTENDED      0x28
3121da177e4SLinus Torvalds #define  SCSI_WRITE_EXTENDED     0x2A
3131da177e4SLinus Torvalds #define  SCSI_WRITE_AND_VERIFY   0x2E
3141da177e4SLinus Torvalds 
3151da177e4SLinus Torvalds #define  SSGOOD                  0x00
3161da177e4SLinus Torvalds #define  SSCHECK                 0x02
3171da177e4SLinus Torvalds #define  SSQ_FULL                0x28
3181da177e4SLinus Torvalds 
3191da177e4SLinus Torvalds #define  SMCMD_COMP              0x00
3201da177e4SLinus Torvalds #define  SMEXT                   0x01
3211da177e4SLinus Torvalds #define  SMSAVE_DATA_PTR         0x02
3221da177e4SLinus Torvalds #define  SMREST_DATA_PTR         0x03
3231da177e4SLinus Torvalds #define  SMDISC                  0x04
3241da177e4SLinus Torvalds #define  SMABORT                 0x06
3251da177e4SLinus Torvalds #define  SMREJECT                0x07
3261da177e4SLinus Torvalds #define  SMNO_OP                 0x08
3271da177e4SLinus Torvalds #define  SMPARITY                0x09
3281da177e4SLinus Torvalds #define  SMDEV_RESET             0x0C
3291da177e4SLinus Torvalds #define	SMABORT_TAG					0x0D
3301da177e4SLinus Torvalds #define	SMINIT_RECOVERY			0x0F
3311da177e4SLinus Torvalds #define	SMREL_RECOVERY				0x10
3321da177e4SLinus Torvalds 
3331da177e4SLinus Torvalds #define  SMIDENT                 0x80
3341da177e4SLinus Torvalds #define  DISC_PRIV               0x40
3351da177e4SLinus Torvalds 
3361da177e4SLinus Torvalds #define  SMSYNC                  0x01
3371da177e4SLinus Torvalds #define  SMWDTR                  0x03
3381da177e4SLinus Torvalds #define  SM8BIT                  0x00
3391da177e4SLinus Torvalds #define  SM16BIT                 0x01
3401da177e4SLinus Torvalds #define  SMIGNORWR               0x23	/* Ignore Wide Residue */
3411da177e4SLinus Torvalds 
3421da177e4SLinus Torvalds #define  SIX_BYTE_CMD            0x06
3431da177e4SLinus Torvalds #define  TWELVE_BYTE_CMD         0x0C
3441da177e4SLinus Torvalds 
3451da177e4SLinus Torvalds #define  ASYNC                   0x00
3461da177e4SLinus Torvalds #define  MAX_OFFSET              0x0F	/* Maxbyteoffset for Sync Xfers */
3471da177e4SLinus Torvalds 
3481da177e4SLinus Torvalds #define  EEPROM_WD_CNT     256
3491da177e4SLinus Torvalds 
3501da177e4SLinus Torvalds #define  EEPROM_CHECK_SUM  0
3511da177e4SLinus Torvalds #define  FW_SIGNATURE      2
3521da177e4SLinus Torvalds #define  MODEL_NUMB_0      4
3531da177e4SLinus Torvalds #define  MODEL_NUMB_2      6
3541da177e4SLinus Torvalds #define  MODEL_NUMB_4      8
3551da177e4SLinus Torvalds #define  SYSTEM_CONFIG     16
3561da177e4SLinus Torvalds #define  SCSI_CONFIG       17
3571da177e4SLinus Torvalds #define  BIOS_CONFIG       18
3581da177e4SLinus Torvalds #define  SCAM_CONFIG       20
3591da177e4SLinus Torvalds #define  ADAPTER_SCSI_ID   24
3601da177e4SLinus Torvalds 
3611da177e4SLinus Torvalds #define  IGNORE_B_SCAN     32
3621da177e4SLinus Torvalds #define  SEND_START_ENA    34
3631da177e4SLinus Torvalds #define  DEVICE_ENABLE     36
3641da177e4SLinus Torvalds 
3651da177e4SLinus Torvalds #define  SYNC_RATE_TBL     38
3661da177e4SLinus Torvalds #define  SYNC_RATE_TBL01   38
3671da177e4SLinus Torvalds #define  SYNC_RATE_TBL23   40
3681da177e4SLinus Torvalds #define  SYNC_RATE_TBL45   42
3691da177e4SLinus Torvalds #define  SYNC_RATE_TBL67   44
3701da177e4SLinus Torvalds #define  SYNC_RATE_TBL89   46
3711da177e4SLinus Torvalds #define  SYNC_RATE_TBLab   48
3721da177e4SLinus Torvalds #define  SYNC_RATE_TBLcd   50
3731da177e4SLinus Torvalds #define  SYNC_RATE_TBLef   52
3741da177e4SLinus Torvalds 
3751da177e4SLinus Torvalds #define  EE_SCAMBASE      256
3761da177e4SLinus Torvalds 
3771da177e4SLinus Torvalds #define  SCAM_ENABLED   BIT(2)
3781da177e4SLinus Torvalds #define  SCAM_LEVEL2    BIT(3)
3791da177e4SLinus Torvalds 
3801cafc30fSJiri Slaby #define	RENEGO_ENA		BIT(10)
3811cafc30fSJiri Slaby #define	CONNIO_ENA		BIT(11)
3821cafc30fSJiri Slaby #define  GREEN_PC_ENA   BIT(12)
3831da177e4SLinus Torvalds 
3841da177e4SLinus Torvalds #define  AUTO_RATE_00   00
3851da177e4SLinus Torvalds #define  AUTO_RATE_05   01
3861da177e4SLinus Torvalds #define  AUTO_RATE_10   02
3871da177e4SLinus Torvalds #define  AUTO_RATE_20   03
3881da177e4SLinus Torvalds 
3891da177e4SLinus Torvalds #define  WIDE_NEGO_BIT     BIT(7)
3901da177e4SLinus Torvalds #define  DISC_ENABLE_BIT   BIT(6)
3911da177e4SLinus Torvalds 
3921da177e4SLinus Torvalds #define  hp_vendor_id_0       0x00	/* LSB */
3931da177e4SLinus Torvalds #define  ORION_VEND_0   0x4B
3941da177e4SLinus Torvalds 
3951da177e4SLinus Torvalds #define  hp_vendor_id_1       0x01	/* MSB */
3961da177e4SLinus Torvalds #define  ORION_VEND_1   0x10
3971da177e4SLinus Torvalds 
3981da177e4SLinus Torvalds #define  hp_device_id_0       0x02	/* LSB */
3991da177e4SLinus Torvalds #define  ORION_DEV_0    0x30
4001da177e4SLinus Torvalds 
4011da177e4SLinus Torvalds #define  hp_device_id_1       0x03	/* MSB */
4021da177e4SLinus Torvalds #define  ORION_DEV_1    0x81
4031da177e4SLinus Torvalds 
4041da177e4SLinus Torvalds 	/* Sub Vendor ID and Sub Device ID only available in
4051da177e4SLinus Torvalds 	   Harpoon Version 2 and higher */
4061da177e4SLinus Torvalds 
4071da177e4SLinus Torvalds #define  hp_sub_device_id_0   0x06	/* LSB */
4081da177e4SLinus Torvalds 
4091da177e4SLinus Torvalds #define  hp_semaphore         0x0C
4101da177e4SLinus Torvalds #define SCCB_MGR_ACTIVE    BIT(0)
4111da177e4SLinus Torvalds #define TICKLE_ME          BIT(1)
4121da177e4SLinus Torvalds #define SCCB_MGR_PRESENT   BIT(3)
4131da177e4SLinus Torvalds #define BIOS_IN_USE        BIT(4)
4141da177e4SLinus Torvalds 
4151da177e4SLinus Torvalds #define  hp_sys_ctrl          0x0F
4161da177e4SLinus Torvalds 
4171da177e4SLinus Torvalds #define  STOP_CLK          BIT(0)	/*Turn off BusMaster Clock */
4181da177e4SLinus Torvalds #define  DRVR_RST          BIT(1)	/*Firmware Reset to 80C15 chip */
4191da177e4SLinus Torvalds #define  HALT_MACH         BIT(3)	/*Halt State Machine      */
4201da177e4SLinus Torvalds #define  HARD_ABORT        BIT(4)	/*Hard Abort              */
4211da177e4SLinus Torvalds 
4221da177e4SLinus Torvalds #define  hp_host_blk_cnt      0x13
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds #define  XFER_BLK64        0x06	/*     1 1 0 64 byte per block */
4251da177e4SLinus Torvalds 
4261da177e4SLinus Torvalds #define  BM_THRESHOLD      0x40	/* PCI mode can only xfer 16 bytes */
4271da177e4SLinus Torvalds 
4281da177e4SLinus Torvalds #define  hp_int_mask          0x17
4291da177e4SLinus Torvalds 
4301da177e4SLinus Torvalds #define  INT_CMD_COMPL     BIT(0)	/* DMA command complete   */
4311da177e4SLinus Torvalds #define  INT_EXT_STATUS    BIT(1)	/* Extended Status Set    */
4321da177e4SLinus Torvalds 
4331da177e4SLinus Torvalds #define  hp_xfer_cnt_lo       0x18
4341da177e4SLinus Torvalds #define  hp_xfer_cnt_hi       0x1A
4351da177e4SLinus Torvalds #define  hp_xfer_cmd          0x1B
4361da177e4SLinus Torvalds 
4371da177e4SLinus Torvalds #define  XFER_HOST_DMA     0x00	/*     0 0 0 Transfer Host -> DMA */
4381da177e4SLinus Torvalds #define  XFER_DMA_HOST     0x01	/*     0 0 1 Transfer DMA  -> Host */
4391da177e4SLinus Torvalds 
4401da177e4SLinus Torvalds #define  XFER_HOST_AUTO    0x00	/*     0 0 Auto Transfer Size   */
4411da177e4SLinus Torvalds 
4421da177e4SLinus Torvalds #define  XFER_DMA_8BIT     0x20	/*     0 1 8 BIT  Transfer Size */
4431da177e4SLinus Torvalds 
4441da177e4SLinus Torvalds #define  DISABLE_INT       BIT(7)	/*Do not interrupt at end of cmd. */
4451da177e4SLinus Torvalds 
4461da177e4SLinus Torvalds #define  HOST_WRT_CMD      ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
4471da177e4SLinus Torvalds #define  HOST_RD_CMD       ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
4481da177e4SLinus Torvalds 
4491da177e4SLinus Torvalds #define  hp_host_addr_lo      0x1C
4501da177e4SLinus Torvalds #define  hp_host_addr_hmi     0x1E
4511da177e4SLinus Torvalds 
4521da177e4SLinus Torvalds #define  hp_ee_ctrl           0x22
4531da177e4SLinus Torvalds 
4541da177e4SLinus Torvalds #define  EXT_ARB_ACK       BIT(7)
4551da177e4SLinus Torvalds #define  SCSI_TERM_ENA_H   BIT(6)	/* SCSI high byte terminator */
4561da177e4SLinus Torvalds #define  SEE_MS            BIT(5)
4571da177e4SLinus Torvalds #define  SEE_CS            BIT(3)
4581da177e4SLinus Torvalds #define  SEE_CLK           BIT(2)
4591da177e4SLinus Torvalds #define  SEE_DO            BIT(1)
4601da177e4SLinus Torvalds #define  SEE_DI            BIT(0)
4611da177e4SLinus Torvalds 
4621da177e4SLinus Torvalds #define  EE_READ           0x06
4631da177e4SLinus Torvalds #define  EE_WRITE          0x05
4641da177e4SLinus Torvalds #define  EWEN              0x04
4651da177e4SLinus Torvalds #define  EWEN_ADDR         0x03C0
4661da177e4SLinus Torvalds #define  EWDS              0x04
4671da177e4SLinus Torvalds #define  EWDS_ADDR         0x0000
4681da177e4SLinus Torvalds 
4691da177e4SLinus Torvalds #define  hp_bm_ctrl           0x26
4701da177e4SLinus Torvalds 
4711da177e4SLinus Torvalds #define  SCSI_TERM_ENA_L   BIT(0)	/*Enable/Disable external terminators */
4721da177e4SLinus Torvalds #define  FLUSH_XFER_CNTR   BIT(1)	/*Flush transfer counter */
4731da177e4SLinus Torvalds #define  FORCE1_XFER       BIT(5)	/*Always xfer one byte in byte mode */
4741da177e4SLinus Torvalds #define  FAST_SINGLE       BIT(6)	/*?? */
4751da177e4SLinus Torvalds 
4761da177e4SLinus Torvalds #define  BMCTRL_DEFAULT    (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)
4771da177e4SLinus Torvalds 
4781da177e4SLinus Torvalds #define  hp_sg_addr           0x28
4791da177e4SLinus Torvalds #define  hp_page_ctrl         0x29
4801da177e4SLinus Torvalds 
4811da177e4SLinus Torvalds #define  SCATTER_EN        BIT(0)
4821da177e4SLinus Torvalds #define  SGRAM_ARAM        BIT(1)
4831da177e4SLinus Torvalds #define  G_INT_DISABLE     BIT(3)	/* Enable/Disable all Interrupts */
4841da177e4SLinus Torvalds #define  NARROW_SCSI_CARD  BIT(4)	/* NARROW/WIDE SCSI config pin */
4851da177e4SLinus Torvalds 
4861da177e4SLinus Torvalds #define  hp_pci_stat_cfg      0x2D
4871da177e4SLinus Torvalds 
4881da177e4SLinus Torvalds #define  REC_MASTER_ABORT  BIT(5)	/*received Master abort */
4891da177e4SLinus Torvalds 
4901da177e4SLinus Torvalds #define  hp_rev_num           0x33
4911da177e4SLinus Torvalds 
4921da177e4SLinus Torvalds #define  hp_stack_data        0x34
4931da177e4SLinus Torvalds #define  hp_stack_addr        0x35
4941da177e4SLinus Torvalds 
4951da177e4SLinus Torvalds #define  hp_ext_status        0x36
4961da177e4SLinus Torvalds 
4971da177e4SLinus Torvalds #define  BM_FORCE_OFF      BIT(0)	/*Bus Master is forced to get off */
4981da177e4SLinus Torvalds #define  PCI_TGT_ABORT     BIT(0)	/*PCI bus master transaction aborted */
4991da177e4SLinus Torvalds #define  PCI_DEV_TMOUT     BIT(1)	/*PCI Device Time out */
5001da177e4SLinus Torvalds #define  CMD_ABORTED       BIT(4)	/*Command aborted */
5011da177e4SLinus Torvalds #define  BM_PARITY_ERR     BIT(5)	/*parity error on data received   */
5021da177e4SLinus Torvalds #define  PIO_OVERRUN       BIT(6)	/*Slave data overrun */
5031da177e4SLinus Torvalds #define  BM_CMD_BUSY       BIT(7)	/*Bus master transfer command busy */
5041da177e4SLinus Torvalds #define  BAD_EXT_STATUS    (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
5051da177e4SLinus Torvalds                                   BM_PARITY_ERR | PIO_OVERRUN)
5061da177e4SLinus Torvalds 
5071da177e4SLinus Torvalds #define  hp_int_status        0x37
5081da177e4SLinus Torvalds 
5091da177e4SLinus Torvalds #define  EXT_STATUS_ON     BIT(1)	/*Extended status is valid */
5101da177e4SLinus Torvalds #define  SCSI_INTERRUPT    BIT(2)	/*Global indication of a SCSI int. */
5111da177e4SLinus Torvalds #define  INT_ASSERTED      BIT(5)	/* */
5121da177e4SLinus Torvalds 
5131da177e4SLinus Torvalds #define  hp_fifo_cnt          0x38
5141da177e4SLinus Torvalds 
5151da177e4SLinus Torvalds #define  hp_intena		 0x40
5161da177e4SLinus Torvalds 
5171cafc30fSJiri Slaby #define  RESET		 BIT(7)
5181cafc30fSJiri Slaby #define  PROG_HLT		 BIT(6)
5191cafc30fSJiri Slaby #define  PARITY		 BIT(5)
5201cafc30fSJiri Slaby #define  FIFO		 BIT(4)
5211cafc30fSJiri Slaby #define  SEL		 BIT(3)
5221cafc30fSJiri Slaby #define  SCAM_SEL		 BIT(2)
5231cafc30fSJiri Slaby #define  RSEL		 BIT(1)
5241cafc30fSJiri Slaby #define  TIMEOUT		 BIT(0)
5251cafc30fSJiri Slaby #define  BUS_FREE		 BIT(15)
5261cafc30fSJiri Slaby #define  XFER_CNT_0	 BIT(14)
5271cafc30fSJiri Slaby #define  PHASE		 BIT(13)
5281cafc30fSJiri Slaby #define  IUNKWN		 BIT(12)
5291cafc30fSJiri Slaby #define  ICMD_COMP	 BIT(11)
5301cafc30fSJiri Slaby #define  ITICKLE		 BIT(10)
5311cafc30fSJiri Slaby #define  IDO_STRT		 BIT(9)
5321cafc30fSJiri Slaby #define  ITAR_DISC	 BIT(8)
5331cafc30fSJiri Slaby #define  AUTO_INT		 (BIT(12)+BIT(11)+BIT(10)+BIT(9)+BIT(8))
5341da177e4SLinus Torvalds #define  CLR_ALL_INT	 0xFFFF
5351da177e4SLinus Torvalds #define  CLR_ALL_INT_1	 0xFF00
5361da177e4SLinus Torvalds 
5371da177e4SLinus Torvalds #define  hp_intstat		 0x42
5381da177e4SLinus Torvalds 
5391da177e4SLinus Torvalds #define  hp_scsisig           0x44
5401da177e4SLinus Torvalds 
5411da177e4SLinus Torvalds #define  SCSI_SEL          BIT(7)
5421da177e4SLinus Torvalds #define  SCSI_BSY          BIT(6)
5431da177e4SLinus Torvalds #define  SCSI_REQ          BIT(5)
5441da177e4SLinus Torvalds #define  SCSI_ACK          BIT(4)
5451da177e4SLinus Torvalds #define  SCSI_ATN          BIT(3)
5461da177e4SLinus Torvalds #define  SCSI_CD           BIT(2)
5471da177e4SLinus Torvalds #define  SCSI_MSG          BIT(1)
5481da177e4SLinus Torvalds #define  SCSI_IOBIT        BIT(0)
5491da177e4SLinus Torvalds 
5501da177e4SLinus Torvalds #define  S_SCSI_PHZ        (BIT(2)+BIT(1)+BIT(0))
5511da177e4SLinus Torvalds #define  S_MSGO_PH         (BIT(2)+BIT(1)       )
5521da177e4SLinus Torvalds #define  S_MSGI_PH         (BIT(2)+BIT(1)+BIT(0))
5531da177e4SLinus Torvalds #define  S_DATAI_PH        (              BIT(0))
5541da177e4SLinus Torvalds #define  S_DATAO_PH        0x00
5551da177e4SLinus Torvalds #define  S_ILL_PH          (       BIT(1)       )
5561da177e4SLinus Torvalds 
5571da177e4SLinus Torvalds #define  hp_scsictrl_0        0x45
5581da177e4SLinus Torvalds 
5591da177e4SLinus Torvalds #define  SEL_TAR           BIT(6)
5601da177e4SLinus Torvalds #define  ENA_ATN           BIT(4)
5611da177e4SLinus Torvalds #define  ENA_RESEL         BIT(2)
5621da177e4SLinus Torvalds #define  SCSI_RST          BIT(1)
5631da177e4SLinus Torvalds #define  ENA_SCAM_SEL      BIT(0)
5641da177e4SLinus Torvalds 
5651da177e4SLinus Torvalds #define  hp_portctrl_0        0x46
5661da177e4SLinus Torvalds 
5671da177e4SLinus Torvalds #define  SCSI_PORT         BIT(7)
5681da177e4SLinus Torvalds #define  SCSI_INBIT        BIT(6)
5691da177e4SLinus Torvalds #define  DMA_PORT          BIT(5)
5701da177e4SLinus Torvalds #define  DMA_RD            BIT(4)
5711da177e4SLinus Torvalds #define  HOST_PORT         BIT(3)
5721da177e4SLinus Torvalds #define  HOST_WRT          BIT(2)
5731da177e4SLinus Torvalds #define  SCSI_BUS_EN       BIT(1)
5741da177e4SLinus Torvalds #define  START_TO          BIT(0)
5751da177e4SLinus Torvalds 
5761da177e4SLinus Torvalds #define  hp_scsireset         0x47
5771da177e4SLinus Torvalds 
5781da177e4SLinus Torvalds #define  SCSI_INI          BIT(6)
5791da177e4SLinus Torvalds #define  SCAM_EN           BIT(5)
5801da177e4SLinus Torvalds #define  DMA_RESET         BIT(3)
5811da177e4SLinus Torvalds #define  HPSCSI_RESET      BIT(2)
5821da177e4SLinus Torvalds #define  PROG_RESET        BIT(1)
5831da177e4SLinus Torvalds #define  FIFO_CLR          BIT(0)
5841da177e4SLinus Torvalds 
5851da177e4SLinus Torvalds #define  hp_xfercnt_0         0x48
5861da177e4SLinus Torvalds #define  hp_xfercnt_2         0x4A
5871da177e4SLinus Torvalds 
5881da177e4SLinus Torvalds #define  hp_fifodata_0        0x4C
5891da177e4SLinus Torvalds #define  hp_addstat           0x4E
5901da177e4SLinus Torvalds 
5911da177e4SLinus Torvalds #define  SCAM_TIMER        BIT(7)
5921da177e4SLinus Torvalds #define  SCSI_MODE8        BIT(3)
5931da177e4SLinus Torvalds #define  SCSI_PAR_ERR      BIT(0)
5941da177e4SLinus Torvalds 
5951da177e4SLinus Torvalds #define  hp_prgmcnt_0         0x4F
5961da177e4SLinus Torvalds 
5971da177e4SLinus Torvalds #define  hp_selfid_0          0x50
5981da177e4SLinus Torvalds #define  hp_selfid_1          0x51
5991da177e4SLinus Torvalds #define  hp_arb_id            0x52
6001da177e4SLinus Torvalds 
6011da177e4SLinus Torvalds #define  hp_select_id         0x53
6021da177e4SLinus Torvalds 
6031da177e4SLinus Torvalds #define  hp_synctarg_base     0x54
6041da177e4SLinus Torvalds #define  hp_synctarg_12       0x54
6051da177e4SLinus Torvalds #define  hp_synctarg_13       0x55
6061da177e4SLinus Torvalds #define  hp_synctarg_14       0x56
6071da177e4SLinus Torvalds #define  hp_synctarg_15       0x57
6081da177e4SLinus Torvalds 
6091da177e4SLinus Torvalds #define  hp_synctarg_8        0x58
6101da177e4SLinus Torvalds #define  hp_synctarg_9        0x59
6111da177e4SLinus Torvalds #define  hp_synctarg_10       0x5A
6121da177e4SLinus Torvalds #define  hp_synctarg_11       0x5B
6131da177e4SLinus Torvalds 
6141da177e4SLinus Torvalds #define  hp_synctarg_4        0x5C
6151da177e4SLinus Torvalds #define  hp_synctarg_5        0x5D
6161da177e4SLinus Torvalds #define  hp_synctarg_6        0x5E
6171da177e4SLinus Torvalds #define  hp_synctarg_7        0x5F
6181da177e4SLinus Torvalds 
6191da177e4SLinus Torvalds #define  hp_synctarg_0        0x60
6201da177e4SLinus Torvalds #define  hp_synctarg_1        0x61
6211da177e4SLinus Torvalds #define  hp_synctarg_2        0x62
6221da177e4SLinus Torvalds #define  hp_synctarg_3        0x63
6231da177e4SLinus Torvalds 
6241da177e4SLinus Torvalds #define  NARROW_SCSI       BIT(4)
6251da177e4SLinus Torvalds #define  DEFAULT_OFFSET    0x0F
6261da177e4SLinus Torvalds 
6271da177e4SLinus Torvalds #define  hp_autostart_0       0x64
6281da177e4SLinus Torvalds #define  hp_autostart_1       0x65
6291da177e4SLinus Torvalds #define  hp_autostart_3       0x67
6301da177e4SLinus Torvalds 
6311da177e4SLinus Torvalds #define  AUTO_IMMED    BIT(5)
6321da177e4SLinus Torvalds #define  SELECT   BIT(6)
6331da177e4SLinus Torvalds #define  END_DATA (BIT(7)+BIT(6))
6341da177e4SLinus Torvalds 
6351da177e4SLinus Torvalds #define  hp_gp_reg_0          0x68
6361da177e4SLinus Torvalds #define  hp_gp_reg_1          0x69
6371da177e4SLinus Torvalds #define  hp_gp_reg_3          0x6B
6381da177e4SLinus Torvalds 
6391da177e4SLinus Torvalds #define  hp_seltimeout        0x6C
6401da177e4SLinus Torvalds 
6411da177e4SLinus Torvalds #define  TO_4ms            0x67	/* 3.9959ms */
6421da177e4SLinus Torvalds 
6431da177e4SLinus Torvalds #define  TO_5ms            0x03	/* 4.9152ms */
6441da177e4SLinus Torvalds #define  TO_10ms           0x07	/* 11.xxxms */
6451da177e4SLinus Torvalds #define  TO_250ms          0x99	/* 250.68ms */
6461da177e4SLinus Torvalds #define  TO_290ms          0xB1	/* 289.99ms */
6471da177e4SLinus Torvalds 
6481da177e4SLinus Torvalds #define  hp_clkctrl_0         0x6D
6491da177e4SLinus Torvalds 
6501da177e4SLinus Torvalds #define  PWR_DWN           BIT(6)
6511da177e4SLinus Torvalds #define  ACTdeassert       BIT(4)
6521da177e4SLinus Torvalds #define  CLK_40MHZ         (BIT(1) + BIT(0))
6531da177e4SLinus Torvalds 
6541da177e4SLinus Torvalds #define  CLKCTRL_DEFAULT   (ACTdeassert | CLK_40MHZ)
6551da177e4SLinus Torvalds 
6561da177e4SLinus Torvalds #define  hp_fiforead          0x6E
6571da177e4SLinus Torvalds #define  hp_fifowrite         0x6F
6581da177e4SLinus Torvalds 
6591da177e4SLinus Torvalds #define  hp_offsetctr         0x70
6601da177e4SLinus Torvalds #define  hp_xferstat          0x71
6611da177e4SLinus Torvalds 
6621da177e4SLinus Torvalds #define  FIFO_EMPTY        BIT(6)
6631da177e4SLinus Torvalds 
6641da177e4SLinus Torvalds #define  hp_portctrl_1        0x72
6651da177e4SLinus Torvalds 
6661da177e4SLinus Torvalds #define  CHK_SCSI_P        BIT(3)
6671da177e4SLinus Torvalds #define  HOST_MODE8        BIT(0)
6681da177e4SLinus Torvalds 
6691da177e4SLinus Torvalds #define  hp_xfer_pad          0x73
6701da177e4SLinus Torvalds 
6711da177e4SLinus Torvalds #define  ID_UNLOCK         BIT(3)
6721da177e4SLinus Torvalds 
6731da177e4SLinus Torvalds #define  hp_scsidata_0        0x74
6741da177e4SLinus Torvalds #define  hp_scsidata_1        0x75
6751da177e4SLinus Torvalds 
6761da177e4SLinus Torvalds #define  hp_aramBase          0x80
6771da177e4SLinus Torvalds #define  BIOS_DATA_OFFSET     0x60
6781da177e4SLinus Torvalds #define  BIOS_RELATIVE_CARD   0x64
6791da177e4SLinus Torvalds 
6801cafc30fSJiri Slaby #define  AR3      (BIT(9) + BIT(8))
6811cafc30fSJiri Slaby #define  SDATA    BIT(10)
6821da177e4SLinus Torvalds 
6831cafc30fSJiri Slaby #define  CRD_OP   BIT(11)	/* Cmp Reg. w/ Data */
6841da177e4SLinus Torvalds 
6851cafc30fSJiri Slaby #define  CRR_OP   BIT(12)	/* Cmp Reg. w. Reg. */
6861da177e4SLinus Torvalds 
6871cafc30fSJiri Slaby #define  CPE_OP   (BIT(14)+BIT(11))	/* Cmp SCSI phs & Branch EQ */
6881da177e4SLinus Torvalds 
6891cafc30fSJiri Slaby #define  CPN_OP   (BIT(14)+BIT(12))	/* Cmp SCSI phs & Branch NOT EQ */
6901da177e4SLinus Torvalds 
6911da177e4SLinus Torvalds #define  ADATA_OUT   0x00
6921cafc30fSJiri Slaby #define  ADATA_IN    BIT(8)
6931cafc30fSJiri Slaby #define  ACOMMAND    BIT(10)
6941cafc30fSJiri Slaby #define  ASTATUS     (BIT(10)+BIT(8))
6951cafc30fSJiri Slaby #define  AMSG_OUT    (BIT(10)+BIT(9))
6961cafc30fSJiri Slaby #define  AMSG_IN     (BIT(10)+BIT(9)+BIT(8))
6971da177e4SLinus Torvalds 
6981cafc30fSJiri Slaby #define  BRH_OP   BIT(13)	/* Branch */
6991da177e4SLinus Torvalds 
7001da177e4SLinus Torvalds #define  ALWAYS   0x00
7011cafc30fSJiri Slaby #define  EQUAL    BIT(8)
7021cafc30fSJiri Slaby #define  NOT_EQ   BIT(9)
7031da177e4SLinus Torvalds 
7041cafc30fSJiri Slaby #define  TCB_OP   (BIT(13)+BIT(11))	/* Test condition & branch */
7051da177e4SLinus Torvalds 
7061cafc30fSJiri Slaby #define  FIFO_0      BIT(10)
7071da177e4SLinus Torvalds 
7081cafc30fSJiri Slaby #define  MPM_OP   BIT(15)	/* Match phase and move data */
7091da177e4SLinus Torvalds 
7101cafc30fSJiri Slaby #define  MRR_OP   BIT(14)	/* Move DReg. to Reg. */
7111da177e4SLinus Torvalds 
7121da177e4SLinus Torvalds #define  S_IDREG  (BIT(2)+BIT(1)+BIT(0))
7131da177e4SLinus Torvalds 
7141da177e4SLinus Torvalds #define  D_AR0    0x00
7151da177e4SLinus Torvalds #define  D_AR1    BIT(0)
7161da177e4SLinus Torvalds #define  D_BUCKET (BIT(2) + BIT(1) + BIT(0))
7171da177e4SLinus Torvalds 
7181cafc30fSJiri Slaby #define  RAT_OP      (BIT(14)+BIT(13)+BIT(11))
7191da177e4SLinus Torvalds 
7201cafc30fSJiri Slaby #define  SSI_OP      (BIT(15)+BIT(11))
7211da177e4SLinus Torvalds 
7221da177e4SLinus Torvalds #define  SSI_ITAR_DISC	(ITAR_DISC >> 8)
7231da177e4SLinus Torvalds #define  SSI_IDO_STRT	(IDO_STRT >> 8)
7241da177e4SLinus Torvalds 
7251da177e4SLinus Torvalds #define  SSI_ICMD_COMP	(ICMD_COMP >> 8)
7261da177e4SLinus Torvalds #define  SSI_ITICKLE	(ITICKLE >> 8)
7271da177e4SLinus Torvalds 
7281da177e4SLinus Torvalds #define  SSI_IUNKWN	(IUNKWN >> 8)
7291da177e4SLinus Torvalds #define  SSI_INO_CC	(IUNKWN >> 8)
7301da177e4SLinus Torvalds #define  SSI_IRFAIL	(IUNKWN >> 8)
7311da177e4SLinus Torvalds 
7321da177e4SLinus Torvalds #define  NP    0x10		/*Next Phase */
7331da177e4SLinus Torvalds #define  NTCMD 0x02		/*Non- Tagged Command start */
7341da177e4SLinus Torvalds #define  CMDPZ 0x04		/*Command phase */
7351da177e4SLinus Torvalds #define  DINT  0x12		/*Data Out/In interrupt */
7361da177e4SLinus Torvalds #define  DI    0x13		/*Data Out */
7371da177e4SLinus Torvalds #define  DC    0x19		/*Disconnect Message */
7381da177e4SLinus Torvalds #define  ST    0x1D		/*Status Phase */
7391da177e4SLinus Torvalds #define  UNKNWN 0x24		/*Unknown bus action */
7401da177e4SLinus Torvalds #define  CC    0x25		/*Command Completion failure */
7411da177e4SLinus Torvalds #define  TICK  0x26		/*New target reselected us. */
7421da177e4SLinus Torvalds #define  SELCHK 0x28		/*Select & Check SCSI ID latch reg */
7431da177e4SLinus Torvalds 
7441da177e4SLinus Torvalds #define  ID_MSG_STRT    hp_aramBase + 0x00
7451da177e4SLinus Torvalds #define  NON_TAG_ID_MSG hp_aramBase + 0x06
7461da177e4SLinus Torvalds #define  CMD_STRT       hp_aramBase + 0x08
7471da177e4SLinus Torvalds #define  SYNC_MSGS      hp_aramBase + 0x08
7481da177e4SLinus Torvalds 
7491da177e4SLinus Torvalds #define  TAG_STRT          0x00
7501da177e4SLinus Torvalds #define  DISCONNECT_START  0x10/2
7511da177e4SLinus Torvalds #define  END_DATA_START    0x14/2
7521da177e4SLinus Torvalds #define  CMD_ONLY_STRT     CMDPZ/2
7531da177e4SLinus Torvalds #define  SELCHK_STRT     SELCHK/2
7541da177e4SLinus Torvalds 
7551da177e4SLinus Torvalds #define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
7561da177e4SLinus Torvalds /* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
7571da177e4SLinus Torvalds                                  xfercnt <<= 16,\
758c823feebSAlexey Dobriyan                                  xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0)))
7591da177e4SLinus Torvalds  */
760c823feebSAlexey Dobriyan #define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (unsigned short)(addr & 0x0000FFFFL)),\
7611da177e4SLinus Torvalds          addr >>= 16,\
762c823feebSAlexey Dobriyan          WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\
7631da177e4SLinus Torvalds          WR_HARP32(port,hp_xfercnt_0,count),\
764c823feebSAlexey Dobriyan          WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\
7651da177e4SLinus Torvalds          count >>= 16,\
7661da177e4SLinus Torvalds          WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
7671da177e4SLinus Torvalds 
7681da177e4SLinus Torvalds #define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
7691da177e4SLinus Torvalds                           WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
7701da177e4SLinus Torvalds 
7711da177e4SLinus Torvalds #define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
7721da177e4SLinus Torvalds                           WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}
7731da177e4SLinus Torvalds 
7741da177e4SLinus Torvalds #define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
7751da177e4SLinus Torvalds                         WR_HARPOON(port+hp_scsireset, 0x00))
7761da177e4SLinus Torvalds 
7771da177e4SLinus Torvalds #define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7781da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))
7791da177e4SLinus Torvalds 
7801da177e4SLinus Torvalds #define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7811da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))
7821da177e4SLinus Torvalds 
7831da177e4SLinus Torvalds #define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7841da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))
7851da177e4SLinus Torvalds 
7861da177e4SLinus Torvalds #define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7871da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
7881da177e4SLinus Torvalds 
789391e2f25SKhalid Aziz static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
7905c04a7b8SAlexey Dobriyan 				 unsigned char syncFlag);
791391e2f25SKhalid Aziz static void FPT_ssel(u32 port, unsigned char p_card);
792391e2f25SKhalid Aziz static void FPT_sres(u32 port, unsigned char p_card,
7935c04a7b8SAlexey Dobriyan 		     struct sccb_card *pCurrCard);
794391e2f25SKhalid Aziz static void FPT_shandem(u32 port, unsigned char p_card,
7955c04a7b8SAlexey Dobriyan 			struct sccb *pCurrSCCB);
796391e2f25SKhalid Aziz static void FPT_stsyncn(u32 port, unsigned char p_card);
797391e2f25SKhalid Aziz static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
7985c04a7b8SAlexey Dobriyan 			unsigned char offset);
799391e2f25SKhalid Aziz static void FPT_sssyncv(u32 p_port, unsigned char p_id,
8005c04a7b8SAlexey Dobriyan 			unsigned char p_sync_value,
801f31dc0cdSAlexey Dobriyan 			struct sccb_mgr_tar_info *currTar_Info);
802391e2f25SKhalid Aziz static void FPT_sresb(u32 port, unsigned char p_card);
803391e2f25SKhalid Aziz static void FPT_sxfrp(u32 p_port, unsigned char p_card);
804391e2f25SKhalid Aziz static void FPT_schkdd(u32 port, unsigned char p_card);
805391e2f25SKhalid Aziz static unsigned char FPT_RdStack(u32 port, unsigned char index);
806391e2f25SKhalid Aziz static void FPT_WrStack(u32 portBase, unsigned char index,
8075c04a7b8SAlexey Dobriyan 			unsigned char data);
808391e2f25SKhalid Aziz static unsigned char FPT_ChkIfChipInitialized(u32 ioPort);
8091da177e4SLinus Torvalds 
810391e2f25SKhalid Aziz static void FPT_SendMsg(u32 port, unsigned char message);
811db038cf8SAlexey Dobriyan static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
812db038cf8SAlexey Dobriyan 				   unsigned char error_code);
8131da177e4SLinus Torvalds 
81469eb2ea4SAlexey Dobriyan static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
81568d0c1aeSAlexey Dobriyan static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
8161da177e4SLinus Torvalds 
817391e2f25SKhalid Aziz static unsigned char FPT_siwidn(u32 port, unsigned char p_card);
818391e2f25SKhalid Aziz static void FPT_stwidn(u32 port, unsigned char p_card);
819391e2f25SKhalid Aziz static void FPT_siwidr(u32 port, unsigned char width);
8201da177e4SLinus Torvalds 
8215c04a7b8SAlexey Dobriyan static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
822db038cf8SAlexey Dobriyan 				unsigned char p_card);
8235c04a7b8SAlexey Dobriyan static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card);
8245c04a7b8SAlexey Dobriyan static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
8255c04a7b8SAlexey Dobriyan 				 struct sccb *p_SCCB, unsigned char p_card);
8265c04a7b8SAlexey Dobriyan static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
8275c04a7b8SAlexey Dobriyan 				  unsigned char p_card);
828db038cf8SAlexey Dobriyan static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code);
82969eb2ea4SAlexey Dobriyan static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card);
8305c04a7b8SAlexey Dobriyan static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
8315c04a7b8SAlexey Dobriyan 				       unsigned char p_card);
83269eb2ea4SAlexey Dobriyan static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
833c823feebSAlexey Dobriyan static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
834db038cf8SAlexey Dobriyan static unsigned char FPT_CalcLrc(unsigned char buffer[]);
8351da177e4SLinus Torvalds 
836391e2f25SKhalid Aziz static void FPT_Wait1Second(u32 p_port);
837391e2f25SKhalid Aziz static void FPT_Wait(u32 p_port, unsigned char p_delay);
838391e2f25SKhalid Aziz static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode);
839391e2f25SKhalid Aziz static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
8405c04a7b8SAlexey Dobriyan 			    unsigned short ee_addr);
841391e2f25SKhalid Aziz static unsigned short FPT_utilEERead(u32 p_port,
8425c04a7b8SAlexey Dobriyan 				     unsigned short ee_addr);
843391e2f25SKhalid Aziz static unsigned short FPT_utilEEReadOrg(u32 p_port,
8445c04a7b8SAlexey Dobriyan 					unsigned short ee_addr);
845391e2f25SKhalid Aziz static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
8465c04a7b8SAlexey Dobriyan 				  unsigned short ee_addr);
8471da177e4SLinus Torvalds 
848391e2f25SKhalid Aziz static void FPT_phaseDataOut(u32 port, unsigned char p_card);
849391e2f25SKhalid Aziz static void FPT_phaseDataIn(u32 port, unsigned char p_card);
850391e2f25SKhalid Aziz static void FPT_phaseCommand(u32 port, unsigned char p_card);
851391e2f25SKhalid Aziz static void FPT_phaseStatus(u32 port, unsigned char p_card);
852391e2f25SKhalid Aziz static void FPT_phaseMsgOut(u32 port, unsigned char p_card);
853391e2f25SKhalid Aziz static void FPT_phaseMsgIn(u32 port, unsigned char p_card);
854391e2f25SKhalid Aziz static void FPT_phaseIllegal(u32 port, unsigned char p_card);
8551da177e4SLinus Torvalds 
856391e2f25SKhalid Aziz static void FPT_phaseDecode(u32 port, unsigned char p_card);
857391e2f25SKhalid Aziz static void FPT_phaseChkFifo(u32 port, unsigned char p_card);
858391e2f25SKhalid Aziz static void FPT_phaseBusFree(u32 p_port, unsigned char p_card);
8591da177e4SLinus Torvalds 
860391e2f25SKhalid Aziz static void FPT_XbowInit(u32 port, unsigned char scamFlg);
861391e2f25SKhalid Aziz static void FPT_BusMasterInit(u32 p_port);
862391e2f25SKhalid Aziz static void FPT_DiagEEPROM(u32 p_port);
8631da177e4SLinus Torvalds 
864391e2f25SKhalid Aziz static void FPT_dataXferProcessor(u32 port,
8655c04a7b8SAlexey Dobriyan 				  struct sccb_card *pCurrCard);
866391e2f25SKhalid Aziz static void FPT_busMstrSGDataXferStart(u32 port,
8675c04a7b8SAlexey Dobriyan 				       struct sccb *pCurrSCCB);
868391e2f25SKhalid Aziz static void FPT_busMstrDataXferStart(u32 port,
8695c04a7b8SAlexey Dobriyan 				     struct sccb *pCurrSCCB);
870391e2f25SKhalid Aziz static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
8715c04a7b8SAlexey Dobriyan 				  struct sccb *pCurrSCCB);
87269eb2ea4SAlexey Dobriyan static void FPT_hostDataXferRestart(struct sccb *currSCCB);
8731da177e4SLinus Torvalds 
874391e2f25SKhalid Aziz static unsigned char FPT_SccbMgr_bad_isr(u32 p_port,
8755c04a7b8SAlexey Dobriyan 					 unsigned char p_card,
8765c04a7b8SAlexey Dobriyan 					 struct sccb_card *pCurrCard,
8775c04a7b8SAlexey Dobriyan 					 unsigned short p_int);
8781da177e4SLinus Torvalds 
87947b5d69cSJames Bottomley  static void FPT_SccbMgrTableInitAll(void);
8805c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
8815c04a7b8SAlexey Dobriyan 				     unsigned char p_card);
8825c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
8835c04a7b8SAlexey Dobriyan 				       unsigned char target);
8841da177e4SLinus Torvalds 
8855c04a7b8SAlexey Dobriyan static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
8865c04a7b8SAlexey Dobriyan 		      unsigned char p_power_up);
8871da177e4SLinus Torvalds 
888391e2f25SKhalid Aziz static int FPT_scarb(u32 p_port, unsigned char p_sel_type);
889391e2f25SKhalid Aziz static void FPT_scbusf(u32 p_port);
890391e2f25SKhalid Aziz static void FPT_scsel(u32 p_port);
891391e2f25SKhalid Aziz static void FPT_scasid(unsigned char p_card, u32 p_port);
892391e2f25SKhalid Aziz static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data);
893391e2f25SKhalid Aziz static unsigned char FPT_scsendi(u32 p_port,
8945c04a7b8SAlexey Dobriyan 				 unsigned char p_id_string[]);
895391e2f25SKhalid Aziz static unsigned char FPT_sciso(u32 p_port,
8965c04a7b8SAlexey Dobriyan 			       unsigned char p_id_string[]);
897391e2f25SKhalid Aziz static void FPT_scwirod(u32 p_port, unsigned char p_data_bit);
898391e2f25SKhalid Aziz static void FPT_scwiros(u32 p_port, unsigned char p_data_bit);
899db038cf8SAlexey Dobriyan static unsigned char FPT_scvalq(unsigned char p_quintet);
900391e2f25SKhalid Aziz static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id);
901391e2f25SKhalid Aziz static void FPT_scwtsel(u32 p_port);
902391e2f25SKhalid Aziz static void FPT_inisci(unsigned char p_card, u32 p_port,
9035c04a7b8SAlexey Dobriyan 		       unsigned char p_our_id);
904391e2f25SKhalid Aziz static void FPT_scsavdi(unsigned char p_card, u32 p_port);
9055c04a7b8SAlexey Dobriyan static unsigned char FPT_scmachid(unsigned char p_card,
9065c04a7b8SAlexey Dobriyan 				  unsigned char p_id_string[]);
9071da177e4SLinus Torvalds 
908391e2f25SKhalid Aziz static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card);
909391e2f25SKhalid Aziz static void FPT_autoLoadDefaultMap(u32 p_port);
9101da177e4SLinus Torvalds 
9115c04a7b8SAlexey Dobriyan static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
9125c04a7b8SAlexey Dobriyan     { {{0}} };
91313e6851aSAlexey Dobriyan static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} };
91447b5d69cSJames Bottomley  static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} };
91568d0c1aeSAlexey Dobriyan static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} };
9161da177e4SLinus Torvalds 
917db038cf8SAlexey Dobriyan static unsigned char FPT_mbCards = 0;
9185c04a7b8SAlexey Dobriyan static unsigned char FPT_scamHAString[] =
9195c04a7b8SAlexey Dobriyan     { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C',
9205c04a7b8SAlexey Dobriyan 	' ', 'B', 'T', '-', '9', '3', '0',
9215c04a7b8SAlexey Dobriyan 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
9225c04a7b8SAlexey Dobriyan 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
9235c04a7b8SAlexey Dobriyan };
9241da177e4SLinus Torvalds 
925c823feebSAlexey Dobriyan static unsigned short FPT_default_intena = 0;
9261da177e4SLinus Torvalds 
927391e2f25SKhalid Aziz static void (*FPT_s_PhaseTbl[8]) (u32, unsigned char) = {
9285c04a7b8SAlexey Dobriyan 0};
9291da177e4SLinus Torvalds 
9301da177e4SLinus Torvalds /*---------------------------------------------------------------------
9311da177e4SLinus Torvalds  *
932d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_ProbeHostAdapter
9331da177e4SLinus Torvalds  *
9341da177e4SLinus Torvalds  * Description: Setup and/or Search for cards and return info to caller.
9351da177e4SLinus Torvalds  *
9361da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
9371da177e4SLinus Torvalds 
9387f101662SAlexey Dobriyan static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
9391da177e4SLinus Torvalds {
940db038cf8SAlexey Dobriyan 	static unsigned char first_time = 1;
9411da177e4SLinus Torvalds 
942db038cf8SAlexey Dobriyan 	unsigned char i, j, id, ScamFlg;
943c823feebSAlexey Dobriyan 	unsigned short temp, temp2, temp3, temp4, temp5, temp6;
944391e2f25SKhalid Aziz 	u32 ioport;
94568d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
9461da177e4SLinus Torvalds 
9471da177e4SLinus Torvalds 	ioport = pCardInfo->si_baseaddr;
9481da177e4SLinus Torvalds 
9491da177e4SLinus Torvalds 	if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0)
9505c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9511da177e4SLinus Torvalds 
9521da177e4SLinus Torvalds 	if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1))
9535c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9541da177e4SLinus Torvalds 
9551da177e4SLinus Torvalds 	if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0))
9565c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9571da177e4SLinus Torvalds 
9581da177e4SLinus Torvalds 	if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1))
9595c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9601da177e4SLinus Torvalds 
9611da177e4SLinus Torvalds 	if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) {
9621da177e4SLinus Torvalds 
9631da177e4SLinus Torvalds /* For new Harpoon then check for sub_device ID LSB
9641da177e4SLinus Torvalds    the bits(0-3) must be all ZERO for compatible with
9651da177e4SLinus Torvalds    current version of SCCBMgr, else skip this Harpoon
9661da177e4SLinus Torvalds 	device. */
9671da177e4SLinus Torvalds 
9681da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f)
9695c1b85e2SAlexey Dobriyan 			return (int)FAILURE;
9701da177e4SLinus Torvalds 	}
9711da177e4SLinus Torvalds 
9725c04a7b8SAlexey Dobriyan 	if (first_time) {
97347b5d69cSJames Bottomley  		FPT_SccbMgrTableInitAll();
9741da177e4SLinus Torvalds 		first_time = 0;
97547b5d69cSJames Bottomley  		FPT_mbCards = 0;
9761da177e4SLinus Torvalds 	}
9771da177e4SLinus Torvalds 
97847b5d69cSJames Bottomley  	if (FPT_RdStack(ioport, 0) != 0x00) {
9795c04a7b8SAlexey Dobriyan 		if (FPT_ChkIfChipInitialized(ioport) == 0) {
9801da177e4SLinus Torvalds 			pCurrNvRam = NULL;
9811da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_semaphore, 0x00);
98247b5d69cSJames Bottomley  			FPT_XbowInit(ioport, 0);	/*Must Init the SCSI before attempting */
98347b5d69cSJames Bottomley  			FPT_DiagEEPROM(ioport);
9845c04a7b8SAlexey Dobriyan 		} else {
98547b5d69cSJames Bottomley  			if (FPT_mbCards < MAX_MB_CARDS) {
98647b5d69cSJames Bottomley  				pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
98747b5d69cSJames Bottomley  				FPT_mbCards++;
9881da177e4SLinus Torvalds 				pCurrNvRam->niBaseAddr = ioport;
98947b5d69cSJames Bottomley  				FPT_RNVRamData(pCurrNvRam);
9901da177e4SLinus Torvalds 			} else
9915c1b85e2SAlexey Dobriyan 				return (int)FAILURE;
9921da177e4SLinus Torvalds 		}
9931da177e4SLinus Torvalds 	} else
9941da177e4SLinus Torvalds 		pCurrNvRam = NULL;
9951da177e4SLinus Torvalds 
9961da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
9971da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
9981da177e4SLinus Torvalds 
9991da177e4SLinus Torvalds 	if (pCurrNvRam)
10001da177e4SLinus Torvalds 		pCardInfo->si_id = pCurrNvRam->niAdapId;
10011da177e4SLinus Torvalds 	else
10025c04a7b8SAlexey Dobriyan 		pCardInfo->si_id =
10035c04a7b8SAlexey Dobriyan 		    (unsigned
10045c04a7b8SAlexey Dobriyan 		     char)(FPT_utilEERead(ioport,
10055c04a7b8SAlexey Dobriyan 					  (ADAPTER_SCSI_ID /
10065c04a7b8SAlexey Dobriyan 					   2)) & (unsigned char)0x0FF);
10071da177e4SLinus Torvalds 
10081da177e4SLinus Torvalds 	pCardInfo->si_lun = 0x00;
10091da177e4SLinus Torvalds 	pCardInfo->si_fw_revision = ORION_FW_REV;
10101da177e4SLinus Torvalds 	temp2 = 0x0000;
10111da177e4SLinus Torvalds 	temp3 = 0x0000;
10121da177e4SLinus Torvalds 	temp4 = 0x0000;
10131da177e4SLinus Torvalds 	temp5 = 0x0000;
10141da177e4SLinus Torvalds 	temp6 = 0x0000;
10151da177e4SLinus Torvalds 
10161da177e4SLinus Torvalds 	for (id = 0; id < (16 / 2); id++) {
10171da177e4SLinus Torvalds 
10181da177e4SLinus Torvalds 		if (pCurrNvRam) {
1019c823feebSAlexey Dobriyan 			temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
10201da177e4SLinus Torvalds 			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
10211da177e4SLinus Torvalds 			    (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
10221da177e4SLinus Torvalds 		} else
10235c04a7b8SAlexey Dobriyan 			temp =
10245c04a7b8SAlexey Dobriyan 			    FPT_utilEERead(ioport,
10255c04a7b8SAlexey Dobriyan 					   (unsigned short)((SYNC_RATE_TBL / 2)
10265c04a7b8SAlexey Dobriyan 							    + id));
10271da177e4SLinus Torvalds 
10281da177e4SLinus Torvalds 		for (i = 0; i < 2; temp >>= 8, i++) {
10291da177e4SLinus Torvalds 
10301da177e4SLinus Torvalds 			temp2 >>= 1;
10311da177e4SLinus Torvalds 			temp3 >>= 1;
10321da177e4SLinus Torvalds 			temp4 >>= 1;
10331da177e4SLinus Torvalds 			temp5 >>= 1;
10341da177e4SLinus Torvalds 			temp6 >>= 1;
10355c04a7b8SAlexey Dobriyan 			switch (temp & 0x3) {
10361da177e4SLinus Torvalds 			case AUTO_RATE_20:	/* Synchronous, 20 mega-transfers/second */
1037*df561f66SGustavo A. R. Silva 				temp6 |= 0x8000;
1038*df561f66SGustavo A. R. Silva 				fallthrough;
10391da177e4SLinus Torvalds 			case AUTO_RATE_10:	/* Synchronous, 10 mega-transfers/second */
1040*df561f66SGustavo A. R. Silva 				temp5 |= 0x8000;
1041*df561f66SGustavo A. R. Silva 				fallthrough;
10421da177e4SLinus Torvalds 			case AUTO_RATE_05:	/* Synchronous, 5 mega-transfers/second */
1043*df561f66SGustavo A. R. Silva 				temp2 |= 0x8000;
1044*df561f66SGustavo A. R. Silva 				fallthrough;
10451da177e4SLinus Torvalds 			case AUTO_RATE_00:	/* Asynchronous */
10461da177e4SLinus Torvalds 				break;
10471da177e4SLinus Torvalds 			}
10481da177e4SLinus Torvalds 
10491da177e4SLinus Torvalds 			if (temp & DISC_ENABLE_BIT)
10501da177e4SLinus Torvalds 				temp3 |= 0x8000;
10511da177e4SLinus Torvalds 
10521da177e4SLinus Torvalds 			if (temp & WIDE_NEGO_BIT)
10531da177e4SLinus Torvalds 				temp4 |= 0x8000;
10541da177e4SLinus Torvalds 
10551da177e4SLinus Torvalds 		}
10561da177e4SLinus Torvalds 	}
10571da177e4SLinus Torvalds 
10581da177e4SLinus Torvalds 	pCardInfo->si_per_targ_init_sync = temp2;
10591da177e4SLinus Torvalds 	pCardInfo->si_per_targ_no_disc = temp3;
10601da177e4SLinus Torvalds 	pCardInfo->si_per_targ_wide_nego = temp4;
10611da177e4SLinus Torvalds 	pCardInfo->si_per_targ_fast_nego = temp5;
10621da177e4SLinus Torvalds 	pCardInfo->si_per_targ_ultra_nego = temp6;
10631da177e4SLinus Torvalds 
10641da177e4SLinus Torvalds 	if (pCurrNvRam)
10651da177e4SLinus Torvalds 		i = pCurrNvRam->niSysConf;
10661da177e4SLinus Torvalds 	else
10675c04a7b8SAlexey Dobriyan 		i = (unsigned
10685c04a7b8SAlexey Dobriyan 		     char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
10691da177e4SLinus Torvalds 
10701da177e4SLinus Torvalds 	if (pCurrNvRam)
10711da177e4SLinus Torvalds 		ScamFlg = pCurrNvRam->niScamConf;
10721da177e4SLinus Torvalds 	else
10735c04a7b8SAlexey Dobriyan 		ScamFlg =
10745c04a7b8SAlexey Dobriyan 		    (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
10751da177e4SLinus Torvalds 
10761da177e4SLinus Torvalds 	pCardInfo->si_flags = 0x0000;
10771da177e4SLinus Torvalds 
10781da177e4SLinus Torvalds 	if (i & 0x01)
10791da177e4SLinus Torvalds 		pCardInfo->si_flags |= SCSI_PARITY_ENA;
10801da177e4SLinus Torvalds 
10811da177e4SLinus Torvalds 	if (!(i & 0x02))
10821da177e4SLinus Torvalds 		pCardInfo->si_flags |= SOFT_RESET;
10831da177e4SLinus Torvalds 
10841da177e4SLinus Torvalds 	if (i & 0x10)
10851da177e4SLinus Torvalds 		pCardInfo->si_flags |= EXTENDED_TRANSLATION;
10861da177e4SLinus Torvalds 
10871da177e4SLinus Torvalds 	if (ScamFlg & SCAM_ENABLED)
10881da177e4SLinus Torvalds 		pCardInfo->si_flags |= FLAG_SCAM_ENABLED;
10891da177e4SLinus Torvalds 
10901da177e4SLinus Torvalds 	if (ScamFlg & SCAM_LEVEL2)
10911da177e4SLinus Torvalds 		pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;
10921da177e4SLinus Torvalds 
10931da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
10941da177e4SLinus Torvalds 	if (i & 0x04) {
10951da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_L;
10961da177e4SLinus Torvalds 	}
10971da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_bm_ctrl, j);
10981da177e4SLinus Torvalds 
10991da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
11001da177e4SLinus Torvalds 	if (i & 0x08) {
11011da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_H;
11021da177e4SLinus Torvalds 	}
11031da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_ee_ctrl, j);
11041da177e4SLinus Torvalds 
11051da177e4SLinus Torvalds 	if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
11061da177e4SLinus Torvalds 
11071da177e4SLinus Torvalds 		pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;
11081da177e4SLinus Torvalds 
11091da177e4SLinus Torvalds 	pCardInfo->si_card_family = HARPOON_FAMILY;
11101da177e4SLinus Torvalds 	pCardInfo->si_bustype = BUSTYPE_PCI;
11111da177e4SLinus Torvalds 
11121da177e4SLinus Torvalds 	if (pCurrNvRam) {
11131da177e4SLinus Torvalds 		pCardInfo->si_card_model[0] = '9';
11141da177e4SLinus Torvalds 		switch (pCurrNvRam->niModel & 0x0f) {
11151da177e4SLinus Torvalds 		case MODEL_LT:
11161da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '3';
11171da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '0';
11181da177e4SLinus Torvalds 			break;
11191da177e4SLinus Torvalds 		case MODEL_LW:
11201da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '5';
11211da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '0';
11221da177e4SLinus Torvalds 			break;
11231da177e4SLinus Torvalds 		case MODEL_DL:
11241da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '3';
11251da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '2';
11261da177e4SLinus Torvalds 			break;
11271da177e4SLinus Torvalds 		case MODEL_DW:
11281da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '5';
11291da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '2';
11301da177e4SLinus Torvalds 			break;
11311da177e4SLinus Torvalds 		}
11321da177e4SLinus Torvalds 	} else {
113347b5d69cSJames Bottomley  		temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1134db038cf8SAlexey Dobriyan 		pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
113547b5d69cSJames Bottomley  		temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
11361da177e4SLinus Torvalds 
1137db038cf8SAlexey Dobriyan 		pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1138db038cf8SAlexey Dobriyan 		pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
11391da177e4SLinus Torvalds 	}
11401da177e4SLinus Torvalds 
11415c04a7b8SAlexey Dobriyan 	if (pCardInfo->si_card_model[1] == '3') {
11421da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
11431da177e4SLinus Torvalds 			pCardInfo->si_flags |= LOW_BYTE_TERM;
11445c04a7b8SAlexey Dobriyan 	} else if (pCardInfo->si_card_model[2] == '0') {
11451da177e4SLinus Torvalds 		temp = RD_HARPOON(ioport + hp_xfer_pad);
11461da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
11471da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
11481da177e4SLinus Torvalds 			pCardInfo->si_flags |= LOW_BYTE_TERM;
11491da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
11501da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
11511da177e4SLinus Torvalds 			pCardInfo->si_flags |= HIGH_BYTE_TERM;
11521da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, temp);
11535c04a7b8SAlexey Dobriyan 	} else {
11541da177e4SLinus Torvalds 		temp = RD_HARPOON(ioport + hp_ee_ctrl);
11551da177e4SLinus Torvalds 		temp2 = RD_HARPOON(ioport + hp_xfer_pad);
11561da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
11571da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
11581da177e4SLinus Torvalds 		temp3 = 0;
11595c04a7b8SAlexey Dobriyan 		for (i = 0; i < 8; i++) {
11601da177e4SLinus Torvalds 			temp3 <<= 1;
11611da177e4SLinus Torvalds 			if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
11621da177e4SLinus Torvalds 				temp3 |= 1;
11631da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
11641da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
11651da177e4SLinus Torvalds 		}
11661da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_ee_ctrl, temp);
11671da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, temp2);
11681da177e4SLinus Torvalds 		if (!(temp3 & BIT(7)))
11691da177e4SLinus Torvalds 			pCardInfo->si_flags |= LOW_BYTE_TERM;
11701da177e4SLinus Torvalds 		if (!(temp3 & BIT(6)))
11711da177e4SLinus Torvalds 			pCardInfo->si_flags |= HIGH_BYTE_TERM;
11721da177e4SLinus Torvalds 	}
11731da177e4SLinus Torvalds 
11741da177e4SLinus Torvalds 	ARAM_ACCESS(ioport);
11751da177e4SLinus Torvalds 
11761da177e4SLinus Torvalds 	for (i = 0; i < 4; i++) {
11771da177e4SLinus Torvalds 
11781da177e4SLinus Torvalds 		pCardInfo->si_XlatInfo[i] =
11791da177e4SLinus Torvalds 		    RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
11801da177e4SLinus Torvalds 	}
11811da177e4SLinus Torvalds 
11821da177e4SLinus Torvalds 	/* return with -1 if no sort, else return with
11831da177e4SLinus Torvalds 	   logical card number sorted by BIOS (zero-based) */
11841da177e4SLinus Torvalds 
11851da177e4SLinus Torvalds 	pCardInfo->si_relative_cardnum =
11865c04a7b8SAlexey Dobriyan 	    (unsigned
11875c04a7b8SAlexey Dobriyan 	     char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
11881da177e4SLinus Torvalds 
11891da177e4SLinus Torvalds 	SGRAM_ACCESS(ioport);
11901da177e4SLinus Torvalds 
119147b5d69cSJames Bottomley  	FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
119247b5d69cSJames Bottomley  	FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
119347b5d69cSJames Bottomley  	FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
119447b5d69cSJames Bottomley  	FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
119547b5d69cSJames Bottomley  	FPT_s_PhaseTbl[4] = FPT_phaseCommand;
119647b5d69cSJames Bottomley  	FPT_s_PhaseTbl[5] = FPT_phaseStatus;
119747b5d69cSJames Bottomley  	FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
119847b5d69cSJames Bottomley  	FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
11991da177e4SLinus Torvalds 
12001da177e4SLinus Torvalds 	pCardInfo->si_present = 0x01;
12011da177e4SLinus Torvalds 
12025c1b85e2SAlexey Dobriyan 	return 0;
12031da177e4SLinus Torvalds }
12041da177e4SLinus Torvalds 
12051da177e4SLinus Torvalds /*---------------------------------------------------------------------
12061da177e4SLinus Torvalds  *
1207d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_HardwareResetHostAdapter
12081da177e4SLinus Torvalds  *
12091da177e4SLinus Torvalds  * Description: Setup adapter for normal operation (hard reset).
12101da177e4SLinus Torvalds  *
12111da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
12121da177e4SLinus Torvalds 
1213391e2f25SKhalid Aziz static void *FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
12145c04a7b8SAlexey Dobriyan 							 *pCardInfo)
12151da177e4SLinus Torvalds {
121613e6851aSAlexey Dobriyan 	struct sccb_card *CurrCard = NULL;
121768d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
1218db038cf8SAlexey Dobriyan 	unsigned char i, j, thisCard, ScamFlg;
1219c823feebSAlexey Dobriyan 	unsigned short temp, sync_bit_map, id;
1220391e2f25SKhalid Aziz 	u32 ioport;
12211da177e4SLinus Torvalds 
12221da177e4SLinus Torvalds 	ioport = pCardInfo->si_baseaddr;
12231da177e4SLinus Torvalds 
12241da177e4SLinus Torvalds 	for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
12251da177e4SLinus Torvalds 
1226391e2f25SKhalid Aziz 		if (thisCard == MAX_CARDS)
1227391e2f25SKhalid Aziz 			return (void *)FAILURE;
12281da177e4SLinus Torvalds 
122947b5d69cSJames Bottomley  		if (FPT_BL_Card[thisCard].ioPort == ioport) {
12301da177e4SLinus Torvalds 
123147b5d69cSJames Bottomley  			CurrCard = &FPT_BL_Card[thisCard];
123247b5d69cSJames Bottomley  			FPT_SccbMgrTableInitCard(CurrCard, thisCard);
12331da177e4SLinus Torvalds 			break;
12341da177e4SLinus Torvalds 		}
12351da177e4SLinus Torvalds 
123647b5d69cSJames Bottomley  		else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
12371da177e4SLinus Torvalds 
123847b5d69cSJames Bottomley  			FPT_BL_Card[thisCard].ioPort = ioport;
123947b5d69cSJames Bottomley  			CurrCard = &FPT_BL_Card[thisCard];
12401da177e4SLinus Torvalds 
124147b5d69cSJames Bottomley  			if (FPT_mbCards)
124247b5d69cSJames Bottomley  				for (i = 0; i < FPT_mbCards; i++) {
12435c04a7b8SAlexey Dobriyan 					if (CurrCard->ioPort ==
12445c04a7b8SAlexey Dobriyan 					    FPT_nvRamInfo[i].niBaseAddr)
12455c04a7b8SAlexey Dobriyan 						CurrCard->pNvRamInfo =
12465c04a7b8SAlexey Dobriyan 						    &FPT_nvRamInfo[i];
12471da177e4SLinus Torvalds 				}
124847b5d69cSJames Bottomley  			FPT_SccbMgrTableInitCard(CurrCard, thisCard);
12491da177e4SLinus Torvalds 			CurrCard->cardIndex = thisCard;
12501da177e4SLinus Torvalds 			CurrCard->cardInfo = pCardInfo;
12511da177e4SLinus Torvalds 
12521da177e4SLinus Torvalds 			break;
12531da177e4SLinus Torvalds 		}
12541da177e4SLinus Torvalds 	}
12551da177e4SLinus Torvalds 
12561da177e4SLinus Torvalds 	pCurrNvRam = CurrCard->pNvRamInfo;
12571da177e4SLinus Torvalds 
12581da177e4SLinus Torvalds 	if (pCurrNvRam) {
12591da177e4SLinus Torvalds 		ScamFlg = pCurrNvRam->niScamConf;
12605c04a7b8SAlexey Dobriyan 	} else {
12615c04a7b8SAlexey Dobriyan 		ScamFlg =
12625c04a7b8SAlexey Dobriyan 		    (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
12631da177e4SLinus Torvalds 	}
12641da177e4SLinus Torvalds 
126547b5d69cSJames Bottomley  	FPT_BusMasterInit(ioport);
126647b5d69cSJames Bottomley  	FPT_XbowInit(ioport, ScamFlg);
12671da177e4SLinus Torvalds 
126847b5d69cSJames Bottomley  	FPT_autoLoadDefaultMap(ioport);
12691da177e4SLinus Torvalds 
12705c04a7b8SAlexey Dobriyan 	for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
12715c04a7b8SAlexey Dobriyan 	}
12721da177e4SLinus Torvalds 
12731da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_selfid_0, id);
12741da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_selfid_1, 0x00);
12751da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
12761da177e4SLinus Torvalds 	CurrCard->ourId = pCardInfo->si_id;
12771da177e4SLinus Torvalds 
1278db038cf8SAlexey Dobriyan 	i = (unsigned char)pCardInfo->si_flags;
12791da177e4SLinus Torvalds 	if (i & SCSI_PARITY_ENA)
12801da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
12811da177e4SLinus Torvalds 
12821da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
12831da177e4SLinus Torvalds 	if (i & LOW_BYTE_TERM)
12841da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_L;
12851da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_bm_ctrl, j);
12861da177e4SLinus Torvalds 
12871da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
12881da177e4SLinus Torvalds 	if (i & HIGH_BYTE_TERM)
12891da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_H;
12901da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_ee_ctrl, j);
12911da177e4SLinus Torvalds 
12921da177e4SLinus Torvalds 	if (!(pCardInfo->si_flags & SOFT_RESET)) {
12931da177e4SLinus Torvalds 
129447b5d69cSJames Bottomley  		FPT_sresb(ioport, thisCard);
12951da177e4SLinus Torvalds 
129647b5d69cSJames Bottomley  		FPT_scini(thisCard, pCardInfo->si_id, 0);
12971da177e4SLinus Torvalds 	}
12981da177e4SLinus Torvalds 
12991da177e4SLinus Torvalds 	if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
13001da177e4SLinus Torvalds 		CurrCard->globalFlags |= F_NO_FILTER;
13011da177e4SLinus Torvalds 
13021da177e4SLinus Torvalds 	if (pCurrNvRam) {
13031da177e4SLinus Torvalds 		if (pCurrNvRam->niSysConf & 0x10)
13041da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_GREEN_PC;
13055c04a7b8SAlexey Dobriyan 	} else {
130647b5d69cSJames Bottomley  		if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
13071da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_GREEN_PC;
13081da177e4SLinus Torvalds 	}
13091da177e4SLinus Torvalds 
13101da177e4SLinus Torvalds 	/* Set global flag to indicate Re-Negotiation to be done on all
13111da177e4SLinus Torvalds 	   ckeck condition */
13121da177e4SLinus Torvalds 	if (pCurrNvRam) {
13131da177e4SLinus Torvalds 		if (pCurrNvRam->niScsiConf & 0x04)
13141da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_DO_RENEGO;
13155c04a7b8SAlexey Dobriyan 	} else {
131647b5d69cSJames Bottomley  		if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
13171da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_DO_RENEGO;
13181da177e4SLinus Torvalds 	}
13191da177e4SLinus Torvalds 
13201da177e4SLinus Torvalds 	if (pCurrNvRam) {
13211da177e4SLinus Torvalds 		if (pCurrNvRam->niScsiConf & 0x08)
13221da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_CONLUN_IO;
13235c04a7b8SAlexey Dobriyan 	} else {
132447b5d69cSJames Bottomley  		if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
13251da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_CONLUN_IO;
13261da177e4SLinus Torvalds 	}
13271da177e4SLinus Torvalds 
13281da177e4SLinus Torvalds 	temp = pCardInfo->si_per_targ_no_disc;
13291da177e4SLinus Torvalds 
13301da177e4SLinus Torvalds 	for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
13311da177e4SLinus Torvalds 
13321da177e4SLinus Torvalds 		if (temp & id)
133347b5d69cSJames Bottomley  			FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
13341da177e4SLinus Torvalds 	}
13351da177e4SLinus Torvalds 
13361da177e4SLinus Torvalds 	sync_bit_map = 0x0001;
13371da177e4SLinus Torvalds 
13381da177e4SLinus Torvalds 	for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
13391da177e4SLinus Torvalds 
13401da177e4SLinus Torvalds 		if (pCurrNvRam) {
1341c823feebSAlexey Dobriyan 			temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
13421da177e4SLinus Torvalds 			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
13431da177e4SLinus Torvalds 			    (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
13441da177e4SLinus Torvalds 		} else
13455c04a7b8SAlexey Dobriyan 			temp =
13465c04a7b8SAlexey Dobriyan 			    FPT_utilEERead(ioport,
13475c04a7b8SAlexey Dobriyan 					   (unsigned short)((SYNC_RATE_TBL / 2)
13485c04a7b8SAlexey Dobriyan 							    + id));
13491da177e4SLinus Torvalds 
13501da177e4SLinus Torvalds 		for (i = 0; i < 2; temp >>= 8, i++) {
13511da177e4SLinus Torvalds 
13521da177e4SLinus Torvalds 			if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
13531da177e4SLinus Torvalds 
13545c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13555c04a7b8SAlexey Dobriyan 							 i].TarEEValue =
13565c04a7b8SAlexey Dobriyan 				    (unsigned char)temp;
13571da177e4SLinus Torvalds 			}
13581da177e4SLinus Torvalds 
13591da177e4SLinus Torvalds 			else {
13605c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13615c04a7b8SAlexey Dobriyan 							 i].TarStatus |=
13625c04a7b8SAlexey Dobriyan 				    SYNC_SUPPORTED;
13635c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13645c04a7b8SAlexey Dobriyan 							 i].TarEEValue =
1365db038cf8SAlexey Dobriyan 				    (unsigned char)(temp & ~EE_SYNC_MASK);
13661da177e4SLinus Torvalds 			}
13671da177e4SLinus Torvalds 
13681da177e4SLinus Torvalds /*         if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
13691da177e4SLinus Torvalds             (id*2+i >= 8)){
13701da177e4SLinus Torvalds */
13711da177e4SLinus Torvalds 			if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
13721da177e4SLinus Torvalds 
13735c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13745c04a7b8SAlexey Dobriyan 							 i].TarEEValue |=
13755c04a7b8SAlexey Dobriyan 				    EE_WIDE_SCSI;
13761da177e4SLinus Torvalds 
13771da177e4SLinus Torvalds 			}
13781da177e4SLinus Torvalds 
13791da177e4SLinus Torvalds 			else {	/* NARROW SCSI */
13805c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13815c04a7b8SAlexey Dobriyan 							 i].TarStatus |=
13825c04a7b8SAlexey Dobriyan 				    WIDE_NEGOCIATED;
13831da177e4SLinus Torvalds 			}
13841da177e4SLinus Torvalds 
13851da177e4SLinus Torvalds 			sync_bit_map <<= 1;
13861da177e4SLinus Torvalds 
13871da177e4SLinus Torvalds 		}
13881da177e4SLinus Torvalds 	}
13891da177e4SLinus Torvalds 
13901da177e4SLinus Torvalds 	WR_HARPOON((ioport + hp_semaphore),
13915c04a7b8SAlexey Dobriyan 		   (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
13925c04a7b8SAlexey Dobriyan 				   SCCB_MGR_PRESENT));
13931da177e4SLinus Torvalds 
1394391e2f25SKhalid Aziz 	return (void *)CurrCard;
13951da177e4SLinus Torvalds }
13961da177e4SLinus Torvalds 
1397391e2f25SKhalid Aziz static void FlashPoint_ReleaseHostAdapter(void *pCurrCard)
13981da177e4SLinus Torvalds {
1399db038cf8SAlexey Dobriyan 	unsigned char i;
1400391e2f25SKhalid Aziz 	u32 portBase;
1401391e2f25SKhalid Aziz 	u32 regOffset;
1402391e2f25SKhalid Aziz 	u32 scamData;
1403391e2f25SKhalid Aziz 	u32 *pScamTbl;
140468d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
14051da177e4SLinus Torvalds 
140613e6851aSAlexey Dobriyan 	pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
14071da177e4SLinus Torvalds 
14081da177e4SLinus Torvalds 	if (pCurrNvRam) {
140947b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
141047b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
141147b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
141247b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
141347b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
14141da177e4SLinus Torvalds 
14151da177e4SLinus Torvalds 		for (i = 0; i < MAX_SCSI_TAR / 2; i++)
14165c04a7b8SAlexey Dobriyan 			FPT_WrStack(pCurrNvRam->niBaseAddr,
14175c04a7b8SAlexey Dobriyan 				    (unsigned char)(i + 5),
14185c04a7b8SAlexey Dobriyan 				    pCurrNvRam->niSyncTbl[i]);
14191da177e4SLinus Torvalds 
14201da177e4SLinus Torvalds 		portBase = pCurrNvRam->niBaseAddr;
14211da177e4SLinus Torvalds 
14221da177e4SLinus Torvalds 		for (i = 0; i < MAX_SCSI_TAR; i++) {
14231da177e4SLinus Torvalds 			regOffset = hp_aramBase + 64 + i * 4;
1424391e2f25SKhalid Aziz 			pScamTbl = (u32 *)&pCurrNvRam->niScamTbl[i];
14251da177e4SLinus Torvalds 			scamData = *pScamTbl;
14261da177e4SLinus Torvalds 			WR_HARP32(portBase, regOffset, scamData);
14271da177e4SLinus Torvalds 		}
14281da177e4SLinus Torvalds 
14291da177e4SLinus Torvalds 	} else {
143013e6851aSAlexey Dobriyan 		FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
14311da177e4SLinus Torvalds 	}
14321da177e4SLinus Torvalds }
14331da177e4SLinus Torvalds 
143468d0c1aeSAlexey Dobriyan static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
14351da177e4SLinus Torvalds {
1436db038cf8SAlexey Dobriyan 	unsigned char i;
1437391e2f25SKhalid Aziz 	u32 portBase;
1438391e2f25SKhalid Aziz 	u32 regOffset;
1439391e2f25SKhalid Aziz 	u32 scamData;
1440391e2f25SKhalid Aziz 	u32 *pScamTbl;
14411da177e4SLinus Torvalds 
144247b5d69cSJames Bottomley  	pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
144347b5d69cSJames Bottomley  	pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
144447b5d69cSJames Bottomley  	pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
144547b5d69cSJames Bottomley  	pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
144647b5d69cSJames Bottomley  	pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
14471da177e4SLinus Torvalds 
14481da177e4SLinus Torvalds 	for (i = 0; i < MAX_SCSI_TAR / 2; i++)
14495c04a7b8SAlexey Dobriyan 		pNvRamInfo->niSyncTbl[i] =
14505c04a7b8SAlexey Dobriyan 		    FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
14511da177e4SLinus Torvalds 
14521da177e4SLinus Torvalds 	portBase = pNvRamInfo->niBaseAddr;
14531da177e4SLinus Torvalds 
14541da177e4SLinus Torvalds 	for (i = 0; i < MAX_SCSI_TAR; i++) {
14551da177e4SLinus Torvalds 		regOffset = hp_aramBase + 64 + i * 4;
14561da177e4SLinus Torvalds 		RD_HARP32(portBase, regOffset, scamData);
1457391e2f25SKhalid Aziz 		pScamTbl = (u32 *)&pNvRamInfo->niScamTbl[i];
14581da177e4SLinus Torvalds 		*pScamTbl = scamData;
14591da177e4SLinus Torvalds 	}
14601da177e4SLinus Torvalds 
14611da177e4SLinus Torvalds }
14621da177e4SLinus Torvalds 
1463391e2f25SKhalid Aziz static unsigned char FPT_RdStack(u32 portBase, unsigned char index)
14641da177e4SLinus Torvalds {
14651da177e4SLinus Torvalds 	WR_HARPOON(portBase + hp_stack_addr, index);
14665c1b85e2SAlexey Dobriyan 	return RD_HARPOON(portBase + hp_stack_data);
14671da177e4SLinus Torvalds }
14681da177e4SLinus Torvalds 
1469391e2f25SKhalid Aziz static void FPT_WrStack(u32 portBase, unsigned char index, unsigned char data)
14701da177e4SLinus Torvalds {
14711da177e4SLinus Torvalds 	WR_HARPOON(portBase + hp_stack_addr, index);
14721da177e4SLinus Torvalds 	WR_HARPOON(portBase + hp_stack_data, data);
14731da177e4SLinus Torvalds }
14741da177e4SLinus Torvalds 
1475391e2f25SKhalid Aziz static unsigned char FPT_ChkIfChipInitialized(u32 ioPort)
14761da177e4SLinus Torvalds {
147747b5d69cSJames Bottomley  	if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
14785c1b85e2SAlexey Dobriyan 		return 0;
14791da177e4SLinus Torvalds 	if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
14801da177e4SLinus Torvalds 	    != CLKCTRL_DEFAULT)
14815c1b85e2SAlexey Dobriyan 		return 0;
14821da177e4SLinus Torvalds 	if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
14831da177e4SLinus Torvalds 	    (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
14845c1b85e2SAlexey Dobriyan 		return 1;
14855c1b85e2SAlexey Dobriyan 	return 0;
14861da177e4SLinus Torvalds 
14871da177e4SLinus Torvalds }
14885c04a7b8SAlexey Dobriyan 
14891da177e4SLinus Torvalds /*---------------------------------------------------------------------
14901da177e4SLinus Torvalds  *
1491d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_StartCCB
14921da177e4SLinus Torvalds  *
14931da177e4SLinus Torvalds  * Description: Start a command pointed to by p_Sccb. When the
14941da177e4SLinus Torvalds  *              command is completed it will be returned via the
14951da177e4SLinus Torvalds  *              callback function.
14961da177e4SLinus Torvalds  *
14971da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
1498391e2f25SKhalid Aziz static void FlashPoint_StartCCB(void *curr_card, struct sccb *p_Sccb)
14991da177e4SLinus Torvalds {
1500391e2f25SKhalid Aziz 	u32 ioport;
1501db038cf8SAlexey Dobriyan 	unsigned char thisCard, lun;
150269eb2ea4SAlexey Dobriyan 	struct sccb *pSaveSccb;
15031da177e4SLinus Torvalds 	CALL_BK_FN callback;
1504391e2f25SKhalid Aziz 	struct sccb_card *pCurrCard = curr_card;
15051da177e4SLinus Torvalds 
1506391e2f25SKhalid Aziz 	thisCard = pCurrCard->cardIndex;
1507391e2f25SKhalid Aziz 	ioport = pCurrCard->ioPort;
15081da177e4SLinus Torvalds 
15091377d8ddSAdrian Bunk 	if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
15101da177e4SLinus Torvalds 
15111da177e4SLinus Torvalds 		p_Sccb->HostStatus = SCCB_COMPLETE;
15121da177e4SLinus Torvalds 		p_Sccb->SccbStatus = SCCB_ERROR;
15131da177e4SLinus Torvalds 		callback = (CALL_BK_FN) p_Sccb->SccbCallback;
15141da177e4SLinus Torvalds 		if (callback)
15151da177e4SLinus Torvalds 			callback(p_Sccb);
15161da177e4SLinus Torvalds 
15171da177e4SLinus Torvalds 		return;
15181da177e4SLinus Torvalds 	}
15191da177e4SLinus Torvalds 
152047b5d69cSJames Bottomley  	FPT_sinits(p_Sccb, thisCard);
15211da177e4SLinus Torvalds 
1522391e2f25SKhalid Aziz 	if (!pCurrCard->cmdCounter) {
15235c04a7b8SAlexey Dobriyan 		WR_HARPOON(ioport + hp_semaphore,
15245c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(ioport + hp_semaphore)
15251da177e4SLinus Torvalds 			    | SCCB_MGR_ACTIVE));
15261da177e4SLinus Torvalds 
1527391e2f25SKhalid Aziz 		if (pCurrCard->globalFlags & F_GREEN_PC) {
15281da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
15291da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
15301da177e4SLinus Torvalds 		}
15311da177e4SLinus Torvalds 	}
15321da177e4SLinus Torvalds 
1533391e2f25SKhalid Aziz 	pCurrCard->cmdCounter++;
15341da177e4SLinus Torvalds 
15351da177e4SLinus Torvalds 	if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
15361da177e4SLinus Torvalds 
15375c04a7b8SAlexey Dobriyan 		WR_HARPOON(ioport + hp_semaphore,
15385c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(ioport + hp_semaphore)
15391da177e4SLinus Torvalds 			    | TICKLE_ME));
15405c04a7b8SAlexey Dobriyan 		if (p_Sccb->OperationCode == RESET_COMMAND) {
15415c04a7b8SAlexey Dobriyan 			pSaveSccb =
1542391e2f25SKhalid Aziz 			    pCurrCard->currentSCCB;
1543391e2f25SKhalid Aziz 			pCurrCard->currentSCCB = p_Sccb;
154447b5d69cSJames Bottomley  			FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1545391e2f25SKhalid Aziz 			pCurrCard->currentSCCB =
15465c04a7b8SAlexey Dobriyan 			    pSaveSccb;
15475c04a7b8SAlexey Dobriyan 		} else {
154847b5d69cSJames Bottomley  			FPT_queueAddSccb(p_Sccb, thisCard);
15491da177e4SLinus Torvalds 		}
15501da177e4SLinus Torvalds 	}
15511da177e4SLinus Torvalds 
15521da177e4SLinus Torvalds 	else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
15531da177e4SLinus Torvalds 
15545c04a7b8SAlexey Dobriyan 		if (p_Sccb->OperationCode == RESET_COMMAND) {
15555c04a7b8SAlexey Dobriyan 			pSaveSccb =
1556391e2f25SKhalid Aziz 			    pCurrCard->currentSCCB;
1557391e2f25SKhalid Aziz 			pCurrCard->currentSCCB = p_Sccb;
155847b5d69cSJames Bottomley  			FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1559391e2f25SKhalid Aziz 			pCurrCard->currentSCCB =
15605c04a7b8SAlexey Dobriyan 			    pSaveSccb;
15615c04a7b8SAlexey Dobriyan 		} else {
156247b5d69cSJames Bottomley  			FPT_queueAddSccb(p_Sccb, thisCard);
15631da177e4SLinus Torvalds 		}
15641da177e4SLinus Torvalds 	}
15651da177e4SLinus Torvalds 
15661da177e4SLinus Torvalds 	else {
15671da177e4SLinus Torvalds 
15681da177e4SLinus Torvalds 		MDISABLE_INT(ioport);
15691da177e4SLinus Torvalds 
1570391e2f25SKhalid Aziz 		if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
15715c04a7b8SAlexey Dobriyan 		    ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
15725c04a7b8SAlexey Dobriyan 		      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
15731da177e4SLinus Torvalds 			lun = p_Sccb->Lun;
15741da177e4SLinus Torvalds 		else
15751da177e4SLinus Torvalds 			lun = 0;
1576391e2f25SKhalid Aziz 		if ((pCurrCard->currentSCCB == NULL) &&
15775c04a7b8SAlexey Dobriyan 		    (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
15785c04a7b8SAlexey Dobriyan 		    && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
157947b5d69cSJames Bottomley  			== 0)) {
15801da177e4SLinus Torvalds 
1581391e2f25SKhalid Aziz 			pCurrCard->currentSCCB = p_Sccb;
158247b5d69cSJames Bottomley  			FPT_ssel(p_Sccb->SccbIOPort, thisCard);
15831da177e4SLinus Torvalds 		}
15841da177e4SLinus Torvalds 
15851da177e4SLinus Torvalds 		else {
15861da177e4SLinus Torvalds 
15875c04a7b8SAlexey Dobriyan 			if (p_Sccb->OperationCode == RESET_COMMAND) {
1588391e2f25SKhalid Aziz 				pSaveSccb = pCurrCard->currentSCCB;
1589391e2f25SKhalid Aziz 				pCurrCard->currentSCCB = p_Sccb;
15905c04a7b8SAlexey Dobriyan 				FPT_queueSelectFail(&FPT_BL_Card[thisCard],
15915c04a7b8SAlexey Dobriyan 						    thisCard);
1592391e2f25SKhalid Aziz 				pCurrCard->currentSCCB = pSaveSccb;
15935c04a7b8SAlexey Dobriyan 			} else {
159447b5d69cSJames Bottomley  				FPT_queueAddSccb(p_Sccb, thisCard);
15951da177e4SLinus Torvalds 			}
15961da177e4SLinus Torvalds 		}
15971da177e4SLinus Torvalds 
15981da177e4SLinus Torvalds 		MENABLE_INT(ioport);
15991da177e4SLinus Torvalds 	}
16001da177e4SLinus Torvalds 
16011da177e4SLinus Torvalds }
16021da177e4SLinus Torvalds 
16031da177e4SLinus Torvalds /*---------------------------------------------------------------------
16041da177e4SLinus Torvalds  *
1605d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_AbortCCB
16061da177e4SLinus Torvalds  *
16071da177e4SLinus Torvalds  * Description: Abort the command pointed to by p_Sccb.  When the
16081da177e4SLinus Torvalds  *              command is completed it will be returned via the
16091da177e4SLinus Torvalds  *              callback function.
16101da177e4SLinus Torvalds  *
16111da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
1612391e2f25SKhalid Aziz static int FlashPoint_AbortCCB(void *pCurrCard, struct sccb *p_Sccb)
16131da177e4SLinus Torvalds {
1614391e2f25SKhalid Aziz 	u32 ioport;
16151da177e4SLinus Torvalds 
1616db038cf8SAlexey Dobriyan 	unsigned char thisCard;
16171da177e4SLinus Torvalds 	CALL_BK_FN callback;
1618db038cf8SAlexey Dobriyan 	unsigned char TID;
161969eb2ea4SAlexey Dobriyan 	struct sccb *pSaveSCCB;
1620f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
16211da177e4SLinus Torvalds 
162213e6851aSAlexey Dobriyan 	ioport = ((struct sccb_card *)pCurrCard)->ioPort;
16231da177e4SLinus Torvalds 
162413e6851aSAlexey Dobriyan 	thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
16251da177e4SLinus Torvalds 
16265c04a7b8SAlexey Dobriyan 	if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
16271da177e4SLinus Torvalds 
16285c04a7b8SAlexey Dobriyan 		if (FPT_queueFindSccb(p_Sccb, thisCard)) {
16291da177e4SLinus Torvalds 
163013e6851aSAlexey Dobriyan 			((struct sccb_card *)pCurrCard)->cmdCounter--;
16311da177e4SLinus Torvalds 
163213e6851aSAlexey Dobriyan 			if (!((struct sccb_card *)pCurrCard)->cmdCounter)
16335c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_semaphore,
16345c04a7b8SAlexey Dobriyan 					   (RD_HARPOON(ioport + hp_semaphore)
16355c04a7b8SAlexey Dobriyan 					    & (unsigned
16365c04a7b8SAlexey Dobriyan 					       char)(~(SCCB_MGR_ACTIVE |
16375c04a7b8SAlexey Dobriyan 						       TICKLE_ME))));
16381da177e4SLinus Torvalds 
16391da177e4SLinus Torvalds 			p_Sccb->SccbStatus = SCCB_ABORT;
16401da177e4SLinus Torvalds 			callback = p_Sccb->SccbCallback;
16411da177e4SLinus Torvalds 			callback(p_Sccb);
16421da177e4SLinus Torvalds 
16435c1b85e2SAlexey Dobriyan 			return 0;
16441da177e4SLinus Torvalds 		}
16451da177e4SLinus Torvalds 
16465c04a7b8SAlexey Dobriyan 		else {
16475c04a7b8SAlexey Dobriyan 			if (((struct sccb_card *)pCurrCard)->currentSCCB ==
16485c04a7b8SAlexey Dobriyan 			    p_Sccb) {
16491da177e4SLinus Torvalds 				p_Sccb->SccbStatus = SCCB_ABORT;
16505c1b85e2SAlexey Dobriyan 				return 0;
16511da177e4SLinus Torvalds 
16521da177e4SLinus Torvalds 			}
16531da177e4SLinus Torvalds 
16545c04a7b8SAlexey Dobriyan 			else {
16551da177e4SLinus Torvalds 
16561da177e4SLinus Torvalds 				TID = p_Sccb->TargID;
16571da177e4SLinus Torvalds 
16585c04a7b8SAlexey Dobriyan 				if (p_Sccb->Sccb_tag) {
16591da177e4SLinus Torvalds 					MDISABLE_INT(ioport);
16605c04a7b8SAlexey Dobriyan 					if (((struct sccb_card *)pCurrCard)->
16615c04a7b8SAlexey Dobriyan 					    discQ_Tbl[p_Sccb->Sccb_tag] ==
16625c04a7b8SAlexey Dobriyan 					    p_Sccb) {
16631da177e4SLinus Torvalds 						p_Sccb->SccbStatus = SCCB_ABORT;
16645c04a7b8SAlexey Dobriyan 						p_Sccb->Sccb_scsistat =
16655c04a7b8SAlexey Dobriyan 						    ABORT_ST;
16665c04a7b8SAlexey Dobriyan 						p_Sccb->Sccb_scsimsg =
16675c04a7b8SAlexey Dobriyan 						    SMABORT_TAG;
16681da177e4SLinus Torvalds 
16695c04a7b8SAlexey Dobriyan 						if (((struct sccb_card *)
16705c04a7b8SAlexey Dobriyan 						     pCurrCard)->currentSCCB ==
16715c04a7b8SAlexey Dobriyan 						    NULL) {
16725c04a7b8SAlexey Dobriyan 							((struct sccb_card *)
16735c04a7b8SAlexey Dobriyan 							 pCurrCard)->
16745c04a7b8SAlexey Dobriyan 					currentSCCB = p_Sccb;
16755c04a7b8SAlexey Dobriyan 							FPT_ssel(ioport,
16765c04a7b8SAlexey Dobriyan 								 thisCard);
16775c04a7b8SAlexey Dobriyan 						} else {
16785c04a7b8SAlexey Dobriyan 							pSaveSCCB =
16795c04a7b8SAlexey Dobriyan 							    ((struct sccb_card
16805c04a7b8SAlexey Dobriyan 							      *)pCurrCard)->
16815c04a7b8SAlexey Dobriyan 							    currentSCCB;
16825c04a7b8SAlexey Dobriyan 							((struct sccb_card *)
16835c04a7b8SAlexey Dobriyan 							 pCurrCard)->
16845c04a7b8SAlexey Dobriyan 					currentSCCB = p_Sccb;
168513e6851aSAlexey Dobriyan 							FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
16865c04a7b8SAlexey Dobriyan 							((struct sccb_card *)
16875c04a7b8SAlexey Dobriyan 							 pCurrCard)->
16885c04a7b8SAlexey Dobriyan 					currentSCCB = pSaveSCCB;
16891da177e4SLinus Torvalds 						}
16901da177e4SLinus Torvalds 					}
16911da177e4SLinus Torvalds 					MENABLE_INT(ioport);
16925c1b85e2SAlexey Dobriyan 					return 0;
16935c04a7b8SAlexey Dobriyan 				} else {
16945c04a7b8SAlexey Dobriyan 					currTar_Info =
16955c04a7b8SAlexey Dobriyan 					    &FPT_sccbMgrTbl[thisCard][p_Sccb->
16965c04a7b8SAlexey Dobriyan 								      TargID];
16971da177e4SLinus Torvalds 
16985c04a7b8SAlexey Dobriyan 					if (FPT_BL_Card[thisCard].
16995c04a7b8SAlexey Dobriyan 					    discQ_Tbl[currTar_Info->
17005c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[p_Sccb->Lun]]
17015c04a7b8SAlexey Dobriyan 					    == p_Sccb) {
17021da177e4SLinus Torvalds 						p_Sccb->SccbStatus = SCCB_ABORT;
17035c1b85e2SAlexey Dobriyan 						return 0;
17041da177e4SLinus Torvalds 					}
17051da177e4SLinus Torvalds 				}
17061da177e4SLinus Torvalds 			}
17071da177e4SLinus Torvalds 		}
17081da177e4SLinus Torvalds 	}
17095c1b85e2SAlexey Dobriyan 	return -1;
17101da177e4SLinus Torvalds }
17111da177e4SLinus Torvalds 
17121da177e4SLinus Torvalds /*---------------------------------------------------------------------
17131da177e4SLinus Torvalds  *
1714d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_InterruptPending
17151da177e4SLinus Torvalds  *
17161da177e4SLinus Torvalds  * Description: Do a quick check to determine if there is a pending
17171da177e4SLinus Torvalds  *              interrupt for this card and disable the IRQ Pin if so.
17181da177e4SLinus Torvalds  *
17191da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
1720391e2f25SKhalid Aziz static unsigned char FlashPoint_InterruptPending(void *pCurrCard)
17211da177e4SLinus Torvalds {
1722391e2f25SKhalid Aziz 	u32 ioport;
17231da177e4SLinus Torvalds 
172413e6851aSAlexey Dobriyan 	ioport = ((struct sccb_card *)pCurrCard)->ioPort;
17251da177e4SLinus Torvalds 
17265c04a7b8SAlexey Dobriyan 	if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
17275c1b85e2SAlexey Dobriyan 		return 1;
17281da177e4SLinus Torvalds 	}
17291da177e4SLinus Torvalds 
17301da177e4SLinus Torvalds 	else
17311da177e4SLinus Torvalds 
17325c1b85e2SAlexey Dobriyan 		return 0;
17331da177e4SLinus Torvalds }
17341da177e4SLinus Torvalds 
17351da177e4SLinus Torvalds /*---------------------------------------------------------------------
17361da177e4SLinus Torvalds  *
1737d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_HandleInterrupt
17381da177e4SLinus Torvalds  *
17391da177e4SLinus Torvalds  * Description: This is our entry point when an interrupt is generated
17401da177e4SLinus Torvalds  *              by the card and the upper level driver passes it on to
17411da177e4SLinus Torvalds  *              us.
17421da177e4SLinus Torvalds  *
17431da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
1744391e2f25SKhalid Aziz static int FlashPoint_HandleInterrupt(void *pcard)
17451da177e4SLinus Torvalds {
174669eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
1747db038cf8SAlexey Dobriyan 	unsigned char thisCard, result, bm_status, bm_int_st;
1748c823feebSAlexey Dobriyan 	unsigned short hp_int;
1749db038cf8SAlexey Dobriyan 	unsigned char i, target;
1750391e2f25SKhalid Aziz 	struct sccb_card *pCurrCard = pcard;
1751391e2f25SKhalid Aziz 	u32 ioport;
17521da177e4SLinus Torvalds 
1753391e2f25SKhalid Aziz 	thisCard = pCurrCard->cardIndex;
1754391e2f25SKhalid Aziz 	ioport = pCurrCard->ioPort;
17551da177e4SLinus Torvalds 
17561da177e4SLinus Torvalds 	MDISABLE_INT(ioport);
17571da177e4SLinus Torvalds 
17581da177e4SLinus Torvalds 	if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON)
1759391e2f25SKhalid Aziz 		bm_status = RD_HARPOON(ioport + hp_ext_status) &
1760391e2f25SKhalid Aziz 					(unsigned char)BAD_EXT_STATUS;
17611da177e4SLinus Torvalds 	else
17621da177e4SLinus Torvalds 		bm_status = 0;
17631da177e4SLinus Torvalds 
17641da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
17651da177e4SLinus Torvalds 
1766391e2f25SKhalid Aziz 	while ((hp_int = RDW_HARPOON((ioport + hp_intstat)) &
1767391e2f25SKhalid Aziz 				FPT_default_intena) | bm_status) {
17681da177e4SLinus Torvalds 
1769391e2f25SKhalid Aziz 		currSCCB = pCurrCard->currentSCCB;
17701da177e4SLinus Torvalds 
17711da177e4SLinus Torvalds 		if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
17725c04a7b8SAlexey Dobriyan 			result =
1773391e2f25SKhalid Aziz 			    FPT_SccbMgr_bad_isr(ioport, thisCard, pCurrCard,
17745c04a7b8SAlexey Dobriyan 						hp_int);
17755c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
17765c04a7b8SAlexey Dobriyan 				    (FIFO | TIMEOUT | RESET | SCAM_SEL));
17771da177e4SLinus Torvalds 			bm_status = 0;
17781da177e4SLinus Torvalds 
17791da177e4SLinus Torvalds 			if (result) {
17801da177e4SLinus Torvalds 
17811da177e4SLinus Torvalds 				MENABLE_INT(ioport);
17825c1b85e2SAlexey Dobriyan 				return result;
17831da177e4SLinus Torvalds 			}
17841da177e4SLinus Torvalds 		}
17851da177e4SLinus Torvalds 
17861da177e4SLinus Torvalds 		else if (hp_int & ICMD_COMP) {
17871da177e4SLinus Torvalds 
17881da177e4SLinus Torvalds 			if (!(hp_int & BUS_FREE)) {
17891da177e4SLinus Torvalds 				/* Wait for the BusFree before starting a new command.  We
17901da177e4SLinus Torvalds 				   must also check for being reselected since the BusFree
17911da177e4SLinus Torvalds 				   may not show up if another device reselects us in 1.5us or
17921da177e4SLinus Torvalds 				   less.  SRR Wednesday, 3/8/1995.
17931da177e4SLinus Torvalds 				 */
17945c04a7b8SAlexey Dobriyan 				while (!
17955c04a7b8SAlexey Dobriyan 				       (RDW_HARPOON((ioport + hp_intstat)) &
17965c04a7b8SAlexey Dobriyan 					(BUS_FREE | RSEL))) ;
17971da177e4SLinus Torvalds 			}
17981da177e4SLinus Torvalds 
1799391e2f25SKhalid Aziz 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
18001da177e4SLinus Torvalds 
180147b5d69cSJames Bottomley  				FPT_phaseChkFifo(ioport, thisCard);
18021da177e4SLinus Torvalds 
18031da177e4SLinus Torvalds /*         WRW_HARPOON((ioport+hp_intstat),
18041da177e4SLinus Torvalds             (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
18051da177e4SLinus Torvalds          */
18061da177e4SLinus Torvalds 
18071da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
18081da177e4SLinus Torvalds 
180947b5d69cSJames Bottomley  			FPT_autoCmdCmplt(ioport, thisCard);
18101da177e4SLinus Torvalds 
18111da177e4SLinus Torvalds 		}
18121da177e4SLinus Torvalds 
18135c04a7b8SAlexey Dobriyan 		else if (hp_int & ITAR_DISC) {
18141da177e4SLinus Torvalds 
1815391e2f25SKhalid Aziz 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
181647b5d69cSJames Bottomley  				FPT_phaseChkFifo(ioport, thisCard);
18171da177e4SLinus Torvalds 
1818391e2f25SKhalid Aziz 			if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1819391e2f25SKhalid Aziz 					SMSAVE_DATA_PTR) {
18201da177e4SLinus Torvalds 
18211da177e4SLinus Torvalds 				WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
18221da177e4SLinus Torvalds 				currSCCB->Sccb_XferState |= F_NO_DATA_YET;
18231da177e4SLinus Torvalds 
18241da177e4SLinus Torvalds 				currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
18251da177e4SLinus Torvalds 			}
18261da177e4SLinus Torvalds 
18271da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = DISCONNECT_ST;
182847b5d69cSJames Bottomley  			FPT_queueDisconnect(currSCCB, thisCard);
18291da177e4SLinus Torvalds 
18301da177e4SLinus Torvalds 			/* Wait for the BusFree before starting a new command.  We
18311da177e4SLinus Torvalds 			   must also check for being reselected since the BusFree
18321da177e4SLinus Torvalds 			   may not show up if another device reselects us in 1.5us or
18331da177e4SLinus Torvalds 			   less.  SRR Wednesday, 3/8/1995.
18341da177e4SLinus Torvalds 			 */
18355c04a7b8SAlexey Dobriyan 			while (!
18365c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((ioport + hp_intstat)) &
18375c04a7b8SAlexey Dobriyan 				(BUS_FREE | RSEL))
18385c04a7b8SAlexey Dobriyan 			       && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
18395c04a7b8SAlexey Dobriyan 				    && RD_HARPOON((ioport + hp_scsisig)) ==
18405c04a7b8SAlexey Dobriyan 				    (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
18415c04a7b8SAlexey Dobriyan 				     SCSI_IOBIT))) ;
18421da177e4SLinus Torvalds 
18431da177e4SLinus Torvalds 			/*
18441da177e4SLinus Torvalds 			   The additional loop exit condition above detects a timing problem
18451da177e4SLinus Torvalds 			   with the revision D/E harpoon chips.  The caller should reset the
18461da177e4SLinus Torvalds 			   host adapter to recover when 0xFE is returned.
18471da177e4SLinus Torvalds 			 */
18485c04a7b8SAlexey Dobriyan 			if (!
18495c04a7b8SAlexey Dobriyan 			    (RDW_HARPOON((ioport + hp_intstat)) &
18505c04a7b8SAlexey Dobriyan 			     (BUS_FREE | RSEL))) {
18511da177e4SLinus Torvalds 				MENABLE_INT(ioport);
18521da177e4SLinus Torvalds 				return 0xFE;
18531da177e4SLinus Torvalds 			}
18541da177e4SLinus Torvalds 
18555c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
18565c04a7b8SAlexey Dobriyan 				    (BUS_FREE | ITAR_DISC));
18571da177e4SLinus Torvalds 
1858391e2f25SKhalid Aziz 			pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
18591da177e4SLinus Torvalds 
18601da177e4SLinus Torvalds 		}
18611da177e4SLinus Torvalds 
18621da177e4SLinus Torvalds 		else if (hp_int & RSEL) {
18631da177e4SLinus Torvalds 
18645c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
18655c04a7b8SAlexey Dobriyan 				    (PROG_HLT | RSEL | PHASE | BUS_FREE));
18661da177e4SLinus Torvalds 
18675c04a7b8SAlexey Dobriyan 			if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
1868391e2f25SKhalid Aziz 				if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
186947b5d69cSJames Bottomley  					FPT_phaseChkFifo(ioport, thisCard);
18701da177e4SLinus Torvalds 
18715c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(ioport + hp_gp_reg_1) ==
18725c04a7b8SAlexey Dobriyan 				    SMSAVE_DATA_PTR) {
18731da177e4SLinus Torvalds 					WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
18745c04a7b8SAlexey Dobriyan 					currSCCB->Sccb_XferState |=
18755c04a7b8SAlexey Dobriyan 					    F_NO_DATA_YET;
18765c04a7b8SAlexey Dobriyan 					currSCCB->Sccb_savedATC =
18775c04a7b8SAlexey Dobriyan 					    currSCCB->Sccb_ATC;
18781da177e4SLinus Torvalds 				}
18791da177e4SLinus Torvalds 
18805c04a7b8SAlexey Dobriyan 				WRW_HARPOON((ioport + hp_intstat),
18815c04a7b8SAlexey Dobriyan 					    (BUS_FREE | ITAR_DISC));
18821da177e4SLinus Torvalds 				currSCCB->Sccb_scsistat = DISCONNECT_ST;
188347b5d69cSJames Bottomley  				FPT_queueDisconnect(currSCCB, thisCard);
18841da177e4SLinus Torvalds 			}
18851da177e4SLinus Torvalds 
1886391e2f25SKhalid Aziz 			FPT_sres(ioport, thisCard, pCurrCard);
188747b5d69cSJames Bottomley  			FPT_phaseDecode(ioport, thisCard);
18881da177e4SLinus Torvalds 
18891da177e4SLinus Torvalds 		}
18901da177e4SLinus Torvalds 
18915c04a7b8SAlexey Dobriyan 		else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
18921da177e4SLinus Torvalds 
18935c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
18945c04a7b8SAlexey Dobriyan 				    (IDO_STRT | XFER_CNT_0));
189547b5d69cSJames Bottomley  			FPT_phaseDecode(ioport, thisCard);
18961da177e4SLinus Torvalds 
18971da177e4SLinus Torvalds 		}
18981da177e4SLinus Torvalds 
18995c04a7b8SAlexey Dobriyan 		else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
19005c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
19015c04a7b8SAlexey Dobriyan 				    (PHASE | IUNKWN | PROG_HLT));
19025c04a7b8SAlexey Dobriyan 			if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
19035c04a7b8SAlexey Dobriyan 			     0x3f) < (unsigned char)SELCHK) {
190447b5d69cSJames Bottomley  				FPT_phaseDecode(ioport, thisCard);
19055c04a7b8SAlexey Dobriyan 			} else {
19061da177e4SLinus Torvalds 				/* Harpoon problem some SCSI target device respond to selection
19071da177e4SLinus Torvalds 				   with short BUSY pulse (<400ns) this will make the Harpoon is not able
19081da177e4SLinus Torvalds 				   to latch the correct Target ID into reg. x53.
19091da177e4SLinus Torvalds 				   The work around require to correct this reg. But when write to this
19101da177e4SLinus Torvalds 				   reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
19111da177e4SLinus Torvalds 				   need to read this reg first then restore it later. After update to 0x53 */
19121da177e4SLinus Torvalds 
19135c04a7b8SAlexey Dobriyan 				i = (unsigned
19145c04a7b8SAlexey Dobriyan 				     char)(RD_HARPOON(ioport + hp_fifowrite));
19155c04a7b8SAlexey Dobriyan 				target =
19165c04a7b8SAlexey Dobriyan 				    (unsigned
19175c04a7b8SAlexey Dobriyan 				     char)(RD_HARPOON(ioport + hp_gp_reg_3));
19185c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_xfer_pad,
19195c04a7b8SAlexey Dobriyan 					   (unsigned char)ID_UNLOCK);
19205c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_select_id,
19215c04a7b8SAlexey Dobriyan 					   (unsigned char)(target | target <<
19225c04a7b8SAlexey Dobriyan 							   4));
19235c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_xfer_pad,
19245c04a7b8SAlexey Dobriyan 					   (unsigned char)0x00);
19251da177e4SLinus Torvalds 				WR_HARPOON(ioport + hp_fifowrite, i);
19265c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_autostart_3,
19275c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + TAG_STRT));
19281da177e4SLinus Torvalds 			}
19291da177e4SLinus Torvalds 		}
19301da177e4SLinus Torvalds 
19311da177e4SLinus Torvalds 		else if (hp_int & XFER_CNT_0) {
19321da177e4SLinus Torvalds 
19331da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
19341da177e4SLinus Torvalds 
193547b5d69cSJames Bottomley  			FPT_schkdd(ioport, thisCard);
19361da177e4SLinus Torvalds 
19371da177e4SLinus Torvalds 		}
19381da177e4SLinus Torvalds 
19391da177e4SLinus Torvalds 		else if (hp_int & BUS_FREE) {
19401da177e4SLinus Torvalds 
19411da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
19421da177e4SLinus Torvalds 
1943391e2f25SKhalid Aziz 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
19441da177e4SLinus Torvalds 
19455c04a7b8SAlexey Dobriyan 				FPT_hostDataXferAbort(ioport, thisCard,
19465c04a7b8SAlexey Dobriyan 						      currSCCB);
19471da177e4SLinus Torvalds 			}
19481da177e4SLinus Torvalds 
194947b5d69cSJames Bottomley  			FPT_phaseBusFree(ioport, thisCard);
19501da177e4SLinus Torvalds 		}
19511da177e4SLinus Torvalds 
19521da177e4SLinus Torvalds 		else if (hp_int & ITICKLE) {
19531da177e4SLinus Torvalds 
19541da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), ITICKLE);
1955391e2f25SKhalid Aziz 			pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
19561da177e4SLinus Torvalds 		}
19571da177e4SLinus Torvalds 
19585c04a7b8SAlexey Dobriyan 		if (((struct sccb_card *)pCurrCard)->
19595c04a7b8SAlexey Dobriyan 		    globalFlags & F_NEW_SCCB_CMD) {
19601da177e4SLinus Torvalds 
1961391e2f25SKhalid Aziz 			pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
19621da177e4SLinus Torvalds 
1963391e2f25SKhalid Aziz 			if (pCurrCard->currentSCCB == NULL)
1964391e2f25SKhalid Aziz 				FPT_queueSearchSelect(pCurrCard, thisCard);
19651da177e4SLinus Torvalds 
1966391e2f25SKhalid Aziz 			if (pCurrCard->currentSCCB != NULL) {
1967391e2f25SKhalid Aziz 				pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
196847b5d69cSJames Bottomley  				FPT_ssel(ioport, thisCard);
19691da177e4SLinus Torvalds 			}
19701da177e4SLinus Torvalds 
19711da177e4SLinus Torvalds 			break;
19721da177e4SLinus Torvalds 
19731da177e4SLinus Torvalds 		}
19741da177e4SLinus Torvalds 
19751da177e4SLinus Torvalds 	}			/*end while */
19761da177e4SLinus Torvalds 
19771da177e4SLinus Torvalds 	MENABLE_INT(ioport);
19781da177e4SLinus Torvalds 
19795c1b85e2SAlexey Dobriyan 	return 0;
19801da177e4SLinus Torvalds }
19811da177e4SLinus Torvalds 
19821da177e4SLinus Torvalds /*---------------------------------------------------------------------
19831da177e4SLinus Torvalds  *
19841da177e4SLinus Torvalds  * Function: Sccb_bad_isr
19851da177e4SLinus Torvalds  *
19861da177e4SLinus Torvalds  * Description: Some type of interrupt has occurred which is slightly
19871da177e4SLinus Torvalds  *              out of the ordinary.  We will now decode it fully, in
19881da177e4SLinus Torvalds  *              this routine.  This is broken up in an attempt to save
19891da177e4SLinus Torvalds  *              processing time.
19901da177e4SLinus Torvalds  *
19911da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
1992391e2f25SKhalid Aziz static unsigned char FPT_SccbMgr_bad_isr(u32 p_port, unsigned char p_card,
19935c04a7b8SAlexey Dobriyan 					 struct sccb_card *pCurrCard,
19945c04a7b8SAlexey Dobriyan 					 unsigned short p_int)
19951da177e4SLinus Torvalds {
1996db038cf8SAlexey Dobriyan 	unsigned char temp, ScamFlg;
1997f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
199868d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
19991da177e4SLinus Torvalds 
20001da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_ext_status) &
20015c04a7b8SAlexey Dobriyan 	    (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
20021da177e4SLinus Torvalds 
20035c04a7b8SAlexey Dobriyan 		if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
20041da177e4SLinus Torvalds 
20055c04a7b8SAlexey Dobriyan 			FPT_hostDataXferAbort(p_port, p_card,
20065c04a7b8SAlexey Dobriyan 					      pCurrCard->currentSCCB);
20071da177e4SLinus Torvalds 		}
20081da177e4SLinus Torvalds 
20091da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
20101da177e4SLinus Torvalds 		{
20111da177e4SLinus Torvalds 			WR_HARPOON(p_port + hp_pci_stat_cfg,
20125c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(p_port + hp_pci_stat_cfg) &
20135c04a7b8SAlexey Dobriyan 				    ~REC_MASTER_ABORT));
20141da177e4SLinus Torvalds 
20151da177e4SLinus Torvalds 			WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
20161da177e4SLinus Torvalds 
20171da177e4SLinus Torvalds 		}
20181da177e4SLinus Torvalds 
20195c04a7b8SAlexey Dobriyan 		if (pCurrCard->currentSCCB != NULL) {
20201da177e4SLinus Torvalds 
20211da177e4SLinus Torvalds 			if (!pCurrCard->currentSCCB->HostStatus)
20225c04a7b8SAlexey Dobriyan 				pCurrCard->currentSCCB->HostStatus =
20235c04a7b8SAlexey Dobriyan 				    SCCB_BM_ERR;
20241da177e4SLinus Torvalds 
202547b5d69cSJames Bottomley  			FPT_sxfrp(p_port, p_card);
20261da177e4SLinus Torvalds 
2027db038cf8SAlexey Dobriyan 			temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
20281da177e4SLinus Torvalds 					       (EXT_ARB_ACK | SCSI_TERM_ENA_H));
20295c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_ee_ctrl,
20305c04a7b8SAlexey Dobriyan 				   ((unsigned char)temp | SEE_MS | SEE_CS));
20311da177e4SLinus Torvalds 			WR_HARPOON(p_port + hp_ee_ctrl, temp);
20321da177e4SLinus Torvalds 
20335c04a7b8SAlexey Dobriyan 			if (!
20345c04a7b8SAlexey Dobriyan 			    (RDW_HARPOON((p_port + hp_intstat)) &
20355c04a7b8SAlexey Dobriyan 			     (BUS_FREE | RESET))) {
203647b5d69cSJames Bottomley  				FPT_phaseDecode(p_port, p_card);
20371da177e4SLinus Torvalds 			}
20381da177e4SLinus Torvalds 		}
20391da177e4SLinus Torvalds 	}
20401da177e4SLinus Torvalds 
20415c04a7b8SAlexey Dobriyan 	else if (p_int & RESET) {
20421da177e4SLinus Torvalds 
20431da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
20441da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
20451da177e4SLinus Torvalds 		if (pCurrCard->currentSCCB != NULL) {
20461da177e4SLinus Torvalds 
20471da177e4SLinus Torvalds 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
20481da177e4SLinus Torvalds 
20495c04a7b8SAlexey Dobriyan 				FPT_hostDataXferAbort(p_port, p_card,
20505c04a7b8SAlexey Dobriyan 						      pCurrCard->currentSCCB);
20511da177e4SLinus Torvalds 		}
20521da177e4SLinus Torvalds 
20531da177e4SLinus Torvalds 		DISABLE_AUTO(p_port);
20541da177e4SLinus Torvalds 
205547b5d69cSJames Bottomley  		FPT_sresb(p_port, p_card);
20561da177e4SLinus Torvalds 
20575c04a7b8SAlexey Dobriyan 		while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
20585c04a7b8SAlexey Dobriyan 		}
20591da177e4SLinus Torvalds 
20601da177e4SLinus Torvalds 		pCurrNvRam = pCurrCard->pNvRamInfo;
20611da177e4SLinus Torvalds 		if (pCurrNvRam) {
20621da177e4SLinus Torvalds 			ScamFlg = pCurrNvRam->niScamConf;
20635c04a7b8SAlexey Dobriyan 		} else {
20645c04a7b8SAlexey Dobriyan 			ScamFlg =
20655c04a7b8SAlexey Dobriyan 			    (unsigned char)FPT_utilEERead(p_port,
20665c04a7b8SAlexey Dobriyan 							  SCAM_CONFIG / 2);
20671da177e4SLinus Torvalds 		}
20681da177e4SLinus Torvalds 
206947b5d69cSJames Bottomley  		FPT_XbowInit(p_port, ScamFlg);
20701da177e4SLinus Torvalds 
207147b5d69cSJames Bottomley  		FPT_scini(p_card, pCurrCard->ourId, 0);
20721da177e4SLinus Torvalds 
20735c1b85e2SAlexey Dobriyan 		return 0xFF;
20741da177e4SLinus Torvalds 	}
20751da177e4SLinus Torvalds 
20761da177e4SLinus Torvalds 	else if (p_int & FIFO) {
20771da177e4SLinus Torvalds 
20781da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat), FIFO);
20791da177e4SLinus Torvalds 
20801da177e4SLinus Torvalds 		if (pCurrCard->currentSCCB != NULL)
208147b5d69cSJames Bottomley  			FPT_sxfrp(p_port, p_card);
20821da177e4SLinus Torvalds 	}
20831da177e4SLinus Torvalds 
20845c04a7b8SAlexey Dobriyan 	else if (p_int & TIMEOUT) {
20851da177e4SLinus Torvalds 
20861da177e4SLinus Torvalds 		DISABLE_AUTO(p_port);
20871da177e4SLinus Torvalds 
20881da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat),
20895c04a7b8SAlexey Dobriyan 			    (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
20905c04a7b8SAlexey Dobriyan 			     IUNKWN));
20911da177e4SLinus Torvalds 
20921da177e4SLinus Torvalds 		pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
20931da177e4SLinus Torvalds 
20945c04a7b8SAlexey Dobriyan 		currTar_Info =
20955c04a7b8SAlexey Dobriyan 		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
20965c04a7b8SAlexey Dobriyan 		if ((pCurrCard->globalFlags & F_CONLUN_IO)
20975c04a7b8SAlexey Dobriyan 		    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
20985c04a7b8SAlexey Dobriyan 			TAG_Q_TRYING))
20995c04a7b8SAlexey Dobriyan 			currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
21005c04a7b8SAlexey Dobriyan 			    0;
21011da177e4SLinus Torvalds 		else
210247b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[0] = 0;
21031da177e4SLinus Torvalds 
21045c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
21051da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
21061da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
21071da177e4SLinus Torvalds 		}
21081da177e4SLinus Torvalds 
21095c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
21101da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
21111da177e4SLinus Torvalds 		}
21121da177e4SLinus Torvalds 
21135c04a7b8SAlexey Dobriyan 		FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
21145c04a7b8SAlexey Dobriyan 			    currTar_Info);
21151da177e4SLinus Torvalds 
211647b5d69cSJames Bottomley  		FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
21171da177e4SLinus Torvalds 
21181da177e4SLinus Torvalds 	}
21191da177e4SLinus Torvalds 
21205c04a7b8SAlexey Dobriyan 	else if (p_int & SCAM_SEL) {
21211da177e4SLinus Torvalds 
212247b5d69cSJames Bottomley  		FPT_scarb(p_port, LEVEL2_TAR);
212347b5d69cSJames Bottomley  		FPT_scsel(p_port);
212447b5d69cSJames Bottomley  		FPT_scasid(p_card, p_port);
21251da177e4SLinus Torvalds 
212647b5d69cSJames Bottomley  		FPT_scbusf(p_port);
21271da177e4SLinus Torvalds 
21281da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
21291da177e4SLinus Torvalds 	}
21301da177e4SLinus Torvalds 
21315c1b85e2SAlexey Dobriyan 	return 0x00;
21321da177e4SLinus Torvalds }
21331da177e4SLinus Torvalds 
21341da177e4SLinus Torvalds /*---------------------------------------------------------------------
21351da177e4SLinus Torvalds  *
21361da177e4SLinus Torvalds  * Function: SccbMgrTableInit
21371da177e4SLinus Torvalds  *
21381da177e4SLinus Torvalds  * Description: Initialize all Sccb manager data structures.
21391da177e4SLinus Torvalds  *
21401da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
21411da177e4SLinus Torvalds 
2142cd9d715cSSudip Mukherjee static void FPT_SccbMgrTableInitAll(void)
21431da177e4SLinus Torvalds {
2144db038cf8SAlexey Dobriyan 	unsigned char thisCard;
21451da177e4SLinus Torvalds 
21465c04a7b8SAlexey Dobriyan 	for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
214747b5d69cSJames Bottomley  		FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
21481da177e4SLinus Torvalds 
214947b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].ioPort = 0x00;
215047b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].cardInfo = NULL;
215147b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].cardIndex = 0xFF;
215247b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].ourId = 0x00;
215347b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].pNvRamInfo = NULL;
21541da177e4SLinus Torvalds 	}
21551da177e4SLinus Torvalds }
21561da177e4SLinus Torvalds 
21571da177e4SLinus Torvalds /*---------------------------------------------------------------------
21581da177e4SLinus Torvalds  *
21591da177e4SLinus Torvalds  * Function: SccbMgrTableInit
21601da177e4SLinus Torvalds  *
21611da177e4SLinus Torvalds  * Description: Initialize all Sccb manager data structures.
21621da177e4SLinus Torvalds  *
21631da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
21641da177e4SLinus Torvalds 
21655c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
21665c04a7b8SAlexey Dobriyan 				     unsigned char p_card)
21671da177e4SLinus Torvalds {
2168db038cf8SAlexey Dobriyan 	unsigned char scsiID, qtag;
21691da177e4SLinus Torvalds 
21705c04a7b8SAlexey Dobriyan 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
217147b5d69cSJames Bottomley  		FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
21721da177e4SLinus Torvalds 	}
21731da177e4SLinus Torvalds 
21745c04a7b8SAlexey Dobriyan 	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
217547b5d69cSJames Bottomley  		FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
217647b5d69cSJames Bottomley  		FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
217747b5d69cSJames Bottomley  		FPT_SccbMgrTableInitTarget(p_card, scsiID);
21781da177e4SLinus Torvalds 	}
21791da177e4SLinus Torvalds 
21801da177e4SLinus Torvalds 	pCurrCard->scanIndex = 0x00;
21811da177e4SLinus Torvalds 	pCurrCard->currentSCCB = NULL;
21821da177e4SLinus Torvalds 	pCurrCard->globalFlags = 0x00;
21831da177e4SLinus Torvalds 	pCurrCard->cmdCounter = 0x00;
21841da177e4SLinus Torvalds 	pCurrCard->tagQ_Lst = 0x01;
21851da177e4SLinus Torvalds 	pCurrCard->discQCount = 0;
21861da177e4SLinus Torvalds 
21871da177e4SLinus Torvalds }
21881da177e4SLinus Torvalds 
21891da177e4SLinus Torvalds /*---------------------------------------------------------------------
21901da177e4SLinus Torvalds  *
21911da177e4SLinus Torvalds  * Function: SccbMgrTableInit
21921da177e4SLinus Torvalds  *
21931da177e4SLinus Torvalds  * Description: Initialize all Sccb manager data structures.
21941da177e4SLinus Torvalds  *
21951da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
21961da177e4SLinus Torvalds 
21975c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
21985c04a7b8SAlexey Dobriyan 				       unsigned char target)
21991da177e4SLinus Torvalds {
22001da177e4SLinus Torvalds 
2201db038cf8SAlexey Dobriyan 	unsigned char lun, qtag;
2202f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
22031da177e4SLinus Torvalds 
220447b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
22051da177e4SLinus Torvalds 
22061da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Cnt = 0;
22071da177e4SLinus Torvalds 	currTar_Info->TarSyncCtrl = 0;
22081da177e4SLinus Torvalds 
22091da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Head = NULL;
22101da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Tail = NULL;
22111da177e4SLinus Torvalds 	currTar_Info->TarTagQ_Cnt = 0;
221247b5d69cSJames Bottomley  	currTar_Info->TarLUN_CA = 0;
22131da177e4SLinus Torvalds 
22145c04a7b8SAlexey Dobriyan 	for (lun = 0; lun < MAX_LUN; lun++) {
221547b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[lun] = 0;
22161da177e4SLinus Torvalds 		currTar_Info->LunDiscQ_Idx[lun] = 0;
22171da177e4SLinus Torvalds 	}
22181da177e4SLinus Torvalds 
22195c04a7b8SAlexey Dobriyan 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
22205c04a7b8SAlexey Dobriyan 		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
22215c04a7b8SAlexey Dobriyan 			if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
22225c04a7b8SAlexey Dobriyan 			    target) {
222347b5d69cSJames Bottomley  				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
222447b5d69cSJames Bottomley  				FPT_BL_Card[p_card].discQCount--;
22251da177e4SLinus Torvalds 			}
22261da177e4SLinus Torvalds 		}
22271da177e4SLinus Torvalds 	}
22281da177e4SLinus Torvalds }
22291da177e4SLinus Torvalds 
22301da177e4SLinus Torvalds /*---------------------------------------------------------------------
22311da177e4SLinus Torvalds  *
22321da177e4SLinus Torvalds  * Function: sfetm
22331da177e4SLinus Torvalds  *
22341da177e4SLinus Torvalds  * Description: Read in a message byte from the SCSI bus, and check
22351da177e4SLinus Torvalds  *              for a parity error.
22361da177e4SLinus Torvalds  *
22371da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
22381da177e4SLinus Torvalds 
2239391e2f25SKhalid Aziz static unsigned char FPT_sfm(u32 port, struct sccb *pCurrSCCB)
22401da177e4SLinus Torvalds {
2241db038cf8SAlexey Dobriyan 	unsigned char message;
2242c823feebSAlexey Dobriyan 	unsigned short TimeOutLoop;
22431da177e4SLinus Torvalds 
22441da177e4SLinus Torvalds 	TimeOutLoop = 0;
22451da177e4SLinus Torvalds 	while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
22465c04a7b8SAlexey Dobriyan 	       (TimeOutLoop++ < 20000)) {
22475c04a7b8SAlexey Dobriyan 	}
22481da177e4SLinus Torvalds 
22491da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
22501da177e4SLinus Torvalds 
22511da177e4SLinus Torvalds 	message = RD_HARPOON(port + hp_scsidata_0);
22521da177e4SLinus Torvalds 
22531da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
22541da177e4SLinus Torvalds 
22551da177e4SLinus Torvalds 	if (TimeOutLoop > 20000)
22561da177e4SLinus Torvalds 		message = 0x00;	/* force message byte = 0 if Time Out on Req */
22571da177e4SLinus Torvalds 
22581da177e4SLinus Torvalds 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
22595c04a7b8SAlexey Dobriyan 	    (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
22601da177e4SLinus Torvalds 		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
22611da177e4SLinus Torvalds 		WR_HARPOON(port + hp_xferstat, 0);
22621da177e4SLinus Torvalds 		WR_HARPOON(port + hp_fiforead, 0);
22631da177e4SLinus Torvalds 		WR_HARPOON(port + hp_fifowrite, 0);
22645c04a7b8SAlexey Dobriyan 		if (pCurrSCCB != NULL) {
22651da177e4SLinus Torvalds 			pCurrSCCB->Sccb_scsimsg = SMPARITY;
22661da177e4SLinus Torvalds 		}
22671da177e4SLinus Torvalds 		message = 0x00;
22685c04a7b8SAlexey Dobriyan 		do {
22691da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
22701da177e4SLinus Torvalds 			TimeOutLoop = 0;
22711da177e4SLinus Torvalds 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
22725c04a7b8SAlexey Dobriyan 			       (TimeOutLoop++ < 20000)) {
22735c04a7b8SAlexey Dobriyan 			}
22745c04a7b8SAlexey Dobriyan 			if (TimeOutLoop > 20000) {
22751da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PARITY);
22765c1b85e2SAlexey Dobriyan 				return message;
22771da177e4SLinus Torvalds 			}
22785c04a7b8SAlexey Dobriyan 			if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
22795c04a7b8SAlexey Dobriyan 			    S_MSGI_PH) {
22801da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PARITY);
22815c1b85e2SAlexey Dobriyan 				return message;
22821da177e4SLinus Torvalds 			}
22831da177e4SLinus Torvalds 			WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
22841da177e4SLinus Torvalds 
22851da177e4SLinus Torvalds 			RD_HARPOON(port + hp_scsidata_0);
22861da177e4SLinus Torvalds 
22871da177e4SLinus Torvalds 			WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
22881da177e4SLinus Torvalds 
22891da177e4SLinus Torvalds 		} while (1);
22901da177e4SLinus Torvalds 
22911da177e4SLinus Torvalds 	}
22921da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
22931da177e4SLinus Torvalds 	WR_HARPOON(port + hp_xferstat, 0);
22941da177e4SLinus Torvalds 	WR_HARPOON(port + hp_fiforead, 0);
22951da177e4SLinus Torvalds 	WR_HARPOON(port + hp_fifowrite, 0);
22965c1b85e2SAlexey Dobriyan 	return message;
22971da177e4SLinus Torvalds }
22981da177e4SLinus Torvalds 
22991da177e4SLinus Torvalds /*---------------------------------------------------------------------
23001da177e4SLinus Torvalds  *
230147b5d69cSJames Bottomley   * Function: FPT_ssel
23021da177e4SLinus Torvalds  *
23031da177e4SLinus Torvalds  * Description: Load up automation and select target device.
23041da177e4SLinus Torvalds  *
23051da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
23061da177e4SLinus Torvalds 
2307391e2f25SKhalid Aziz static void FPT_ssel(u32 port, unsigned char p_card)
23081da177e4SLinus Torvalds {
23091da177e4SLinus Torvalds 
2310db038cf8SAlexey Dobriyan 	unsigned char auto_loaded, i, target, *theCCB;
23111da177e4SLinus Torvalds 
2312391e2f25SKhalid Aziz 	u32 cdb_reg;
231313e6851aSAlexey Dobriyan 	struct sccb_card *CurrCard;
231469eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
2315f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
2316db038cf8SAlexey Dobriyan 	unsigned char lastTag, lun;
23171da177e4SLinus Torvalds 
231847b5d69cSJames Bottomley  	CurrCard = &FPT_BL_Card[p_card];
23191da177e4SLinus Torvalds 	currSCCB = CurrCard->currentSCCB;
23201da177e4SLinus Torvalds 	target = currSCCB->TargID;
232147b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
23221da177e4SLinus Torvalds 	lastTag = CurrCard->tagQ_Lst;
23231da177e4SLinus Torvalds 
23241da177e4SLinus Torvalds 	ARAM_ACCESS(port);
23251da177e4SLinus Torvalds 
23261da177e4SLinus Torvalds 	if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
23271da177e4SLinus Torvalds 		currSCCB->ControlByte &= ~F_USE_CMD_Q;
23281da177e4SLinus Torvalds 
23291da177e4SLinus Torvalds 	if (((CurrCard->globalFlags & F_CONLUN_IO) &&
23301da177e4SLinus Torvalds 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
23311da177e4SLinus Torvalds 
23321da177e4SLinus Torvalds 		lun = currSCCB->Lun;
23331da177e4SLinus Torvalds 	else
23341da177e4SLinus Torvalds 		lun = 0;
23351da177e4SLinus Torvalds 
23365c04a7b8SAlexey Dobriyan 	if (CurrCard->globalFlags & F_TAG_STARTED) {
23375c04a7b8SAlexey Dobriyan 		if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
233847b5d69cSJames Bottomley  			if ((currTar_Info->TarLUN_CA == 0)
23391da177e4SLinus Torvalds 			    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
23405c04a7b8SAlexey Dobriyan 				== TAG_Q_TRYING)) {
23411da177e4SLinus Torvalds 
23425c04a7b8SAlexey Dobriyan 				if (currTar_Info->TarTagQ_Cnt != 0) {
234347b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[lun] = 1;
234447b5d69cSJames Bottomley  					FPT_queueSelectFail(CurrCard, p_card);
23451da177e4SLinus Torvalds 					SGRAM_ACCESS(port);
23461da177e4SLinus Torvalds 					return;
23471da177e4SLinus Torvalds 				}
23481da177e4SLinus Torvalds 
23491da177e4SLinus Torvalds 				else {
235047b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[lun] = 1;
23511da177e4SLinus Torvalds 				}
23521da177e4SLinus Torvalds 
23535c04a7b8SAlexey Dobriyan 			}
23545c04a7b8SAlexey Dobriyan 			/*End non-tagged */
23551da177e4SLinus Torvalds 			else {
235647b5d69cSJames Bottomley  				currTar_Info->TarLUNBusy[lun] = 1;
23571da177e4SLinus Torvalds 			}
23581da177e4SLinus Torvalds 
23595c04a7b8SAlexey Dobriyan 		}
23605c04a7b8SAlexey Dobriyan 		/*!Use cmd Q Tagged */
23611da177e4SLinus Torvalds 		else {
23625c04a7b8SAlexey Dobriyan 			if (currTar_Info->TarLUN_CA == 1) {
236347b5d69cSJames Bottomley  				FPT_queueSelectFail(CurrCard, p_card);
23641da177e4SLinus Torvalds 				SGRAM_ACCESS(port);
23651da177e4SLinus Torvalds 				return;
23661da177e4SLinus Torvalds 			}
23671da177e4SLinus Torvalds 
236847b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[lun] = 1;
23691da177e4SLinus Torvalds 
23701da177e4SLinus Torvalds 		}		/*else use cmd Q tagged */
23711da177e4SLinus Torvalds 
23725c04a7b8SAlexey Dobriyan 	}
23735c04a7b8SAlexey Dobriyan 	/*if glob tagged started */
23741da177e4SLinus Torvalds 	else {
237547b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[lun] = 1;
23761da177e4SLinus Torvalds 	}
23771da177e4SLinus Torvalds 
23781da177e4SLinus Torvalds 	if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
23791da177e4SLinus Torvalds 	      ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
23805c04a7b8SAlexey Dobriyan 	     || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
23815c04a7b8SAlexey Dobriyan 		if (CurrCard->discQCount >= QUEUE_DEPTH) {
238247b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[lun] = 1;
238347b5d69cSJames Bottomley  			FPT_queueSelectFail(CurrCard, p_card);
23841da177e4SLinus Torvalds 			SGRAM_ACCESS(port);
23851da177e4SLinus Torvalds 			return;
23861da177e4SLinus Torvalds 		}
23875c04a7b8SAlexey Dobriyan 		for (i = 1; i < QUEUE_DEPTH; i++) {
23885c04a7b8SAlexey Dobriyan 			if (++lastTag >= QUEUE_DEPTH)
23895c04a7b8SAlexey Dobriyan 				lastTag = 1;
23905c04a7b8SAlexey Dobriyan 			if (CurrCard->discQ_Tbl[lastTag] == NULL) {
23911da177e4SLinus Torvalds 				CurrCard->tagQ_Lst = lastTag;
23921da177e4SLinus Torvalds 				currTar_Info->LunDiscQ_Idx[lun] = lastTag;
23931da177e4SLinus Torvalds 				CurrCard->discQ_Tbl[lastTag] = currSCCB;
23941da177e4SLinus Torvalds 				CurrCard->discQCount++;
23951da177e4SLinus Torvalds 				break;
23961da177e4SLinus Torvalds 			}
23971da177e4SLinus Torvalds 		}
23985c04a7b8SAlexey Dobriyan 		if (i == QUEUE_DEPTH) {
239947b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[lun] = 1;
240047b5d69cSJames Bottomley  			FPT_queueSelectFail(CurrCard, p_card);
24011da177e4SLinus Torvalds 			SGRAM_ACCESS(port);
24021da177e4SLinus Torvalds 			return;
24031da177e4SLinus Torvalds 		}
24041da177e4SLinus Torvalds 	}
24051da177e4SLinus Torvalds 
240647b5d69cSJames Bottomley  	auto_loaded = 0;
24071da177e4SLinus Torvalds 
24081da177e4SLinus Torvalds 	WR_HARPOON(port + hp_select_id, target);
24091da177e4SLinus Torvalds 	WR_HARPOON(port + hp_gp_reg_3, target);	/* Use by new automation logic */
24101da177e4SLinus Torvalds 
24111da177e4SLinus Torvalds 	if (currSCCB->OperationCode == RESET_COMMAND) {
24121da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
24135c04a7b8SAlexey Dobriyan 						   (currSCCB->
24145c04a7b8SAlexey Dobriyan 						    Sccb_idmsg & ~DISC_PRIV)));
24151da177e4SLinus Torvalds 
24161da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
24171da177e4SLinus Torvalds 
24181da177e4SLinus Torvalds 		currSCCB->Sccb_scsimsg = SMDEV_RESET;
24191da177e4SLinus Torvalds 
24201da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
242147b5d69cSJames Bottomley  		auto_loaded = 1;
24221da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = SELECT_BDR_ST;
24231da177e4SLinus Torvalds 
24245c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
24251da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
24261da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
24271da177e4SLinus Torvalds 		}
24281da177e4SLinus Torvalds 
24295c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
24301da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
24311da177e4SLinus Torvalds 		}
24321da177e4SLinus Torvalds 
243347b5d69cSJames Bottomley  		FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
243447b5d69cSJames Bottomley  		FPT_SccbMgrTableInitTarget(p_card, target);
24351da177e4SLinus Torvalds 
24361da177e4SLinus Torvalds 	}
24371da177e4SLinus Torvalds 
24385c04a7b8SAlexey Dobriyan 	else if (currSCCB->Sccb_scsistat == ABORT_ST) {
24391da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
24405c04a7b8SAlexey Dobriyan 						   (currSCCB->
24415c04a7b8SAlexey Dobriyan 						    Sccb_idmsg & ~DISC_PRIV)));
24421da177e4SLinus Torvalds 
24431da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
24441da177e4SLinus Torvalds 
24451da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
24465c04a7b8SAlexey Dobriyan 						     (((unsigned
24475c04a7b8SAlexey Dobriyan 							char)(currSCCB->
24485c04a7b8SAlexey Dobriyan 							      ControlByte &
24495c04a7b8SAlexey Dobriyan 							      TAG_TYPE_MASK)
24505c04a7b8SAlexey Dobriyan 						       >> 6) | (unsigned char)
24515c04a7b8SAlexey Dobriyan 						      0x20)));
24521da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 2),
24531da177e4SLinus Torvalds 			    (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
24541da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
24551da177e4SLinus Torvalds 
24561da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
245747b5d69cSJames Bottomley  		auto_loaded = 1;
24581da177e4SLinus Torvalds 
24591da177e4SLinus Torvalds 	}
24601da177e4SLinus Torvalds 
24611da177e4SLinus Torvalds 	else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
246247b5d69cSJames Bottomley  		auto_loaded = FPT_siwidn(port, p_card);
24631da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = SELECT_WN_ST;
24641da177e4SLinus Torvalds 	}
24651da177e4SLinus Torvalds 
24661da177e4SLinus Torvalds 	else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
24671da177e4SLinus Torvalds 		   == SYNC_SUPPORTED)) {
246847b5d69cSJames Bottomley  		auto_loaded = FPT_sisyncn(port, p_card, 0);
24691da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = SELECT_SN_ST;
24701da177e4SLinus Torvalds 	}
24711da177e4SLinus Torvalds 
24725c04a7b8SAlexey Dobriyan 	if (!auto_loaded) {
24731da177e4SLinus Torvalds 
24745c04a7b8SAlexey Dobriyan 		if (currSCCB->ControlByte & F_USE_CMD_Q) {
24751da177e4SLinus Torvalds 
24761da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_TAG_STARTED;
24771da177e4SLinus Torvalds 
24781da177e4SLinus Torvalds 			if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
24795c04a7b8SAlexey Dobriyan 			    == TAG_Q_REJECT) {
24801da177e4SLinus Torvalds 				currSCCB->ControlByte &= ~F_USE_CMD_Q;
24811da177e4SLinus Torvalds 
24821da177e4SLinus Torvalds 				/* Fix up the start instruction with a jump to
24831da177e4SLinus Torvalds 				   Non-Tag-CMD handling */
24845c04a7b8SAlexey Dobriyan 				WRW_HARPOON((port + ID_MSG_STRT),
24855c04a7b8SAlexey Dobriyan 					    BRH_OP + ALWAYS + NTCMD);
24861da177e4SLinus Torvalds 
24871da177e4SLinus Torvalds 				WRW_HARPOON((port + NON_TAG_ID_MSG),
24885c04a7b8SAlexey Dobriyan 					    (MPM_OP + AMSG_OUT +
24895c04a7b8SAlexey Dobriyan 					     currSCCB->Sccb_idmsg));
24901da177e4SLinus Torvalds 
24915c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_3,
24925c04a7b8SAlexey Dobriyan 					   (SELECT + SELCHK_STRT));
24931da177e4SLinus Torvalds 
249425985edcSLucas De Marchi 				/* Setup our STATE so we know what happened when
24951da177e4SLinus Torvalds 				   the wheels fall off. */
24961da177e4SLinus Torvalds 				currSCCB->Sccb_scsistat = SELECT_ST;
24971da177e4SLinus Torvalds 
249847b5d69cSJames Bottomley  				currTar_Info->TarLUNBusy[lun] = 1;
24991da177e4SLinus Torvalds 			}
25001da177e4SLinus Torvalds 
25015c04a7b8SAlexey Dobriyan 			else {
25025c04a7b8SAlexey Dobriyan 				WRW_HARPOON((port + ID_MSG_STRT),
25035c04a7b8SAlexey Dobriyan 					    (MPM_OP + AMSG_OUT +
25045c04a7b8SAlexey Dobriyan 					     currSCCB->Sccb_idmsg));
25051da177e4SLinus Torvalds 
25065c04a7b8SAlexey Dobriyan 				WRW_HARPOON((port + ID_MSG_STRT + 2),
25075c04a7b8SAlexey Dobriyan 					    (MPM_OP + AMSG_OUT +
25085c04a7b8SAlexey Dobriyan 					     (((unsigned char)(currSCCB->
25095c04a7b8SAlexey Dobriyan 							       ControlByte &
25105c04a7b8SAlexey Dobriyan 							       TAG_TYPE_MASK)
2511db038cf8SAlexey Dobriyan 					       >> 6) | (unsigned char)0x20)));
25121da177e4SLinus Torvalds 
25135c04a7b8SAlexey Dobriyan 				for (i = 1; i < QUEUE_DEPTH; i++) {
25145c04a7b8SAlexey Dobriyan 					if (++lastTag >= QUEUE_DEPTH)
25155c04a7b8SAlexey Dobriyan 						lastTag = 1;
25165c04a7b8SAlexey Dobriyan 					if (CurrCard->discQ_Tbl[lastTag] ==
25175c04a7b8SAlexey Dobriyan 					    NULL) {
25185c04a7b8SAlexey Dobriyan 						WRW_HARPOON((port +
25195c04a7b8SAlexey Dobriyan 							     ID_MSG_STRT + 6),
25205c04a7b8SAlexey Dobriyan 							    (MPM_OP + AMSG_OUT +
25215c04a7b8SAlexey Dobriyan 							     lastTag));
25221da177e4SLinus Torvalds 						CurrCard->tagQ_Lst = lastTag;
25231da177e4SLinus Torvalds 						currSCCB->Sccb_tag = lastTag;
25245c04a7b8SAlexey Dobriyan 						CurrCard->discQ_Tbl[lastTag] =
25255c04a7b8SAlexey Dobriyan 						    currSCCB;
25261da177e4SLinus Torvalds 						CurrCard->discQCount++;
25271da177e4SLinus Torvalds 						break;
25281da177e4SLinus Torvalds 					}
25291da177e4SLinus Torvalds 				}
25301da177e4SLinus Torvalds 
25315c04a7b8SAlexey Dobriyan 				if (i == QUEUE_DEPTH) {
253247b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[lun] = 1;
253347b5d69cSJames Bottomley  					FPT_queueSelectFail(CurrCard, p_card);
25341da177e4SLinus Torvalds 					SGRAM_ACCESS(port);
25351da177e4SLinus Torvalds 					return;
25361da177e4SLinus Torvalds 				}
25371da177e4SLinus Torvalds 
25381da177e4SLinus Torvalds 				currSCCB->Sccb_scsistat = SELECT_Q_ST;
25391da177e4SLinus Torvalds 
25405c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_3,
25415c04a7b8SAlexey Dobriyan 					   (SELECT + SELCHK_STRT));
25421da177e4SLinus Torvalds 			}
25431da177e4SLinus Torvalds 		}
25441da177e4SLinus Torvalds 
25455c04a7b8SAlexey Dobriyan 		else {
25461da177e4SLinus Torvalds 
25475c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + ID_MSG_STRT),
25485c04a7b8SAlexey Dobriyan 				    BRH_OP + ALWAYS + NTCMD);
25491da177e4SLinus Torvalds 
25501da177e4SLinus Torvalds 			WRW_HARPOON((port + NON_TAG_ID_MSG),
25511da177e4SLinus Torvalds 				    (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
25521da177e4SLinus Torvalds 
25531da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = SELECT_ST;
25541da177e4SLinus Torvalds 
25555c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_3,
25565c04a7b8SAlexey Dobriyan 				   (SELECT + SELCHK_STRT));
25571da177e4SLinus Torvalds 		}
25581da177e4SLinus Torvalds 
2559db038cf8SAlexey Dobriyan 		theCCB = (unsigned char *)&currSCCB->Cdb[0];
25601da177e4SLinus Torvalds 
25611da177e4SLinus Torvalds 		cdb_reg = port + CMD_STRT;
25621da177e4SLinus Torvalds 
25635c04a7b8SAlexey Dobriyan 		for (i = 0; i < currSCCB->CdbLength; i++) {
25641da177e4SLinus Torvalds 			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
25651da177e4SLinus Torvalds 			cdb_reg += 2;
25661da177e4SLinus Torvalds 			theCCB++;
25671da177e4SLinus Torvalds 		}
25681da177e4SLinus Torvalds 
25691da177e4SLinus Torvalds 		if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
25701da177e4SLinus Torvalds 			WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
25711da177e4SLinus Torvalds 
25725c04a7b8SAlexey Dobriyan 	}
25735c04a7b8SAlexey Dobriyan 	/* auto_loaded */
2574c823feebSAlexey Dobriyan 	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
25751da177e4SLinus Torvalds 	WR_HARPOON(port + hp_xferstat, 0x00);
25761da177e4SLinus Torvalds 
25771da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
25781da177e4SLinus Torvalds 
25791da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
25801da177e4SLinus Torvalds 
25815c04a7b8SAlexey Dobriyan 	if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
25825c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_scsictrl_0,
25835c04a7b8SAlexey Dobriyan 			   (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
25845c04a7b8SAlexey Dobriyan 	} else {
25851da177e4SLinus Torvalds 
2586db038cf8SAlexey Dobriyan /*      auto_loaded =  (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
25871da177e4SLinus Torvalds       auto_loaded |= AUTO_IMMED; */
25881da177e4SLinus Torvalds 		auto_loaded = AUTO_IMMED;
25891da177e4SLinus Torvalds 
25901da177e4SLinus Torvalds 		DISABLE_AUTO(port);
25911da177e4SLinus Torvalds 
25921da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, auto_loaded);
25931da177e4SLinus Torvalds 	}
25941da177e4SLinus Torvalds 
25951da177e4SLinus Torvalds 	SGRAM_ACCESS(port);
25961da177e4SLinus Torvalds }
25971da177e4SLinus Torvalds 
25981da177e4SLinus Torvalds /*---------------------------------------------------------------------
25991da177e4SLinus Torvalds  *
260047b5d69cSJames Bottomley   * Function: FPT_sres
26011da177e4SLinus Torvalds  *
26021da177e4SLinus Torvalds  * Description: Hookup the correct CCB and handle the incoming messages.
26031da177e4SLinus Torvalds  *
26041da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
26051da177e4SLinus Torvalds 
2606391e2f25SKhalid Aziz static void FPT_sres(u32 port, unsigned char p_card,
26075c04a7b8SAlexey Dobriyan 		     struct sccb_card *pCurrCard)
26081da177e4SLinus Torvalds {
26091da177e4SLinus Torvalds 
2610db038cf8SAlexey Dobriyan 	unsigned char our_target, message, lun = 0, tag, msgRetryCount;
26111da177e4SLinus Torvalds 
2612f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
261369eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
26141da177e4SLinus Torvalds 
26155c04a7b8SAlexey Dobriyan 	if (pCurrCard->currentSCCB != NULL) {
26165c04a7b8SAlexey Dobriyan 		currTar_Info =
26175c04a7b8SAlexey Dobriyan 		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
26181da177e4SLinus Torvalds 		DISABLE_AUTO(port);
26191da177e4SLinus Torvalds 
26201da177e4SLinus Torvalds 		WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
26211da177e4SLinus Torvalds 
26221da177e4SLinus Torvalds 		currSCCB = pCurrCard->currentSCCB;
26235c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
26241da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
26251da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
26261da177e4SLinus Torvalds 		}
26275c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
26281da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
26291da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
26301da177e4SLinus Torvalds 		}
26311da177e4SLinus Torvalds 		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
26325c04a7b8SAlexey Dobriyan 		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
26335c04a7b8SAlexey Dobriyan 		      TAG_Q_TRYING))) {
263447b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
26355c04a7b8SAlexey Dobriyan 			if (currSCCB->Sccb_scsistat != ABORT_ST) {
26361da177e4SLinus Torvalds 				pCurrCard->discQCount--;
26375c04a7b8SAlexey Dobriyan 				pCurrCard->discQ_Tbl[currTar_Info->
26385c04a7b8SAlexey Dobriyan 						     LunDiscQ_Idx[currSCCB->
26395c04a7b8SAlexey Dobriyan 								  Lun]]
26401da177e4SLinus Torvalds 				    = NULL;
26411da177e4SLinus Torvalds 			}
26425c04a7b8SAlexey Dobriyan 		} else {
264347b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[0] = 0;
26445c04a7b8SAlexey Dobriyan 			if (currSCCB->Sccb_tag) {
26455c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_scsistat != ABORT_ST) {
26461da177e4SLinus Torvalds 					pCurrCard->discQCount--;
26475c04a7b8SAlexey Dobriyan 					pCurrCard->discQ_Tbl[currSCCB->
26485c04a7b8SAlexey Dobriyan 							     Sccb_tag] = NULL;
26491da177e4SLinus Torvalds 				}
26505c04a7b8SAlexey Dobriyan 			} else {
26515c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_scsistat != ABORT_ST) {
26521da177e4SLinus Torvalds 					pCurrCard->discQCount--;
26535c04a7b8SAlexey Dobriyan 					pCurrCard->discQ_Tbl[currTar_Info->
26545c04a7b8SAlexey Dobriyan 							     LunDiscQ_Idx[0]] =
26555c04a7b8SAlexey Dobriyan 					    NULL;
26561da177e4SLinus Torvalds 				}
26571da177e4SLinus Torvalds 			}
26581da177e4SLinus Torvalds 		}
26591da177e4SLinus Torvalds 
266047b5d69cSJames Bottomley  		FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
26611da177e4SLinus Torvalds 	}
26621da177e4SLinus Torvalds 
2663c823feebSAlexey Dobriyan 	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
26641da177e4SLinus Torvalds 
2665db038cf8SAlexey Dobriyan 	our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
266647b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
26671da177e4SLinus Torvalds 
26681da177e4SLinus Torvalds 	msgRetryCount = 0;
26695c04a7b8SAlexey Dobriyan 	do {
26701da177e4SLinus Torvalds 
267147b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
26721da177e4SLinus Torvalds 		tag = 0;
26731da177e4SLinus Torvalds 
26745c04a7b8SAlexey Dobriyan 		while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
26755c04a7b8SAlexey Dobriyan 			if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
26761da177e4SLinus Torvalds 
26771da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PHASE);
26781da177e4SLinus Torvalds 				return;
26791da177e4SLinus Torvalds 			}
26801da177e4SLinus Torvalds 		}
26811da177e4SLinus Torvalds 
26821da177e4SLinus Torvalds 		WRW_HARPOON((port + hp_intstat), PHASE);
26835c04a7b8SAlexey Dobriyan 		if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
26841da177e4SLinus Torvalds 
268547b5d69cSJames Bottomley  			message = FPT_sfm(port, pCurrCard->currentSCCB);
26865c04a7b8SAlexey Dobriyan 			if (message) {
26871da177e4SLinus Torvalds 
26885c04a7b8SAlexey Dobriyan 				if (message <= (0x80 | LUN_MASK)) {
2689db038cf8SAlexey Dobriyan 					lun = message & (unsigned char)LUN_MASK;
26901da177e4SLinus Torvalds 
26915c04a7b8SAlexey Dobriyan 					if ((currTar_Info->
26925c04a7b8SAlexey Dobriyan 					     TarStatus & TAR_TAG_Q_MASK) ==
26935c04a7b8SAlexey Dobriyan 					    TAG_Q_TRYING) {
26945c04a7b8SAlexey Dobriyan 						if (currTar_Info->TarTagQ_Cnt !=
26955c04a7b8SAlexey Dobriyan 						    0) {
26961da177e4SLinus Torvalds 
26975c04a7b8SAlexey Dobriyan 							if (!
26985c04a7b8SAlexey Dobriyan 							    (currTar_Info->
26995c04a7b8SAlexey Dobriyan 							     TarLUN_CA)) {
27001da177e4SLinus Torvalds 								ACCEPT_MSG(port);	/*Release the ACK for ID msg. */
27011da177e4SLinus Torvalds 
27025c04a7b8SAlexey Dobriyan 								message =
27035c04a7b8SAlexey Dobriyan 								    FPT_sfm
27045c04a7b8SAlexey Dobriyan 								    (port,
27055c04a7b8SAlexey Dobriyan 								     pCurrCard->
27065c04a7b8SAlexey Dobriyan 								     currentSCCB);
27075c04a7b8SAlexey Dobriyan 								if (message) {
27085c04a7b8SAlexey Dobriyan 									ACCEPT_MSG
27095c04a7b8SAlexey Dobriyan 									    (port);
27101da177e4SLinus Torvalds 								}
27111da177e4SLinus Torvalds 
27121da177e4SLinus Torvalds 								else
27135c04a7b8SAlexey Dobriyan 									message
27145c04a7b8SAlexey Dobriyan 									    = 0;
27151da177e4SLinus Torvalds 
27165c04a7b8SAlexey Dobriyan 								if (message !=
27175c04a7b8SAlexey Dobriyan 								    0) {
27185c04a7b8SAlexey Dobriyan 									tag =
27195c04a7b8SAlexey Dobriyan 									    FPT_sfm
27205c04a7b8SAlexey Dobriyan 									    (port,
27215c04a7b8SAlexey Dobriyan 									     pCurrCard->
27225c04a7b8SAlexey Dobriyan 									     currentSCCB);
27231da177e4SLinus Torvalds 
27245c04a7b8SAlexey Dobriyan 									if (!
27255c04a7b8SAlexey Dobriyan 									    (tag))
27265c04a7b8SAlexey Dobriyan 										message
27275c04a7b8SAlexey Dobriyan 										    =
27285c04a7b8SAlexey Dobriyan 										    0;
27291da177e4SLinus Torvalds 								}
27301da177e4SLinus Torvalds 
27315c04a7b8SAlexey Dobriyan 							}
27325c04a7b8SAlexey Dobriyan 							/*C.A. exists! */
27335c04a7b8SAlexey Dobriyan 						}
27345c04a7b8SAlexey Dobriyan 						/*End Q cnt != 0 */
27355c04a7b8SAlexey Dobriyan 					}
27365c04a7b8SAlexey Dobriyan 					/*End Tag cmds supported! */
27375c04a7b8SAlexey Dobriyan 				}
27385c04a7b8SAlexey Dobriyan 				/*End valid ID message.  */
27395c04a7b8SAlexey Dobriyan 				else {
27401da177e4SLinus Torvalds 
27411da177e4SLinus Torvalds 					ACCEPT_MSG_ATN(port);
27421da177e4SLinus Torvalds 				}
27431da177e4SLinus Torvalds 
27445c04a7b8SAlexey Dobriyan 			}
27455c04a7b8SAlexey Dobriyan 			/* End good id message. */
27465c04a7b8SAlexey Dobriyan 			else {
27471da177e4SLinus Torvalds 
274847b5d69cSJames Bottomley  				message = 0;
27491da177e4SLinus Torvalds 			}
27505c04a7b8SAlexey Dobriyan 		} else {
27511da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
27521da177e4SLinus Torvalds 
27535c04a7b8SAlexey Dobriyan 			while (!
27545c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((port + hp_intstat)) &
27555c04a7b8SAlexey Dobriyan 				(PHASE | RESET))
27565c04a7b8SAlexey Dobriyan 			       && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
27575c04a7b8SAlexey Dobriyan 			       && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
27581da177e4SLinus Torvalds 
27591da177e4SLinus Torvalds 			return;
27601da177e4SLinus Torvalds 		}
27611da177e4SLinus Torvalds 
27625c04a7b8SAlexey Dobriyan 		if (message == 0) {
27631da177e4SLinus Torvalds 			msgRetryCount++;
27645c04a7b8SAlexey Dobriyan 			if (msgRetryCount == 1) {
276547b5d69cSJames Bottomley  				FPT_SendMsg(port, SMPARITY);
27665c04a7b8SAlexey Dobriyan 			} else {
276747b5d69cSJames Bottomley  				FPT_SendMsg(port, SMDEV_RESET);
27681da177e4SLinus Torvalds 
27695c04a7b8SAlexey Dobriyan 				FPT_sssyncv(port, our_target, NARROW_SCSI,
27705c04a7b8SAlexey Dobriyan 					    currTar_Info);
27711da177e4SLinus Torvalds 
27725c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][our_target].
27735c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_SYNC_MASK) {
27741da177e4SLinus Torvalds 
27755c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][our_target].
27765c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_SYNC_MASK;
27771da177e4SLinus Torvalds 
27781da177e4SLinus Torvalds 				}
27791da177e4SLinus Torvalds 
27805c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][our_target].
27815c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_WIDE_SCSI) {
27821da177e4SLinus Torvalds 
27835c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][our_target].
27845c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_WIDE_MASK;
27851da177e4SLinus Torvalds 				}
27861da177e4SLinus Torvalds 
27875c04a7b8SAlexey Dobriyan 				FPT_queueFlushTargSccb(p_card, our_target,
27885c04a7b8SAlexey Dobriyan 						       SCCB_COMPLETE);
278947b5d69cSJames Bottomley  				FPT_SccbMgrTableInitTarget(p_card, our_target);
27901da177e4SLinus Torvalds 				return;
27911da177e4SLinus Torvalds 			}
27921da177e4SLinus Torvalds 		}
279347b5d69cSJames Bottomley  	} while (message == 0);
27941da177e4SLinus Torvalds 
27951da177e4SLinus Torvalds 	if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
27965c04a7b8SAlexey Dobriyan 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
279747b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[lun] = 1;
27985c04a7b8SAlexey Dobriyan 		pCurrCard->currentSCCB =
27995c04a7b8SAlexey Dobriyan 		    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
28005c04a7b8SAlexey Dobriyan 		if (pCurrCard->currentSCCB != NULL) {
28011da177e4SLinus Torvalds 			ACCEPT_MSG(port);
28025c04a7b8SAlexey Dobriyan 		} else {
28031da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
28041da177e4SLinus Torvalds 		}
28055c04a7b8SAlexey Dobriyan 	} else {
280647b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[0] = 1;
28071da177e4SLinus Torvalds 
28085c04a7b8SAlexey Dobriyan 		if (tag) {
28095c04a7b8SAlexey Dobriyan 			if (pCurrCard->discQ_Tbl[tag] != NULL) {
28105c04a7b8SAlexey Dobriyan 				pCurrCard->currentSCCB =
28115c04a7b8SAlexey Dobriyan 				    pCurrCard->discQ_Tbl[tag];
28121da177e4SLinus Torvalds 				currTar_Info->TarTagQ_Cnt--;
28131da177e4SLinus Torvalds 				ACCEPT_MSG(port);
28145c04a7b8SAlexey Dobriyan 			} else {
28151da177e4SLinus Torvalds 				ACCEPT_MSG_ATN(port);
28161da177e4SLinus Torvalds 			}
28175c04a7b8SAlexey Dobriyan 		} else {
28185c04a7b8SAlexey Dobriyan 			pCurrCard->currentSCCB =
28195c04a7b8SAlexey Dobriyan 			    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
28205c04a7b8SAlexey Dobriyan 			if (pCurrCard->currentSCCB != NULL) {
28211da177e4SLinus Torvalds 				ACCEPT_MSG(port);
28225c04a7b8SAlexey Dobriyan 			} else {
28231da177e4SLinus Torvalds 				ACCEPT_MSG_ATN(port);
28241da177e4SLinus Torvalds 			}
28251da177e4SLinus Torvalds 		}
28261da177e4SLinus Torvalds 	}
28271da177e4SLinus Torvalds 
28285c04a7b8SAlexey Dobriyan 	if (pCurrCard->currentSCCB != NULL) {
28295c04a7b8SAlexey Dobriyan 		if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
28301da177e4SLinus Torvalds 			/* During Abort Tag command, the target could have got re-selected
28311da177e4SLinus Torvalds 			   and completed the command. Check the select Q and remove the CCB
28321da177e4SLinus Torvalds 			   if it is in the Select Q */
283347b5d69cSJames Bottomley  			FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
28341da177e4SLinus Torvalds 		}
28351da177e4SLinus Torvalds 	}
28361da177e4SLinus Torvalds 
28371da177e4SLinus Torvalds 	while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
28381da177e4SLinus Torvalds 	       !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
28391da177e4SLinus Torvalds 	       (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
28401da177e4SLinus Torvalds }
28411da177e4SLinus Torvalds 
2842391e2f25SKhalid Aziz static void FPT_SendMsg(u32 port, unsigned char message)
28431da177e4SLinus Torvalds {
28445c04a7b8SAlexey Dobriyan 	while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
28455c04a7b8SAlexey Dobriyan 		if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
28461da177e4SLinus Torvalds 
28471da177e4SLinus Torvalds 			WRW_HARPOON((port + hp_intstat), PHASE);
28481da177e4SLinus Torvalds 			return;
28491da177e4SLinus Torvalds 		}
28501da177e4SLinus Torvalds 	}
28511da177e4SLinus Torvalds 
28521da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), PHASE);
28535c04a7b8SAlexey Dobriyan 	if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
28545c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + hp_intstat),
28555c04a7b8SAlexey Dobriyan 			    (BUS_FREE | PHASE | XFER_CNT_0));
28561da177e4SLinus Torvalds 
28571da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
28581da177e4SLinus Torvalds 
28591da177e4SLinus Torvalds 		WR_HARPOON(port + hp_scsidata_0, message);
28601da177e4SLinus Torvalds 
28611da177e4SLinus Torvalds 		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
28621da177e4SLinus Torvalds 
28631da177e4SLinus Torvalds 		ACCEPT_MSG(port);
28641da177e4SLinus Torvalds 
28651da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, 0x00);
28661da177e4SLinus Torvalds 
28671da177e4SLinus Torvalds 		if ((message == SMABORT) || (message == SMDEV_RESET) ||
28685c04a7b8SAlexey Dobriyan 		    (message == SMABORT_TAG)) {
28695c04a7b8SAlexey Dobriyan 			while (!
28705c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((port + hp_intstat)) &
28715c04a7b8SAlexey Dobriyan 				(BUS_FREE | PHASE))) {
28725c04a7b8SAlexey Dobriyan 			}
28731da177e4SLinus Torvalds 
28745c04a7b8SAlexey Dobriyan 			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
28751da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), BUS_FREE);
28761da177e4SLinus Torvalds 			}
28771da177e4SLinus Torvalds 		}
28781da177e4SLinus Torvalds 	}
28791da177e4SLinus Torvalds }
28801da177e4SLinus Torvalds 
28811da177e4SLinus Torvalds /*---------------------------------------------------------------------
28821da177e4SLinus Torvalds  *
288347b5d69cSJames Bottomley   * Function: FPT_sdecm
28841da177e4SLinus Torvalds  *
288525985edcSLucas De Marchi  * Description: Determine the proper response to the message from the
28861da177e4SLinus Torvalds  *              target device.
28871da177e4SLinus Torvalds  *
28881da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
2889391e2f25SKhalid Aziz static void FPT_sdecm(unsigned char message, u32 port, unsigned char p_card)
28901da177e4SLinus Torvalds {
289169eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
289213e6851aSAlexey Dobriyan 	struct sccb_card *CurrCard;
2893f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
28941da177e4SLinus Torvalds 
289547b5d69cSJames Bottomley  	CurrCard = &FPT_BL_Card[p_card];
28961da177e4SLinus Torvalds 	currSCCB = CurrCard->currentSCCB;
28971da177e4SLinus Torvalds 
289847b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
28991da177e4SLinus Torvalds 
29005c04a7b8SAlexey Dobriyan 	if (message == SMREST_DATA_PTR) {
29015c04a7b8SAlexey Dobriyan 		if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
29021da177e4SLinus Torvalds 			currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
29031da177e4SLinus Torvalds 
290447b5d69cSJames Bottomley  			FPT_hostDataXferRestart(currSCCB);
29051da177e4SLinus Torvalds 		}
29061da177e4SLinus Torvalds 
29071da177e4SLinus Torvalds 		ACCEPT_MSG(port);
29085c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
29095c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
29101da177e4SLinus Torvalds 	}
29111da177e4SLinus Torvalds 
29125c04a7b8SAlexey Dobriyan 	else if (message == SMCMD_COMP) {
29131da177e4SLinus Torvalds 
29145c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
29155c04a7b8SAlexey Dobriyan 			currTar_Info->TarStatus &=
29165c04a7b8SAlexey Dobriyan 			    ~(unsigned char)TAR_TAG_Q_MASK;
2917db038cf8SAlexey Dobriyan 			currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
29181da177e4SLinus Torvalds 		}
29191da177e4SLinus Torvalds 
29201da177e4SLinus Torvalds 		ACCEPT_MSG(port);
29211da177e4SLinus Torvalds 
29221da177e4SLinus Torvalds 	}
29231da177e4SLinus Torvalds 
29241da177e4SLinus Torvalds 	else if ((message == SMNO_OP) || (message >= SMIDENT)
29255c04a7b8SAlexey Dobriyan 		 || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) {
29261da177e4SLinus Torvalds 
29271da177e4SLinus Torvalds 		ACCEPT_MSG(port);
29285c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
29295c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
29301da177e4SLinus Torvalds 	}
29311da177e4SLinus Torvalds 
29325c04a7b8SAlexey Dobriyan 	else if (message == SMREJECT) {
29331da177e4SLinus Torvalds 
29341da177e4SLinus Torvalds 		if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
29351da177e4SLinus Torvalds 		    (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
29365c04a7b8SAlexey Dobriyan 		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
29375c04a7b8SAlexey Dobriyan 		    || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
29385c04a7b8SAlexey Dobriyan 			TAG_Q_TRYING))
29391da177e4SLinus Torvalds 		{
29401da177e4SLinus Torvalds 			WRW_HARPOON((port + hp_intstat), BUS_FREE);
29411da177e4SLinus Torvalds 
29421da177e4SLinus Torvalds 			ACCEPT_MSG(port);
29431da177e4SLinus Torvalds 
29441da177e4SLinus Torvalds 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
29455c04a7b8SAlexey Dobriyan 			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
29461da177e4SLinus Torvalds 			{
29471da177e4SLinus Torvalds 			}
29481da177e4SLinus Torvalds 
29495c04a7b8SAlexey Dobriyan 			if (currSCCB->Lun == 0x00) {
2950adb11023SNathan Chancellor 				if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
29511da177e4SLinus Torvalds 
29525c04a7b8SAlexey Dobriyan 					currTar_Info->TarStatus |=
29535c04a7b8SAlexey Dobriyan 					    (unsigned char)SYNC_SUPPORTED;
29541da177e4SLinus Torvalds 
29555c04a7b8SAlexey Dobriyan 					currTar_Info->TarEEValue &=
29565c04a7b8SAlexey Dobriyan 					    ~EE_SYNC_MASK;
29575c04a7b8SAlexey Dobriyan 				}
29581da177e4SLinus Torvalds 
2959adb11023SNathan Chancellor 				else if (currSCCB->Sccb_scsistat ==
2960adb11023SNathan Chancellor 					  SELECT_WN_ST) {
29615c04a7b8SAlexey Dobriyan 
29625c04a7b8SAlexey Dobriyan 					currTar_Info->TarStatus =
29635c04a7b8SAlexey Dobriyan 					    (currTar_Info->
29645c04a7b8SAlexey Dobriyan 					     TarStatus & ~WIDE_ENABLED) |
29655c04a7b8SAlexey Dobriyan 					    WIDE_NEGOCIATED;
29665c04a7b8SAlexey Dobriyan 
29675c04a7b8SAlexey Dobriyan 					currTar_Info->TarEEValue &=
29685c04a7b8SAlexey Dobriyan 					    ~EE_WIDE_SCSI;
29691da177e4SLinus Torvalds 
29701da177e4SLinus Torvalds 				}
29711da177e4SLinus Torvalds 
29725c04a7b8SAlexey Dobriyan 				else if ((currTar_Info->
29735c04a7b8SAlexey Dobriyan 					  TarStatus & TAR_TAG_Q_MASK) ==
29745c04a7b8SAlexey Dobriyan 					 TAG_Q_TRYING) {
29755c04a7b8SAlexey Dobriyan 					currTar_Info->TarStatus =
29765c04a7b8SAlexey Dobriyan 					    (currTar_Info->
29775c04a7b8SAlexey Dobriyan 					     TarStatus & ~(unsigned char)
29785c04a7b8SAlexey Dobriyan 					     TAR_TAG_Q_MASK) | TAG_Q_REJECT;
29791da177e4SLinus Torvalds 
29801da177e4SLinus Torvalds 					currSCCB->ControlByte &= ~F_USE_CMD_Q;
29811da177e4SLinus Torvalds 					CurrCard->discQCount--;
29825c04a7b8SAlexey Dobriyan 					CurrCard->discQ_Tbl[currSCCB->
29835c04a7b8SAlexey Dobriyan 							    Sccb_tag] = NULL;
29841da177e4SLinus Torvalds 					currSCCB->Sccb_tag = 0x00;
29851da177e4SLinus Torvalds 
29861da177e4SLinus Torvalds 				}
29871da177e4SLinus Torvalds 			}
29881da177e4SLinus Torvalds 
29895c04a7b8SAlexey Dobriyan 			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
29901da177e4SLinus Torvalds 
29915c04a7b8SAlexey Dobriyan 				if (currSCCB->Lun == 0x00) {
29925c04a7b8SAlexey Dobriyan 					WRW_HARPOON((port + hp_intstat),
29935c04a7b8SAlexey Dobriyan 						    BUS_FREE);
29941da177e4SLinus Torvalds 					CurrCard->globalFlags |= F_NEW_SCCB_CMD;
29951da177e4SLinus Torvalds 				}
29961da177e4SLinus Torvalds 			}
29971da177e4SLinus Torvalds 
29985c04a7b8SAlexey Dobriyan 			else {
29991da177e4SLinus Torvalds 
30001da177e4SLinus Torvalds 				if ((CurrCard->globalFlags & F_CONLUN_IO) &&
30015c04a7b8SAlexey Dobriyan 				    ((currTar_Info->
30025c04a7b8SAlexey Dobriyan 				      TarStatus & TAR_TAG_Q_MASK) !=
30035c04a7b8SAlexey Dobriyan 				     TAG_Q_TRYING))
30045c04a7b8SAlexey Dobriyan 					currTar_Info->TarLUNBusy[currSCCB->
30055c04a7b8SAlexey Dobriyan 								 Lun] = 1;
30061da177e4SLinus Torvalds 				else
300747b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[0] = 1;
30081da177e4SLinus Torvalds 
30095c04a7b8SAlexey Dobriyan 				currSCCB->ControlByte &=
30105c04a7b8SAlexey Dobriyan 				    ~(unsigned char)F_USE_CMD_Q;
30111da177e4SLinus Torvalds 
30125c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_1,
30135c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + DISCONNECT_START));
30141da177e4SLinus Torvalds 
30151da177e4SLinus Torvalds 			}
30161da177e4SLinus Torvalds 		}
30171da177e4SLinus Torvalds 
30185c04a7b8SAlexey Dobriyan 		else {
30191da177e4SLinus Torvalds 			ACCEPT_MSG(port);
30201da177e4SLinus Torvalds 
30211da177e4SLinus Torvalds 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
30225c04a7b8SAlexey Dobriyan 			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
30231da177e4SLinus Torvalds 			{
30245c04a7b8SAlexey Dobriyan 			}
30255c04a7b8SAlexey Dobriyan 
30265c04a7b8SAlexey Dobriyan 			if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
30275c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_1,
30285c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + DISCONNECT_START));
30291da177e4SLinus Torvalds 			}
30301da177e4SLinus Torvalds 		}
30311da177e4SLinus Torvalds 	}
30321da177e4SLinus Torvalds 
30335c04a7b8SAlexey Dobriyan 	else if (message == SMEXT) {
30341da177e4SLinus Torvalds 
30351da177e4SLinus Torvalds 		ACCEPT_MSG(port);
303647b5d69cSJames Bottomley  		FPT_shandem(port, p_card, currSCCB);
30371da177e4SLinus Torvalds 	}
30381da177e4SLinus Torvalds 
30395c04a7b8SAlexey Dobriyan 	else if (message == SMIGNORWR) {
30401da177e4SLinus Torvalds 
30411da177e4SLinus Torvalds 		ACCEPT_MSG(port);	/* ACK the RESIDUE MSG */
30421da177e4SLinus Torvalds 
304347b5d69cSJames Bottomley  		message = FPT_sfm(port, currSCCB);
30441da177e4SLinus Torvalds 
30451da177e4SLinus Torvalds 		if (currSCCB->Sccb_scsimsg != SMPARITY)
30461da177e4SLinus Torvalds 			ACCEPT_MSG(port);
30475c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
30485c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
30491da177e4SLinus Torvalds 	}
30501da177e4SLinus Torvalds 
30515c04a7b8SAlexey Dobriyan 	else {
30521da177e4SLinus Torvalds 
30531da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
30541da177e4SLinus Torvalds 		currSCCB->Sccb_scsimsg = SMREJECT;
30551da177e4SLinus Torvalds 
30561da177e4SLinus Torvalds 		ACCEPT_MSG_ATN(port);
30575c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
30585c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
30591da177e4SLinus Torvalds 	}
30601da177e4SLinus Torvalds }
30611da177e4SLinus Torvalds 
30621da177e4SLinus Torvalds /*---------------------------------------------------------------------
30631da177e4SLinus Torvalds  *
306447b5d69cSJames Bottomley   * Function: FPT_shandem
30651da177e4SLinus Torvalds  *
30661da177e4SLinus Torvalds  * Description: Decide what to do with the extended message.
30671da177e4SLinus Torvalds  *
30681da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
3069391e2f25SKhalid Aziz static void FPT_shandem(u32 port, unsigned char p_card, struct sccb *pCurrSCCB)
30701da177e4SLinus Torvalds {
3071db038cf8SAlexey Dobriyan 	unsigned char length, message;
30721da177e4SLinus Torvalds 
307347b5d69cSJames Bottomley  	length = FPT_sfm(port, pCurrSCCB);
30745c04a7b8SAlexey Dobriyan 	if (length) {
30751da177e4SLinus Torvalds 
30761da177e4SLinus Torvalds 		ACCEPT_MSG(port);
307747b5d69cSJames Bottomley  		message = FPT_sfm(port, pCurrSCCB);
30785c04a7b8SAlexey Dobriyan 		if (message) {
30791da177e4SLinus Torvalds 
30805c04a7b8SAlexey Dobriyan 			if (message == SMSYNC) {
30811da177e4SLinus Torvalds 
30825c04a7b8SAlexey Dobriyan 				if (length == 0x03) {
30831da177e4SLinus Torvalds 
30841da177e4SLinus Torvalds 					ACCEPT_MSG(port);
308547b5d69cSJames Bottomley  					FPT_stsyncn(port, p_card);
30865c04a7b8SAlexey Dobriyan 				} else {
30871da177e4SLinus Torvalds 
30881da177e4SLinus Torvalds 					pCurrSCCB->Sccb_scsimsg = SMREJECT;
30891da177e4SLinus Torvalds 					ACCEPT_MSG_ATN(port);
30901da177e4SLinus Torvalds 				}
30915c04a7b8SAlexey Dobriyan 			} else if (message == SMWDTR) {
30921da177e4SLinus Torvalds 
30935c04a7b8SAlexey Dobriyan 				if (length == 0x02) {
30941da177e4SLinus Torvalds 
30951da177e4SLinus Torvalds 					ACCEPT_MSG(port);
309647b5d69cSJames Bottomley  					FPT_stwidn(port, p_card);
30975c04a7b8SAlexey Dobriyan 				} else {
30981da177e4SLinus Torvalds 
30991da177e4SLinus Torvalds 					pCurrSCCB->Sccb_scsimsg = SMREJECT;
31001da177e4SLinus Torvalds 					ACCEPT_MSG_ATN(port);
31011da177e4SLinus Torvalds 
31025c04a7b8SAlexey Dobriyan 					WR_HARPOON(port + hp_autostart_1,
31035c04a7b8SAlexey Dobriyan 						   (AUTO_IMMED +
31045c04a7b8SAlexey Dobriyan 						    DISCONNECT_START));
31051da177e4SLinus Torvalds 				}
31065c04a7b8SAlexey Dobriyan 			} else {
31071da177e4SLinus Torvalds 
31081da177e4SLinus Torvalds 				pCurrSCCB->Sccb_scsimsg = SMREJECT;
31091da177e4SLinus Torvalds 				ACCEPT_MSG_ATN(port);
31101da177e4SLinus Torvalds 
31115c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_1,
31125c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + DISCONNECT_START));
31131da177e4SLinus Torvalds 			}
31145c04a7b8SAlexey Dobriyan 		} else {
31151da177e4SLinus Torvalds 			if (pCurrSCCB->Sccb_scsimsg != SMPARITY)
31161da177e4SLinus Torvalds 				ACCEPT_MSG(port);
31175c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
31185c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
31191da177e4SLinus Torvalds 		}
31205c04a7b8SAlexey Dobriyan 	} else {
31211da177e4SLinus Torvalds 		if (pCurrSCCB->Sccb_scsimsg == SMPARITY)
31225c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
31235c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
31241da177e4SLinus Torvalds 	}
31251da177e4SLinus Torvalds }
31261da177e4SLinus Torvalds 
31271da177e4SLinus Torvalds /*---------------------------------------------------------------------
31281da177e4SLinus Torvalds  *
312947b5d69cSJames Bottomley   * Function: FPT_sisyncn
31301da177e4SLinus Torvalds  *
31311da177e4SLinus Torvalds  * Description: Read in a message byte from the SCSI bus, and check
31321da177e4SLinus Torvalds  *              for a parity error.
31331da177e4SLinus Torvalds  *
31341da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
31351da177e4SLinus Torvalds 
3136391e2f25SKhalid Aziz static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
31375c04a7b8SAlexey Dobriyan 				 unsigned char syncFlag)
31381da177e4SLinus Torvalds {
313969eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3140f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
31411da177e4SLinus Torvalds 
314247b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
314347b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
31441da177e4SLinus Torvalds 
31451da177e4SLinus Torvalds 	if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
31461da177e4SLinus Torvalds 
31471da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT),
31485c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT +
31495c04a7b8SAlexey Dobriyan 			     (currSCCB->
31505c04a7b8SAlexey Dobriyan 			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
31511da177e4SLinus Torvalds 
31521da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
31531da177e4SLinus Torvalds 
31545c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 0),
31555c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + SMEXT));
31561da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
31575c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 4),
31585c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + SMSYNC));
31591da177e4SLinus Torvalds 
31601da177e4SLinus Torvalds 		if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
31611da177e4SLinus Torvalds 
31625c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31635c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 12));
31641da177e4SLinus Torvalds 
31655c04a7b8SAlexey Dobriyan 		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
31665c04a7b8SAlexey Dobriyan 			 EE_SYNC_10MB)
31671da177e4SLinus Torvalds 
31685c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31695c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 25));
31701da177e4SLinus Torvalds 
31715c04a7b8SAlexey Dobriyan 		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
31725c04a7b8SAlexey Dobriyan 			 EE_SYNC_5MB)
31731da177e4SLinus Torvalds 
31745c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31755c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 50));
31761da177e4SLinus Torvalds 
31771da177e4SLinus Torvalds 		else
31785c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31795c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 00));
31801da177e4SLinus Torvalds 
31811da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
31825c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 10),
31835c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
31841da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
31851da177e4SLinus Torvalds 
31865c04a7b8SAlexey Dobriyan 		if (syncFlag == 0) {
31875c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_3,
31885c04a7b8SAlexey Dobriyan 				   (SELECT + SELCHK_STRT));
31895c04a7b8SAlexey Dobriyan 			currTar_Info->TarStatus =
31905c04a7b8SAlexey Dobriyan 			    ((currTar_Info->
31915c04a7b8SAlexey Dobriyan 			      TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
31925c04a7b8SAlexey Dobriyan 			     (unsigned char)SYNC_TRYING);
31935c04a7b8SAlexey Dobriyan 		} else {
31945c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_3,
31955c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + CMD_ONLY_STRT));
31961da177e4SLinus Torvalds 		}
31971da177e4SLinus Torvalds 
31985c1b85e2SAlexey Dobriyan 		return 1;
31991da177e4SLinus Torvalds 	}
32001da177e4SLinus Torvalds 
32011da177e4SLinus Torvalds 	else {
32021da177e4SLinus Torvalds 
3203db038cf8SAlexey Dobriyan 		currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
32041da177e4SLinus Torvalds 		currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
32055c1b85e2SAlexey Dobriyan 		return 0;
32061da177e4SLinus Torvalds 	}
32071da177e4SLinus Torvalds }
32081da177e4SLinus Torvalds 
32091da177e4SLinus Torvalds /*---------------------------------------------------------------------
32101da177e4SLinus Torvalds  *
321147b5d69cSJames Bottomley   * Function: FPT_stsyncn
32121da177e4SLinus Torvalds  *
32131da177e4SLinus Torvalds  * Description: The has sent us a Sync Nego message so handle it as
32141da177e4SLinus Torvalds  *              necessary.
32151da177e4SLinus Torvalds  *
32161da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
3217391e2f25SKhalid Aziz static void FPT_stsyncn(u32 port, unsigned char p_card)
32181da177e4SLinus Torvalds {
3219db038cf8SAlexey Dobriyan 	unsigned char sync_msg, offset, sync_reg, our_sync_msg;
322069eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3221f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
32221da177e4SLinus Torvalds 
322347b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
322447b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
32251da177e4SLinus Torvalds 
322647b5d69cSJames Bottomley  	sync_msg = FPT_sfm(port, currSCCB);
32271da177e4SLinus Torvalds 
32285c04a7b8SAlexey Dobriyan 	if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
32295c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
32305c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
32311da177e4SLinus Torvalds 		return;
32321da177e4SLinus Torvalds 	}
32331da177e4SLinus Torvalds 
32341da177e4SLinus Torvalds 	ACCEPT_MSG(port);
32351da177e4SLinus Torvalds 
323647b5d69cSJames Bottomley  	offset = FPT_sfm(port, currSCCB);
32371da177e4SLinus Torvalds 
32385c04a7b8SAlexey Dobriyan 	if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
32395c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
32405c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
32411da177e4SLinus Torvalds 		return;
32421da177e4SLinus Torvalds 	}
32431da177e4SLinus Torvalds 
32441da177e4SLinus Torvalds 	if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
32451da177e4SLinus Torvalds 
32461da177e4SLinus Torvalds 		our_sync_msg = 12;	/* Setup our Message to 20mb/s */
32471da177e4SLinus Torvalds 
32481da177e4SLinus Torvalds 	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
32491da177e4SLinus Torvalds 
32501da177e4SLinus Torvalds 		our_sync_msg = 25;	/* Setup our Message to 10mb/s */
32511da177e4SLinus Torvalds 
32521da177e4SLinus Torvalds 	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
32531da177e4SLinus Torvalds 
32541da177e4SLinus Torvalds 		our_sync_msg = 50;	/* Setup our Message to 5mb/s */
32551da177e4SLinus Torvalds 	else
32561da177e4SLinus Torvalds 
32571da177e4SLinus Torvalds 		our_sync_msg = 0;	/* Message = Async */
32581da177e4SLinus Torvalds 
32591da177e4SLinus Torvalds 	if (sync_msg < our_sync_msg) {
32601da177e4SLinus Torvalds 		sync_msg = our_sync_msg;	/*if faster, then set to max. */
32611da177e4SLinus Torvalds 	}
32621da177e4SLinus Torvalds 
32631da177e4SLinus Torvalds 	if (offset == ASYNC)
32641da177e4SLinus Torvalds 		sync_msg = ASYNC;
32651da177e4SLinus Torvalds 
32661da177e4SLinus Torvalds 	if (offset > MAX_OFFSET)
32671da177e4SLinus Torvalds 		offset = MAX_OFFSET;
32681da177e4SLinus Torvalds 
32691da177e4SLinus Torvalds 	sync_reg = 0x00;
32701da177e4SLinus Torvalds 
32711da177e4SLinus Torvalds 	if (sync_msg > 12)
32721da177e4SLinus Torvalds 
32731da177e4SLinus Torvalds 		sync_reg = 0x20;	/* Use 10MB/s */
32741da177e4SLinus Torvalds 
32751da177e4SLinus Torvalds 	if (sync_msg > 25)
32761da177e4SLinus Torvalds 
32771da177e4SLinus Torvalds 		sync_reg = 0x40;	/* Use 6.6MB/s */
32781da177e4SLinus Torvalds 
32791da177e4SLinus Torvalds 	if (sync_msg > 38)
32801da177e4SLinus Torvalds 
32811da177e4SLinus Torvalds 		sync_reg = 0x60;	/* Use 5MB/s */
32821da177e4SLinus Torvalds 
32831da177e4SLinus Torvalds 	if (sync_msg > 50)
32841da177e4SLinus Torvalds 
32851da177e4SLinus Torvalds 		sync_reg = 0x80;	/* Use 4MB/s */
32861da177e4SLinus Torvalds 
32871da177e4SLinus Torvalds 	if (sync_msg > 62)
32881da177e4SLinus Torvalds 
32891da177e4SLinus Torvalds 		sync_reg = 0xA0;	/* Use 3.33MB/s */
32901da177e4SLinus Torvalds 
32911da177e4SLinus Torvalds 	if (sync_msg > 75)
32921da177e4SLinus Torvalds 
32931da177e4SLinus Torvalds 		sync_reg = 0xC0;	/* Use 2.85MB/s */
32941da177e4SLinus Torvalds 
32951da177e4SLinus Torvalds 	if (sync_msg > 87)
32961da177e4SLinus Torvalds 
32971da177e4SLinus Torvalds 		sync_reg = 0xE0;	/* Use 2.5MB/s */
32981da177e4SLinus Torvalds 
32991da177e4SLinus Torvalds 	if (sync_msg > 100) {
33001da177e4SLinus Torvalds 
33011da177e4SLinus Torvalds 		sync_reg = 0x00;	/* Use ASYNC */
33021da177e4SLinus Torvalds 		offset = 0x00;
33031da177e4SLinus Torvalds 	}
33041da177e4SLinus Torvalds 
33051da177e4SLinus Torvalds 	if (currTar_Info->TarStatus & WIDE_ENABLED)
33061da177e4SLinus Torvalds 
33071da177e4SLinus Torvalds 		sync_reg |= offset;
33081da177e4SLinus Torvalds 
33091da177e4SLinus Torvalds 	else
33101da177e4SLinus Torvalds 
33111da177e4SLinus Torvalds 		sync_reg |= (offset | NARROW_SCSI);
33121da177e4SLinus Torvalds 
331347b5d69cSJames Bottomley  	FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
33141da177e4SLinus Torvalds 
33151da177e4SLinus Torvalds 	if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
33161da177e4SLinus Torvalds 
33171da177e4SLinus Torvalds 		ACCEPT_MSG(port);
33181da177e4SLinus Torvalds 
33191da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
33205c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_SYNC_MASK) |
33215c04a7b8SAlexey Dobriyan 					   (unsigned char)SYNC_SUPPORTED);
33221da177e4SLinus Torvalds 
33235c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
33245c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
33251da177e4SLinus Torvalds 	}
33261da177e4SLinus Torvalds 
33271da177e4SLinus Torvalds 	else {
33281da177e4SLinus Torvalds 
33291da177e4SLinus Torvalds 		ACCEPT_MSG_ATN(port);
33301da177e4SLinus Torvalds 
333147b5d69cSJames Bottomley  		FPT_sisyncr(port, sync_msg, offset);
33321da177e4SLinus Torvalds 
33331da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
33345c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_SYNC_MASK) |
33355c04a7b8SAlexey Dobriyan 					   (unsigned char)SYNC_SUPPORTED);
33361da177e4SLinus Torvalds 	}
33371da177e4SLinus Torvalds }
33381da177e4SLinus Torvalds 
33391da177e4SLinus Torvalds /*---------------------------------------------------------------------
33401da177e4SLinus Torvalds  *
334147b5d69cSJames Bottomley   * Function: FPT_sisyncr
33421da177e4SLinus Torvalds  *
33431da177e4SLinus Torvalds  * Description: Answer the targets sync message.
33441da177e4SLinus Torvalds  *
33451da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
3346391e2f25SKhalid Aziz static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
33475c04a7b8SAlexey Dobriyan 			unsigned char offset)
33481da177e4SLinus Torvalds {
33491da177e4SLinus Torvalds 	ARAM_ACCESS(port);
33501da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
33511da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
33521da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC));
33531da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
33541da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
33551da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
33561da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
33571da177e4SLinus Torvalds 	SGRAM_ACCESS(port);
33581da177e4SLinus Torvalds 
33591da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
33601da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
33611da177e4SLinus Torvalds 
33621da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
33631da177e4SLinus Torvalds 
33645c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
33651da177e4SLinus Torvalds 	}
33665c04a7b8SAlexey Dobriyan }
33671da177e4SLinus Torvalds 
33681da177e4SLinus Torvalds /*---------------------------------------------------------------------
33691da177e4SLinus Torvalds  *
337047b5d69cSJames Bottomley   * Function: FPT_siwidn
33711da177e4SLinus Torvalds  *
33721da177e4SLinus Torvalds  * Description: Read in a message byte from the SCSI bus, and check
33731da177e4SLinus Torvalds  *              for a parity error.
33741da177e4SLinus Torvalds  *
33751da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
33761da177e4SLinus Torvalds 
3377391e2f25SKhalid Aziz static unsigned char FPT_siwidn(u32 port, unsigned char p_card)
33781da177e4SLinus Torvalds {
337969eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3380f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
33811da177e4SLinus Torvalds 
338247b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
338347b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
33841da177e4SLinus Torvalds 
33851da177e4SLinus Torvalds 	if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
33861da177e4SLinus Torvalds 
33871da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT),
33885c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT +
33895c04a7b8SAlexey Dobriyan 			     (currSCCB->
33905c04a7b8SAlexey Dobriyan 			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
33911da177e4SLinus Torvalds 
33921da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
33931da177e4SLinus Torvalds 
33945c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 0),
33955c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + SMEXT));
33961da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
33975c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 4),
33985c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + SMWDTR));
33991da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
34005c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 8),
34015c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + SM16BIT));
34021da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
34031da177e4SLinus Torvalds 
34041da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
34051da177e4SLinus Torvalds 
34061da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
34075c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_WIDE_MASK) |
34085c04a7b8SAlexey Dobriyan 					   (unsigned char)WIDE_ENABLED);
34091da177e4SLinus Torvalds 
34105c1b85e2SAlexey Dobriyan 		return 1;
34111da177e4SLinus Torvalds 	}
34121da177e4SLinus Torvalds 
34131da177e4SLinus Torvalds 	else {
34141da177e4SLinus Torvalds 
34151da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
34165c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_WIDE_MASK) |
34175c04a7b8SAlexey Dobriyan 					   WIDE_NEGOCIATED);
34181da177e4SLinus Torvalds 
34191da177e4SLinus Torvalds 		currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
34205c1b85e2SAlexey Dobriyan 		return 0;
34211da177e4SLinus Torvalds 	}
34221da177e4SLinus Torvalds }
34231da177e4SLinus Torvalds 
34241da177e4SLinus Torvalds /*---------------------------------------------------------------------
34251da177e4SLinus Torvalds  *
342647b5d69cSJames Bottomley   * Function: FPT_stwidn
34271da177e4SLinus Torvalds  *
34281da177e4SLinus Torvalds  * Description: The has sent us a Wide Nego message so handle it as
34291da177e4SLinus Torvalds  *              necessary.
34301da177e4SLinus Torvalds  *
34311da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
3432391e2f25SKhalid Aziz static void FPT_stwidn(u32 port, unsigned char p_card)
34331da177e4SLinus Torvalds {
3434db038cf8SAlexey Dobriyan 	unsigned char width;
343569eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3436f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
34371da177e4SLinus Torvalds 
343847b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
343947b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
34401da177e4SLinus Torvalds 
344147b5d69cSJames Bottomley  	width = FPT_sfm(port, currSCCB);
34421da177e4SLinus Torvalds 
34435c04a7b8SAlexey Dobriyan 	if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
34445c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
34455c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
34461da177e4SLinus Torvalds 		return;
34471da177e4SLinus Torvalds 	}
34481da177e4SLinus Torvalds 
34491da177e4SLinus Torvalds 	if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
34501da177e4SLinus Torvalds 		width = 0;
34511da177e4SLinus Torvalds 
34521da177e4SLinus Torvalds 	if (width) {
34531da177e4SLinus Torvalds 		currTar_Info->TarStatus |= WIDE_ENABLED;
34541da177e4SLinus Torvalds 		width = 0;
34555c04a7b8SAlexey Dobriyan 	} else {
34561da177e4SLinus Torvalds 		width = NARROW_SCSI;
34571da177e4SLinus Torvalds 		currTar_Info->TarStatus &= ~WIDE_ENABLED;
34581da177e4SLinus Torvalds 	}
34591da177e4SLinus Torvalds 
346047b5d69cSJames Bottomley  	FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
34611da177e4SLinus Torvalds 
34625c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
34631da177e4SLinus Torvalds 
34641da177e4SLinus Torvalds 		currTar_Info->TarStatus |= WIDE_NEGOCIATED;
34651da177e4SLinus Torvalds 
34665c04a7b8SAlexey Dobriyan 		if (!
34675c04a7b8SAlexey Dobriyan 		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
34685c04a7b8SAlexey Dobriyan 		     SYNC_SUPPORTED)) {
34691da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
34701da177e4SLinus Torvalds 			ARAM_ACCESS(port);
347147b5d69cSJames Bottomley  			FPT_sisyncn(port, p_card, 1);
34721da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = SELECT_SN_ST;
34731da177e4SLinus Torvalds 			SGRAM_ACCESS(port);
34745c04a7b8SAlexey Dobriyan 		} else {
34751da177e4SLinus Torvalds 			ACCEPT_MSG(port);
34765c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
34775c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
34781da177e4SLinus Torvalds 		}
34791da177e4SLinus Torvalds 	}
34801da177e4SLinus Torvalds 
34811da177e4SLinus Torvalds 	else {
34821da177e4SLinus Torvalds 
34831da177e4SLinus Torvalds 		ACCEPT_MSG_ATN(port);
34841da177e4SLinus Torvalds 
34851da177e4SLinus Torvalds 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
34861da177e4SLinus Torvalds 			width = SM16BIT;
34871da177e4SLinus Torvalds 		else
34881da177e4SLinus Torvalds 			width = SM8BIT;
34891da177e4SLinus Torvalds 
349047b5d69cSJames Bottomley  		FPT_siwidr(port, width);
34911da177e4SLinus Torvalds 
34921da177e4SLinus Torvalds 		currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
34931da177e4SLinus Torvalds 	}
34941da177e4SLinus Torvalds }
34951da177e4SLinus Torvalds 
34961da177e4SLinus Torvalds /*---------------------------------------------------------------------
34971da177e4SLinus Torvalds  *
349847b5d69cSJames Bottomley   * Function: FPT_siwidr
34991da177e4SLinus Torvalds  *
35001da177e4SLinus Torvalds  * Description: Answer the targets Wide nego message.
35011da177e4SLinus Torvalds  *
35021da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
3503391e2f25SKhalid Aziz static void FPT_siwidr(u32 port, unsigned char width)
35041da177e4SLinus Torvalds {
35051da177e4SLinus Torvalds 	ARAM_ACCESS(port);
35061da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
35071da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
35081da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR));
35091da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
35101da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
35111da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
35121da177e4SLinus Torvalds 	SGRAM_ACCESS(port);
35131da177e4SLinus Torvalds 
35141da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
35151da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
35161da177e4SLinus Torvalds 
35171da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
35181da177e4SLinus Torvalds 
35195c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
35201da177e4SLinus Torvalds 	}
35215c04a7b8SAlexey Dobriyan }
35221da177e4SLinus Torvalds 
35231da177e4SLinus Torvalds /*---------------------------------------------------------------------
35241da177e4SLinus Torvalds  *
352547b5d69cSJames Bottomley   * Function: FPT_sssyncv
35261da177e4SLinus Torvalds  *
35271da177e4SLinus Torvalds  * Description: Write the desired value to the Sync Register for the
35281da177e4SLinus Torvalds  *              ID specified.
35291da177e4SLinus Torvalds  *
35301da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
3531391e2f25SKhalid Aziz static void FPT_sssyncv(u32 p_port, unsigned char p_id,
35325c04a7b8SAlexey Dobriyan 			unsigned char p_sync_value,
3533f31dc0cdSAlexey Dobriyan 			struct sccb_mgr_tar_info *currTar_Info)
35341da177e4SLinus Torvalds {
3535db038cf8SAlexey Dobriyan 	unsigned char index;
35361da177e4SLinus Torvalds 
35371da177e4SLinus Torvalds 	index = p_id;
35381da177e4SLinus Torvalds 
35391da177e4SLinus Torvalds 	switch (index) {
35401da177e4SLinus Torvalds 
35411da177e4SLinus Torvalds 	case 0:
35421da177e4SLinus Torvalds 		index = 12;	/* hp_synctarg_0 */
35431da177e4SLinus Torvalds 		break;
35441da177e4SLinus Torvalds 	case 1:
35451da177e4SLinus Torvalds 		index = 13;	/* hp_synctarg_1 */
35461da177e4SLinus Torvalds 		break;
35471da177e4SLinus Torvalds 	case 2:
35481da177e4SLinus Torvalds 		index = 14;	/* hp_synctarg_2 */
35491da177e4SLinus Torvalds 		break;
35501da177e4SLinus Torvalds 	case 3:
35511da177e4SLinus Torvalds 		index = 15;	/* hp_synctarg_3 */
35521da177e4SLinus Torvalds 		break;
35531da177e4SLinus Torvalds 	case 4:
35541da177e4SLinus Torvalds 		index = 8;	/* hp_synctarg_4 */
35551da177e4SLinus Torvalds 		break;
35561da177e4SLinus Torvalds 	case 5:
35571da177e4SLinus Torvalds 		index = 9;	/* hp_synctarg_5 */
35581da177e4SLinus Torvalds 		break;
35591da177e4SLinus Torvalds 	case 6:
35601da177e4SLinus Torvalds 		index = 10;	/* hp_synctarg_6 */
35611da177e4SLinus Torvalds 		break;
35621da177e4SLinus Torvalds 	case 7:
35631da177e4SLinus Torvalds 		index = 11;	/* hp_synctarg_7 */
35641da177e4SLinus Torvalds 		break;
35651da177e4SLinus Torvalds 	case 8:
35661da177e4SLinus Torvalds 		index = 4;	/* hp_synctarg_8 */
35671da177e4SLinus Torvalds 		break;
35681da177e4SLinus Torvalds 	case 9:
35691da177e4SLinus Torvalds 		index = 5;	/* hp_synctarg_9 */
35701da177e4SLinus Torvalds 		break;
35711da177e4SLinus Torvalds 	case 10:
35721da177e4SLinus Torvalds 		index = 6;	/* hp_synctarg_10 */
35731da177e4SLinus Torvalds 		break;
35741da177e4SLinus Torvalds 	case 11:
35751da177e4SLinus Torvalds 		index = 7;	/* hp_synctarg_11 */
35761da177e4SLinus Torvalds 		break;
35771da177e4SLinus Torvalds 	case 12:
35781da177e4SLinus Torvalds 		index = 0;	/* hp_synctarg_12 */
35791da177e4SLinus Torvalds 		break;
35801da177e4SLinus Torvalds 	case 13:
35811da177e4SLinus Torvalds 		index = 1;	/* hp_synctarg_13 */
35821da177e4SLinus Torvalds 		break;
35831da177e4SLinus Torvalds 	case 14:
35841da177e4SLinus Torvalds 		index = 2;	/* hp_synctarg_14 */
35851da177e4SLinus Torvalds 		break;
35861da177e4SLinus Torvalds 	case 15:
35871da177e4SLinus Torvalds 		index = 3;	/* hp_synctarg_15 */
35881da177e4SLinus Torvalds 
35891da177e4SLinus Torvalds 	}
35901da177e4SLinus Torvalds 
35911da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
35921da177e4SLinus Torvalds 
35931da177e4SLinus Torvalds 	currTar_Info->TarSyncCtrl = p_sync_value;
35941da177e4SLinus Torvalds }
35951da177e4SLinus Torvalds 
35961da177e4SLinus Torvalds /*---------------------------------------------------------------------
35971da177e4SLinus Torvalds  *
359847b5d69cSJames Bottomley   * Function: FPT_sresb
35991da177e4SLinus Torvalds  *
36001da177e4SLinus Torvalds  * Description: Reset the desired card's SCSI bus.
36011da177e4SLinus Torvalds  *
36021da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
3603391e2f25SKhalid Aziz static void FPT_sresb(u32 port, unsigned char p_card)
36041da177e4SLinus Torvalds {
3605db038cf8SAlexey Dobriyan 	unsigned char scsiID, i;
36061da177e4SLinus Torvalds 
3607f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
36081da177e4SLinus Torvalds 
36091da177e4SLinus Torvalds 	WR_HARPOON(port + hp_page_ctrl,
36101da177e4SLinus Torvalds 		   (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
36111da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
36121da177e4SLinus Torvalds 
36131da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
36141da177e4SLinus Torvalds 
36151da177e4SLinus Torvalds 	scsiID = RD_HARPOON(port + hp_seltimeout);
36161da177e4SLinus Torvalds 	WR_HARPOON(port + hp_seltimeout, TO_5ms);
36171da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), TIMEOUT);
36181da177e4SLinus Torvalds 
36191da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
36201da177e4SLinus Torvalds 
36215c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
36225c04a7b8SAlexey Dobriyan 	}
36231da177e4SLinus Torvalds 
36241da177e4SLinus Torvalds 	WR_HARPOON(port + hp_seltimeout, scsiID);
36251da177e4SLinus Torvalds 
36261da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
36271da177e4SLinus Torvalds 
362847b5d69cSJames Bottomley  	FPT_Wait(port, TO_5ms);
36291da177e4SLinus Torvalds 
36301da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
36311da177e4SLinus Torvalds 
36321da177e4SLinus Torvalds 	WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
36331da177e4SLinus Torvalds 
36345c04a7b8SAlexey Dobriyan 	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
363547b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
36361da177e4SLinus Torvalds 
36375c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
36381da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
36391da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
36401da177e4SLinus Torvalds 		}
36411da177e4SLinus Torvalds 
36425c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
36431da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
36441da177e4SLinus Torvalds 		}
36451da177e4SLinus Torvalds 
364647b5d69cSJames Bottomley  		FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
36471da177e4SLinus Torvalds 
364847b5d69cSJames Bottomley  		FPT_SccbMgrTableInitTarget(p_card, scsiID);
36491da177e4SLinus Torvalds 	}
36501da177e4SLinus Torvalds 
365147b5d69cSJames Bottomley  	FPT_BL_Card[p_card].scanIndex = 0x00;
365247b5d69cSJames Bottomley  	FPT_BL_Card[p_card].currentSCCB = NULL;
365347b5d69cSJames Bottomley  	FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
36541da177e4SLinus Torvalds 					     | F_NEW_SCCB_CMD);
365547b5d69cSJames Bottomley  	FPT_BL_Card[p_card].cmdCounter = 0x00;
365647b5d69cSJames Bottomley  	FPT_BL_Card[p_card].discQCount = 0x00;
365747b5d69cSJames Bottomley  	FPT_BL_Card[p_card].tagQ_Lst = 0x01;
36581da177e4SLinus Torvalds 
36591da177e4SLinus Torvalds 	for (i = 0; i < QUEUE_DEPTH; i++)
366047b5d69cSJames Bottomley  		FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
36611da177e4SLinus Torvalds 
36621da177e4SLinus Torvalds 	WR_HARPOON(port + hp_page_ctrl,
36631da177e4SLinus Torvalds 		   (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
36641da177e4SLinus Torvalds 
36651da177e4SLinus Torvalds }
36661da177e4SLinus Torvalds 
36671da177e4SLinus Torvalds /*---------------------------------------------------------------------
36681da177e4SLinus Torvalds  *
366947b5d69cSJames Bottomley   * Function: FPT_ssenss
36701da177e4SLinus Torvalds  *
36711da177e4SLinus Torvalds  * Description: Setup for the Auto Sense command.
36721da177e4SLinus Torvalds  *
36731da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
367413e6851aSAlexey Dobriyan static void FPT_ssenss(struct sccb_card *pCurrCard)
36751da177e4SLinus Torvalds {
3676db038cf8SAlexey Dobriyan 	unsigned char i;
367769eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
36781da177e4SLinus Torvalds 
36791da177e4SLinus Torvalds 	currSCCB = pCurrCard->currentSCCB;
36801da177e4SLinus Torvalds 
36811da177e4SLinus Torvalds 	currSCCB->Save_CdbLen = currSCCB->CdbLength;
36821da177e4SLinus Torvalds 
36831da177e4SLinus Torvalds 	for (i = 0; i < 6; i++) {
36841da177e4SLinus Torvalds 
36851da177e4SLinus Torvalds 		currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
36861da177e4SLinus Torvalds 	}
36871da177e4SLinus Torvalds 
36881da177e4SLinus Torvalds 	currSCCB->CdbLength = SIX_BYTE_CMD;
36891da177e4SLinus Torvalds 	currSCCB->Cdb[0] = SCSI_REQUEST_SENSE;
3690db038cf8SAlexey Dobriyan 	currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0;	/*Keep LUN. */
36911da177e4SLinus Torvalds 	currSCCB->Cdb[2] = 0x00;
36921da177e4SLinus Torvalds 	currSCCB->Cdb[3] = 0x00;
36931da177e4SLinus Torvalds 	currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
36941da177e4SLinus Torvalds 	currSCCB->Cdb[5] = 0x00;
36951da177e4SLinus Torvalds 
3696391e2f25SKhalid Aziz 	currSCCB->Sccb_XferCnt = (u32)currSCCB->RequestSenseLength;
36971da177e4SLinus Torvalds 
36981da177e4SLinus Torvalds 	currSCCB->Sccb_ATC = 0x00;
36991da177e4SLinus Torvalds 
37001da177e4SLinus Torvalds 	currSCCB->Sccb_XferState |= F_AUTO_SENSE;
37011da177e4SLinus Torvalds 
37021da177e4SLinus Torvalds 	currSCCB->Sccb_XferState &= ~F_SG_XFER;
37031da177e4SLinus Torvalds 
3704db038cf8SAlexey Dobriyan 	currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
37051da177e4SLinus Torvalds 
37061da177e4SLinus Torvalds 	currSCCB->ControlByte = 0x00;
37071da177e4SLinus Torvalds 
37081da177e4SLinus Torvalds 	currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
37091da177e4SLinus Torvalds }
37101da177e4SLinus Torvalds 
37111da177e4SLinus Torvalds /*---------------------------------------------------------------------
37121da177e4SLinus Torvalds  *
371347b5d69cSJames Bottomley   * Function: FPT_sxfrp
37141da177e4SLinus Torvalds  *
37151da177e4SLinus Torvalds  * Description: Transfer data into the bit bucket until the device
37161da177e4SLinus Torvalds  *              decides to switch phase.
37171da177e4SLinus Torvalds  *
37181da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
37191da177e4SLinus Torvalds 
3720391e2f25SKhalid Aziz static void FPT_sxfrp(u32 p_port, unsigned char p_card)
37211da177e4SLinus Torvalds {
3722db038cf8SAlexey Dobriyan 	unsigned char curr_phz;
37231da177e4SLinus Torvalds 
37241da177e4SLinus Torvalds 	DISABLE_AUTO(p_port);
37251da177e4SLinus Torvalds 
372647b5d69cSJames Bottomley  	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
37271da177e4SLinus Torvalds 
37285c04a7b8SAlexey Dobriyan 		FPT_hostDataXferAbort(p_port, p_card,
37295c04a7b8SAlexey Dobriyan 				      FPT_BL_Card[p_card].currentSCCB);
37301da177e4SLinus Torvalds 
37311da177e4SLinus Torvalds 	}
37321da177e4SLinus Torvalds 
37331da177e4SLinus Torvalds 	/* If the Automation handled the end of the transfer then do not
37341da177e4SLinus Torvalds 	   match the phase or we will get out of sync with the ISR.       */
37351da177e4SLinus Torvalds 
37365c04a7b8SAlexey Dobriyan 	if (RDW_HARPOON((p_port + hp_intstat)) &
37375c04a7b8SAlexey Dobriyan 	    (BUS_FREE | XFER_CNT_0 | AUTO_INT))
37381da177e4SLinus Torvalds 		return;
37391da177e4SLinus Torvalds 
37401da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
37411da177e4SLinus Torvalds 
3742db038cf8SAlexey Dobriyan 	curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
37431da177e4SLinus Torvalds 
37441da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
37451da177e4SLinus Torvalds 
37461da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, curr_phz);
37471da177e4SLinus Torvalds 
37481da177e4SLinus Torvalds 	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
37495c04a7b8SAlexey Dobriyan 	       (curr_phz ==
37505c04a7b8SAlexey Dobriyan 		(RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
37511da177e4SLinus Torvalds 	{
37525c04a7b8SAlexey Dobriyan 		if (curr_phz & (unsigned char)SCSI_IOBIT) {
37535c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_portctrl_0,
37545c04a7b8SAlexey Dobriyan 				   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
37551da177e4SLinus Torvalds 
37565c04a7b8SAlexey Dobriyan 			if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
37571da177e4SLinus Torvalds 				RD_HARPOON(p_port + hp_fifodata_0);
37581da177e4SLinus Torvalds 			}
37595c04a7b8SAlexey Dobriyan 		} else {
37605c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_portctrl_0,
37615c04a7b8SAlexey Dobriyan 				   (SCSI_PORT | HOST_PORT | HOST_WRT));
37625c04a7b8SAlexey Dobriyan 			if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
37631da177e4SLinus Torvalds 				WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
37641da177e4SLinus Torvalds 			}
37651da177e4SLinus Torvalds 		}
37661da177e4SLinus Torvalds 	}			/* End of While loop for padding data I/O phase */
37671da177e4SLinus Torvalds 
37685c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
37691da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
37701da177e4SLinus Torvalds 			break;
37711da177e4SLinus Torvalds 	}
37721da177e4SLinus Torvalds 
37735c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_portctrl_0,
37745c04a7b8SAlexey Dobriyan 		   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
37755c04a7b8SAlexey Dobriyan 	while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
37761da177e4SLinus Torvalds 		RD_HARPOON(p_port + hp_fifodata_0);
37771da177e4SLinus Torvalds 	}
37781da177e4SLinus Torvalds 
37795c04a7b8SAlexey Dobriyan 	if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
37805c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_autostart_0,
37815c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
37825c04a7b8SAlexey Dobriyan 		while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
37831da177e4SLinus Torvalds 		}
37841da177e4SLinus Torvalds 
37855c04a7b8SAlexey Dobriyan 		if (RDW_HARPOON((p_port + hp_intstat)) &
37865c04a7b8SAlexey Dobriyan 		    (ICMD_COMP | ITAR_DISC))
37875c04a7b8SAlexey Dobriyan 			while (!
37885c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((p_port + hp_intstat)) &
37895c04a7b8SAlexey Dobriyan 				(BUS_FREE | RSEL))) ;
37905c04a7b8SAlexey Dobriyan 	}
37915c04a7b8SAlexey Dobriyan }
37921da177e4SLinus Torvalds 
37931da177e4SLinus Torvalds /*---------------------------------------------------------------------
37941da177e4SLinus Torvalds  *
379547b5d69cSJames Bottomley   * Function: FPT_schkdd
37961da177e4SLinus Torvalds  *
37971da177e4SLinus Torvalds  * Description: Make sure data has been flushed from both FIFOs and abort
37981da177e4SLinus Torvalds  *              the operations if necessary.
37991da177e4SLinus Torvalds  *
38001da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
38011da177e4SLinus Torvalds 
3802391e2f25SKhalid Aziz static void FPT_schkdd(u32 port, unsigned char p_card)
38031da177e4SLinus Torvalds {
3804c823feebSAlexey Dobriyan 	unsigned short TimeOutLoop;
3805db038cf8SAlexey Dobriyan 	unsigned char sPhase;
38061da177e4SLinus Torvalds 
380769eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
38081da177e4SLinus Torvalds 
380947b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
38101da177e4SLinus Torvalds 
38111da177e4SLinus Torvalds 	if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
38121da177e4SLinus Torvalds 	    (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
38131da177e4SLinus Torvalds 		return;
38141da177e4SLinus Torvalds 	}
38151da177e4SLinus Torvalds 
38165c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
38171da177e4SLinus Torvalds 
38181da177e4SLinus Torvalds 		currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
38191da177e4SLinus Torvalds 
38201da177e4SLinus Torvalds 		currSCCB->Sccb_XferCnt = 1;
38211da177e4SLinus Torvalds 
38221da177e4SLinus Torvalds 		currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3823c823feebSAlexey Dobriyan 		WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
38241da177e4SLinus Torvalds 		WR_HARPOON(port + hp_xferstat, 0x00);
38251da177e4SLinus Torvalds 	}
38261da177e4SLinus Torvalds 
38275c04a7b8SAlexey Dobriyan 	else {
38281da177e4SLinus Torvalds 
38291da177e4SLinus Torvalds 		currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
38301da177e4SLinus Torvalds 
38311da177e4SLinus Torvalds 		currSCCB->Sccb_XferCnt = 0;
38321da177e4SLinus Torvalds 	}
38331da177e4SLinus Torvalds 
38341da177e4SLinus Torvalds 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
38351da177e4SLinus Torvalds 	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
38361da177e4SLinus Torvalds 
38371da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PARITY_ERR;
38381da177e4SLinus Torvalds 		WRW_HARPOON((port + hp_intstat), PARITY);
38391da177e4SLinus Torvalds 	}
38401da177e4SLinus Torvalds 
384147b5d69cSJames Bottomley  	FPT_hostDataXferAbort(port, p_card, currSCCB);
38421da177e4SLinus Torvalds 
38435c04a7b8SAlexey Dobriyan 	while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
38445c04a7b8SAlexey Dobriyan 	}
38451da177e4SLinus Torvalds 
38461da177e4SLinus Torvalds 	TimeOutLoop = 0;
38471da177e4SLinus Torvalds 
38485c04a7b8SAlexey Dobriyan 	while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
38491da177e4SLinus Torvalds 		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
38501da177e4SLinus Torvalds 			return;
38511da177e4SLinus Torvalds 		}
3852db038cf8SAlexey Dobriyan 		if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
38531da177e4SLinus Torvalds 			break;
38541da177e4SLinus Torvalds 		}
38551da177e4SLinus Torvalds 		if (RDW_HARPOON((port + hp_intstat)) & RESET) {
38561da177e4SLinus Torvalds 			return;
38571da177e4SLinus Torvalds 		}
38585c04a7b8SAlexey Dobriyan 		if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
38595c04a7b8SAlexey Dobriyan 		    || (TimeOutLoop++ > 0x3000))
38601da177e4SLinus Torvalds 			break;
38611da177e4SLinus Torvalds 	}
38621da177e4SLinus Torvalds 
38631da177e4SLinus Torvalds 	sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
38641da177e4SLinus Torvalds 	if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3865db038cf8SAlexey Dobriyan 	    (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
38661da177e4SLinus Torvalds 	    (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
38675c04a7b8SAlexey Dobriyan 	    (sPhase == (SCSI_BSY | S_DATAI_PH))) {
38681da177e4SLinus Torvalds 
38691da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
38701da177e4SLinus Torvalds 
38715c04a7b8SAlexey Dobriyan 		if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
38721da177e4SLinus Torvalds 			if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
387347b5d69cSJames Bottomley  				FPT_phaseDataIn(port, p_card);
38741da177e4SLinus Torvalds 			}
38751da177e4SLinus Torvalds 
38761da177e4SLinus Torvalds 			else {
387747b5d69cSJames Bottomley  				FPT_phaseDataOut(port, p_card);
38781da177e4SLinus Torvalds 			}
38795c04a7b8SAlexey Dobriyan 		} else {
388047b5d69cSJames Bottomley  			FPT_sxfrp(port, p_card);
38811da177e4SLinus Torvalds 			if (!(RDW_HARPOON((port + hp_intstat)) &
38825c04a7b8SAlexey Dobriyan 			      (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
38831da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), AUTO_INT);
388447b5d69cSJames Bottomley  				FPT_phaseDecode(port, p_card);
38851da177e4SLinus Torvalds 			}
38861da177e4SLinus Torvalds 		}
38871da177e4SLinus Torvalds 
38881da177e4SLinus Torvalds 	}
38891da177e4SLinus Torvalds 
38901da177e4SLinus Torvalds 	else {
38911da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, 0x00);
38921da177e4SLinus Torvalds 	}
38931da177e4SLinus Torvalds }
38941da177e4SLinus Torvalds 
38951da177e4SLinus Torvalds /*---------------------------------------------------------------------
38961da177e4SLinus Torvalds  *
389747b5d69cSJames Bottomley   * Function: FPT_sinits
38981da177e4SLinus Torvalds  *
38991da177e4SLinus Torvalds  * Description: Setup SCCB manager fields in this SCCB.
39001da177e4SLinus Torvalds  *
39011da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
39021da177e4SLinus Torvalds 
390369eb2ea4SAlexey Dobriyan static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
39041da177e4SLinus Torvalds {
3905f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
39061da177e4SLinus Torvalds 
39075d7ebb9cSDan Carpenter 	if ((p_sccb->TargID >= MAX_SCSI_TAR) || (p_sccb->Lun >= MAX_LUN)) {
39081da177e4SLinus Torvalds 		return;
39091da177e4SLinus Torvalds 	}
391047b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
39111da177e4SLinus Torvalds 
39121da177e4SLinus Torvalds 	p_sccb->Sccb_XferState = 0x00;
39131da177e4SLinus Torvalds 	p_sccb->Sccb_XferCnt = p_sccb->DataLength;
39141da177e4SLinus Torvalds 
39151da177e4SLinus Torvalds 	if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
39161da177e4SLinus Torvalds 	    (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
39171da177e4SLinus Torvalds 
39181da177e4SLinus Torvalds 		p_sccb->Sccb_SGoffset = 0;
39191da177e4SLinus Torvalds 		p_sccb->Sccb_XferState = F_SG_XFER;
39201da177e4SLinus Torvalds 		p_sccb->Sccb_XferCnt = 0x00;
39211da177e4SLinus Torvalds 	}
39221da177e4SLinus Torvalds 
39231da177e4SLinus Torvalds 	if (p_sccb->DataLength == 0x00)
39241da177e4SLinus Torvalds 
39251da177e4SLinus Torvalds 		p_sccb->Sccb_XferState |= F_ALL_XFERRED;
39261da177e4SLinus Torvalds 
39275c04a7b8SAlexey Dobriyan 	if (p_sccb->ControlByte & F_USE_CMD_Q) {
39281da177e4SLinus Torvalds 		if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
39291da177e4SLinus Torvalds 			p_sccb->ControlByte &= ~F_USE_CMD_Q;
39301da177e4SLinus Torvalds 
39311da177e4SLinus Torvalds 		else
39321da177e4SLinus Torvalds 			currTar_Info->TarStatus |= TAG_Q_TRYING;
39331da177e4SLinus Torvalds 	}
39341da177e4SLinus Torvalds 
39351da177e4SLinus Torvalds /*      For !single SCSI device in system  & device allow Disconnect
39361da177e4SLinus Torvalds 	or command is tag_q type then send Cmd with Disconnect Enable
39371da177e4SLinus Torvalds 	else send Cmd with Disconnect Disable */
39381da177e4SLinus Torvalds 
39391da177e4SLinus Torvalds /*
394047b5d69cSJames Bottomley     if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
39411da177e4SLinus Torvalds       (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
39421da177e4SLinus Torvalds       (currTar_Info->TarStatus & TAG_Q_TRYING)) {
39431da177e4SLinus Torvalds */
39441da177e4SLinus Torvalds 	if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
39451da177e4SLinus Torvalds 	    (currTar_Info->TarStatus & TAG_Q_TRYING)) {
39465c04a7b8SAlexey Dobriyan 		p_sccb->Sccb_idmsg =
39475c04a7b8SAlexey Dobriyan 		    (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
39481da177e4SLinus Torvalds 	}
39491da177e4SLinus Torvalds 
39501da177e4SLinus Torvalds 	else {
39511da177e4SLinus Torvalds 
3952db038cf8SAlexey Dobriyan 		p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun;
39531da177e4SLinus Torvalds 	}
39541da177e4SLinus Torvalds 
39551da177e4SLinus Torvalds 	p_sccb->HostStatus = 0x00;
39561da177e4SLinus Torvalds 	p_sccb->TargetStatus = 0x00;
39571da177e4SLinus Torvalds 	p_sccb->Sccb_tag = 0x00;
39581da177e4SLinus Torvalds 	p_sccb->Sccb_MGRFlags = 0x00;
39591da177e4SLinus Torvalds 	p_sccb->Sccb_sgseg = 0x00;
39601da177e4SLinus Torvalds 	p_sccb->Sccb_ATC = 0x00;
39611da177e4SLinus Torvalds 	p_sccb->Sccb_savedATC = 0x00;
39621da177e4SLinus Torvalds /*
39631da177e4SLinus Torvalds    p_sccb->SccbVirtDataPtr    = 0x00;
39641da177e4SLinus Torvalds    p_sccb->Sccb_forwardlink   = NULL;
39651da177e4SLinus Torvalds    p_sccb->Sccb_backlink      = NULL;
39661da177e4SLinus Torvalds  */
39671da177e4SLinus Torvalds 	p_sccb->Sccb_scsistat = BUS_FREE_ST;
39681da177e4SLinus Torvalds 	p_sccb->SccbStatus = SCCB_IN_PROCESS;
39691da177e4SLinus Torvalds 	p_sccb->Sccb_scsimsg = SMNO_OP;
39701da177e4SLinus Torvalds 
39711da177e4SLinus Torvalds }
39721da177e4SLinus Torvalds 
39731da177e4SLinus Torvalds /*---------------------------------------------------------------------
39741da177e4SLinus Torvalds  *
39751da177e4SLinus Torvalds  * Function: Phase Decode
39761da177e4SLinus Torvalds  *
39771da177e4SLinus Torvalds  * Description: Determine the phase and call the appropriate function.
39781da177e4SLinus Torvalds  *
39791da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
39801da177e4SLinus Torvalds 
3981391e2f25SKhalid Aziz static void FPT_phaseDecode(u32 p_port, unsigned char p_card)
39821da177e4SLinus Torvalds {
39831da177e4SLinus Torvalds 	unsigned char phase_ref;
3984391e2f25SKhalid Aziz 	void (*phase) (u32, unsigned char);
39851da177e4SLinus Torvalds 
39861da177e4SLinus Torvalds 	DISABLE_AUTO(p_port);
39871da177e4SLinus Torvalds 
39885c04a7b8SAlexey Dobriyan 	phase_ref =
39895c04a7b8SAlexey Dobriyan 	    (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
39901da177e4SLinus Torvalds 
399147b5d69cSJames Bottomley  	phase = FPT_s_PhaseTbl[phase_ref];
39921da177e4SLinus Torvalds 
39931da177e4SLinus Torvalds 	(*phase) (p_port, p_card);	/* Call the correct phase func */
39941da177e4SLinus Torvalds }
39951da177e4SLinus Torvalds 
39961da177e4SLinus Torvalds /*---------------------------------------------------------------------
39971da177e4SLinus Torvalds  *
39981da177e4SLinus Torvalds  * Function: Data Out Phase
39991da177e4SLinus Torvalds  *
40001da177e4SLinus Torvalds  * Description: Start up both the BusMaster and Xbow.
40011da177e4SLinus Torvalds  *
40021da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
40031da177e4SLinus Torvalds 
4004391e2f25SKhalid Aziz static void FPT_phaseDataOut(u32 port, unsigned char p_card)
40051da177e4SLinus Torvalds {
40061da177e4SLinus Torvalds 
400769eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
40081da177e4SLinus Torvalds 
400947b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
40105c04a7b8SAlexey Dobriyan 	if (currSCCB == NULL) {
40111da177e4SLinus Torvalds 		return;		/* Exit if No SCCB record */
40121da177e4SLinus Torvalds 	}
40131da177e4SLinus Torvalds 
40141da177e4SLinus Torvalds 	currSCCB->Sccb_scsistat = DATA_OUT_ST;
40151da177e4SLinus Torvalds 	currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
40161da177e4SLinus Torvalds 
40171da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
40181da177e4SLinus Torvalds 
40191da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
40201da177e4SLinus Torvalds 
40211da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
40221da177e4SLinus Torvalds 
402347b5d69cSJames Bottomley  	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
40241da177e4SLinus Torvalds 
40251da177e4SLinus Torvalds 	if (currSCCB->Sccb_XferCnt == 0) {
40261da177e4SLinus Torvalds 
40271da177e4SLinus Torvalds 		if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
40281da177e4SLinus Torvalds 		    (currSCCB->HostStatus == SCCB_COMPLETE))
40291da177e4SLinus Torvalds 			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
40301da177e4SLinus Torvalds 
403147b5d69cSJames Bottomley  		FPT_sxfrp(port, p_card);
40321da177e4SLinus Torvalds 		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
403347b5d69cSJames Bottomley  			FPT_phaseDecode(port, p_card);
40341da177e4SLinus Torvalds 	}
40351da177e4SLinus Torvalds }
40361da177e4SLinus Torvalds 
40371da177e4SLinus Torvalds /*---------------------------------------------------------------------
40381da177e4SLinus Torvalds  *
40391da177e4SLinus Torvalds  * Function: Data In Phase
40401da177e4SLinus Torvalds  *
40411da177e4SLinus Torvalds  * Description: Startup the BusMaster and the XBOW.
40421da177e4SLinus Torvalds  *
40431da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
40441da177e4SLinus Torvalds 
4045391e2f25SKhalid Aziz static void FPT_phaseDataIn(u32 port, unsigned char p_card)
40461da177e4SLinus Torvalds {
40471da177e4SLinus Torvalds 
404869eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
40491da177e4SLinus Torvalds 
405047b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
40511da177e4SLinus Torvalds 
40525c04a7b8SAlexey Dobriyan 	if (currSCCB == NULL) {
40531da177e4SLinus Torvalds 		return;		/* Exit if No SCCB record */
40541da177e4SLinus Torvalds 	}
40551da177e4SLinus Torvalds 
40561da177e4SLinus Torvalds 	currSCCB->Sccb_scsistat = DATA_IN_ST;
40571da177e4SLinus Torvalds 	currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
40581da177e4SLinus Torvalds 	currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
40591da177e4SLinus Torvalds 
40601da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
40611da177e4SLinus Torvalds 
40621da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
40631da177e4SLinus Torvalds 
40641da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
40651da177e4SLinus Torvalds 
406647b5d69cSJames Bottomley  	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
40671da177e4SLinus Torvalds 
40681da177e4SLinus Torvalds 	if (currSCCB->Sccb_XferCnt == 0) {
40691da177e4SLinus Torvalds 
40701da177e4SLinus Torvalds 		if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
40711da177e4SLinus Torvalds 		    (currSCCB->HostStatus == SCCB_COMPLETE))
40721da177e4SLinus Torvalds 			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
40731da177e4SLinus Torvalds 
407447b5d69cSJames Bottomley  		FPT_sxfrp(port, p_card);
40751da177e4SLinus Torvalds 		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
407647b5d69cSJames Bottomley  			FPT_phaseDecode(port, p_card);
40771da177e4SLinus Torvalds 
40781da177e4SLinus Torvalds 	}
40791da177e4SLinus Torvalds }
40801da177e4SLinus Torvalds 
40811da177e4SLinus Torvalds /*---------------------------------------------------------------------
40821da177e4SLinus Torvalds  *
40831da177e4SLinus Torvalds  * Function: Command Phase
40841da177e4SLinus Torvalds  *
40851da177e4SLinus Torvalds  * Description: Load the CDB into the automation and start it up.
40861da177e4SLinus Torvalds  *
40871da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
40881da177e4SLinus Torvalds 
4089391e2f25SKhalid Aziz static void FPT_phaseCommand(u32 p_port, unsigned char p_card)
40901da177e4SLinus Torvalds {
409169eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
4092391e2f25SKhalid Aziz 	u32 cdb_reg;
4093db038cf8SAlexey Dobriyan 	unsigned char i;
40941da177e4SLinus Torvalds 
409547b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
40961da177e4SLinus Torvalds 
40971da177e4SLinus Torvalds 	if (currSCCB->OperationCode == RESET_COMMAND) {
40981da177e4SLinus Torvalds 
40991da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
41001da177e4SLinus Torvalds 		currSCCB->CdbLength = SIX_BYTE_CMD;
41011da177e4SLinus Torvalds 	}
41021da177e4SLinus Torvalds 
41031da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, 0x00);
41041da177e4SLinus Torvalds 
41051da177e4SLinus Torvalds 	ARAM_ACCESS(p_port);
41061da177e4SLinus Torvalds 
41071da177e4SLinus Torvalds 	cdb_reg = p_port + CMD_STRT;
41081da177e4SLinus Torvalds 
41091da177e4SLinus Torvalds 	for (i = 0; i < currSCCB->CdbLength; i++) {
41101da177e4SLinus Torvalds 
41111da177e4SLinus Torvalds 		if (currSCCB->OperationCode == RESET_COMMAND)
41121da177e4SLinus Torvalds 
41131da177e4SLinus Torvalds 			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
41141da177e4SLinus Torvalds 
41151da177e4SLinus Torvalds 		else
41165c04a7b8SAlexey Dobriyan 			WRW_HARPOON(cdb_reg,
41175c04a7b8SAlexey Dobriyan 				    (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
41181da177e4SLinus Torvalds 		cdb_reg += 2;
41191da177e4SLinus Torvalds 	}
41201da177e4SLinus Torvalds 
41211da177e4SLinus Torvalds 	if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
41221da177e4SLinus Torvalds 		WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
41231da177e4SLinus Torvalds 
41241da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
41251da177e4SLinus Torvalds 
41261da177e4SLinus Torvalds 	currSCCB->Sccb_scsistat = COMMAND_ST;
41271da177e4SLinus Torvalds 
41281da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
41291da177e4SLinus Torvalds 	SGRAM_ACCESS(p_port);
41301da177e4SLinus Torvalds }
41311da177e4SLinus Torvalds 
41321da177e4SLinus Torvalds /*---------------------------------------------------------------------
41331da177e4SLinus Torvalds  *
41341da177e4SLinus Torvalds  * Function: Status phase
41351da177e4SLinus Torvalds  *
41361da177e4SLinus Torvalds  * Description: Bring in the status and command complete message bytes
41371da177e4SLinus Torvalds  *
41381da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
41391da177e4SLinus Torvalds 
4140391e2f25SKhalid Aziz static void FPT_phaseStatus(u32 port, unsigned char p_card)
41411da177e4SLinus Torvalds {
41421da177e4SLinus Torvalds 	/* Start-up the automation to finish off this command and let the
41431da177e4SLinus Torvalds 	   isr handle the interrupt for command complete when it comes in.
41441da177e4SLinus Torvalds 	   We could wait here for the interrupt to be generated?
41451da177e4SLinus Torvalds 	 */
41461da177e4SLinus Torvalds 
41471da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, 0x00);
41481da177e4SLinus Torvalds 
41491da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
41501da177e4SLinus Torvalds }
41511da177e4SLinus Torvalds 
41521da177e4SLinus Torvalds /*---------------------------------------------------------------------
41531da177e4SLinus Torvalds  *
41541da177e4SLinus Torvalds  * Function: Phase Message Out
41551da177e4SLinus Torvalds  *
41561da177e4SLinus Torvalds  * Description: Send out our message (if we have one) and handle whatever
41571da177e4SLinus Torvalds  *              else is involed.
41581da177e4SLinus Torvalds  *
41591da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
41601da177e4SLinus Torvalds 
4161391e2f25SKhalid Aziz static void FPT_phaseMsgOut(u32 port, unsigned char p_card)
41621da177e4SLinus Torvalds {
4163db038cf8SAlexey Dobriyan 	unsigned char message, scsiID;
416469eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
4165f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
41661da177e4SLinus Torvalds 
416747b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
41681da177e4SLinus Torvalds 
41691da177e4SLinus Torvalds 	if (currSCCB != NULL) {
41701da177e4SLinus Torvalds 
41711da177e4SLinus Torvalds 		message = currSCCB->Sccb_scsimsg;
41721da177e4SLinus Torvalds 		scsiID = currSCCB->TargID;
41731da177e4SLinus Torvalds 
41745c04a7b8SAlexey Dobriyan 		if (message == SMDEV_RESET) {
41751da177e4SLinus Torvalds 
417647b5d69cSJames Bottomley  			currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
41771da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
417847b5d69cSJames Bottomley  			FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
41791da177e4SLinus Torvalds 
41805c04a7b8SAlexey Dobriyan 			if (FPT_sccbMgrTbl[p_card][scsiID].
41815c04a7b8SAlexey Dobriyan 			    TarEEValue & EE_SYNC_MASK) {
41821da177e4SLinus Torvalds 
41835c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
41845c04a7b8SAlexey Dobriyan 				    ~TAR_SYNC_MASK;
41851da177e4SLinus Torvalds 
41861da177e4SLinus Torvalds 			}
41871da177e4SLinus Torvalds 
41885c04a7b8SAlexey Dobriyan 			if (FPT_sccbMgrTbl[p_card][scsiID].
41895c04a7b8SAlexey Dobriyan 			    TarEEValue & EE_WIDE_SCSI) {
41901da177e4SLinus Torvalds 
41915c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
41925c04a7b8SAlexey Dobriyan 				    ~TAR_WIDE_MASK;
41931da177e4SLinus Torvalds 			}
41941da177e4SLinus Torvalds 
419547b5d69cSJames Bottomley  			FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
419647b5d69cSJames Bottomley  			FPT_SccbMgrTableInitTarget(p_card, scsiID);
41975c04a7b8SAlexey Dobriyan 		} else if (currSCCB->Sccb_scsistat == ABORT_ST) {
41981da177e4SLinus Torvalds 			currSCCB->HostStatus = SCCB_COMPLETE;
41995c04a7b8SAlexey Dobriyan 			if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
42005c04a7b8SAlexey Dobriyan 			    NULL) {
42015c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
42025c04a7b8SAlexey Dobriyan 							      Sccb_tag] = NULL;
420347b5d69cSJames Bottomley  				FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
42041da177e4SLinus Torvalds 			}
42051da177e4SLinus Torvalds 
42061da177e4SLinus Torvalds 		}
42071da177e4SLinus Torvalds 
42085c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
42091da177e4SLinus Torvalds 
42105c04a7b8SAlexey Dobriyan 			if (message == SMNO_OP) {
42111da177e4SLinus Torvalds 				currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
42121da177e4SLinus Torvalds 
421347b5d69cSJames Bottomley  				FPT_ssel(port, p_card);
42141da177e4SLinus Torvalds 				return;
42151da177e4SLinus Torvalds 			}
42165c04a7b8SAlexey Dobriyan 		} else {
42171da177e4SLinus Torvalds 
42181da177e4SLinus Torvalds 			if (message == SMABORT)
42191da177e4SLinus Torvalds 
422047b5d69cSJames Bottomley  				FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
42211da177e4SLinus Torvalds 		}
42221da177e4SLinus Torvalds 
42235c04a7b8SAlexey Dobriyan 	} else {
42241da177e4SLinus Torvalds 		message = SMABORT;
42251da177e4SLinus Torvalds 	}
42261da177e4SLinus Torvalds 
42271da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
42281da177e4SLinus Torvalds 
42291da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
42301da177e4SLinus Torvalds 
42311da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsidata_0, message);
42321da177e4SLinus Torvalds 
42331da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
42341da177e4SLinus Torvalds 
42351da177e4SLinus Torvalds 	ACCEPT_MSG(port);
42361da177e4SLinus Torvalds 
42371da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, 0x00);
42381da177e4SLinus Torvalds 
42391da177e4SLinus Torvalds 	if ((message == SMABORT) || (message == SMDEV_RESET) ||
42405c04a7b8SAlexey Dobriyan 	    (message == SMABORT_TAG)) {
42411da177e4SLinus Torvalds 
42425c04a7b8SAlexey Dobriyan 		while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
42435c04a7b8SAlexey Dobriyan 		}
42441da177e4SLinus Torvalds 
42455c04a7b8SAlexey Dobriyan 		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
42461da177e4SLinus Torvalds 			WRW_HARPOON((port + hp_intstat), BUS_FREE);
42471da177e4SLinus Torvalds 
42485c04a7b8SAlexey Dobriyan 			if (currSCCB != NULL) {
42491da177e4SLinus Torvalds 
42505c04a7b8SAlexey Dobriyan 				if ((FPT_BL_Card[p_card].
42515c04a7b8SAlexey Dobriyan 				     globalFlags & F_CONLUN_IO)
42525c04a7b8SAlexey Dobriyan 				    &&
42535c04a7b8SAlexey Dobriyan 				    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
42545c04a7b8SAlexey Dobriyan 				      TarStatus & TAR_TAG_Q_MASK) !=
42555c04a7b8SAlexey Dobriyan 				     TAG_Q_TRYING))
42565c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
42575c04a7b8SAlexey Dobriyan 							       TargID].
42585c04a7b8SAlexey Dobriyan 					    TarLUNBusy[currSCCB->Lun] = 0;
42591da177e4SLinus Torvalds 				else
42605c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
42615c04a7b8SAlexey Dobriyan 							       TargID].
42625c04a7b8SAlexey Dobriyan 					    TarLUNBusy[0] = 0;
42631da177e4SLinus Torvalds 
42645c04a7b8SAlexey Dobriyan 				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
42655c04a7b8SAlexey Dobriyan 						     currSCCB, p_card);
42661da177e4SLinus Torvalds 			}
42671da177e4SLinus Torvalds 
42685c04a7b8SAlexey Dobriyan 			else {
42695c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].globalFlags |=
42705c04a7b8SAlexey Dobriyan 				    F_NEW_SCCB_CMD;
42711da177e4SLinus Torvalds 			}
42721da177e4SLinus Torvalds 		}
42731da177e4SLinus Torvalds 
42745c04a7b8SAlexey Dobriyan 		else {
42751da177e4SLinus Torvalds 
427647b5d69cSJames Bottomley  			FPT_sxfrp(port, p_card);
42771da177e4SLinus Torvalds 		}
42781da177e4SLinus Torvalds 	}
42791da177e4SLinus Torvalds 
42805c04a7b8SAlexey Dobriyan 	else {
42811da177e4SLinus Torvalds 
42825c04a7b8SAlexey Dobriyan 		if (message == SMPARITY) {
42831da177e4SLinus Torvalds 			currSCCB->Sccb_scsimsg = SMNO_OP;
42845c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
42855c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
42865c04a7b8SAlexey Dobriyan 		} else {
428747b5d69cSJames Bottomley  			FPT_sxfrp(port, p_card);
42881da177e4SLinus Torvalds 		}
42891da177e4SLinus Torvalds 	}
42901da177e4SLinus Torvalds }
42911da177e4SLinus Torvalds 
42921da177e4SLinus Torvalds /*---------------------------------------------------------------------
42931da177e4SLinus Torvalds  *
42941da177e4SLinus Torvalds  * Function: Message In phase
42951da177e4SLinus Torvalds  *
42961da177e4SLinus Torvalds  * Description: Bring in the message and determine what to do with it.
42971da177e4SLinus Torvalds  *
42981da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
42991da177e4SLinus Torvalds 
4300391e2f25SKhalid Aziz static void FPT_phaseMsgIn(u32 port, unsigned char p_card)
43011da177e4SLinus Torvalds {
4302db038cf8SAlexey Dobriyan 	unsigned char message;
430369eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
43041da177e4SLinus Torvalds 
430547b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
43061da177e4SLinus Torvalds 
43075c04a7b8SAlexey Dobriyan 	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
43081da177e4SLinus Torvalds 
430947b5d69cSJames Bottomley  		FPT_phaseChkFifo(port, p_card);
43101da177e4SLinus Torvalds 	}
43111da177e4SLinus Torvalds 
43121da177e4SLinus Torvalds 	message = RD_HARPOON(port + hp_scsidata_0);
43135c04a7b8SAlexey Dobriyan 	if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) {
43141da177e4SLinus Torvalds 
43155c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
43165c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + END_DATA_START));
43171da177e4SLinus Torvalds 
43181da177e4SLinus Torvalds 	}
43191da177e4SLinus Torvalds 
43205c04a7b8SAlexey Dobriyan 	else {
43211da177e4SLinus Torvalds 
432247b5d69cSJames Bottomley  		message = FPT_sfm(port, currSCCB);
43235c04a7b8SAlexey Dobriyan 		if (message) {
43241da177e4SLinus Torvalds 
432547b5d69cSJames Bottomley  			FPT_sdecm(message, port, p_card);
43261da177e4SLinus Torvalds 
43275c04a7b8SAlexey Dobriyan 		} else {
43281da177e4SLinus Torvalds 			if (currSCCB->Sccb_scsimsg != SMPARITY)
43291da177e4SLinus Torvalds 				ACCEPT_MSG(port);
43305c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
43315c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
43321da177e4SLinus Torvalds 		}
43331da177e4SLinus Torvalds 	}
43341da177e4SLinus Torvalds 
43351da177e4SLinus Torvalds }
43361da177e4SLinus Torvalds 
43371da177e4SLinus Torvalds /*---------------------------------------------------------------------
43381da177e4SLinus Torvalds  *
43391da177e4SLinus Torvalds  * Function: Illegal phase
43401da177e4SLinus Torvalds  *
43411da177e4SLinus Torvalds  * Description: Target switched to some illegal phase, so all we can do
43421da177e4SLinus Torvalds  *              is report an error back to the host (if that is possible)
43431da177e4SLinus Torvalds  *              and send an ABORT message to the misbehaving target.
43441da177e4SLinus Torvalds  *
43451da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
43461da177e4SLinus Torvalds 
4347391e2f25SKhalid Aziz static void FPT_phaseIllegal(u32 port, unsigned char p_card)
43481da177e4SLinus Torvalds {
434969eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
43501da177e4SLinus Torvalds 
435147b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
43521da177e4SLinus Torvalds 
43531da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
43541da177e4SLinus Torvalds 	if (currSCCB != NULL) {
43551da177e4SLinus Torvalds 
43561da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
43571da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = ABORT_ST;
43581da177e4SLinus Torvalds 		currSCCB->Sccb_scsimsg = SMABORT;
43591da177e4SLinus Torvalds 	}
43601da177e4SLinus Torvalds 
43611da177e4SLinus Torvalds 	ACCEPT_MSG_ATN(port);
43621da177e4SLinus Torvalds }
43631da177e4SLinus Torvalds 
43641da177e4SLinus Torvalds /*---------------------------------------------------------------------
43651da177e4SLinus Torvalds  *
43661da177e4SLinus Torvalds  * Function: Phase Check FIFO
43671da177e4SLinus Torvalds  *
43681da177e4SLinus Torvalds  * Description: Make sure data has been flushed from both FIFOs and abort
43691da177e4SLinus Torvalds  *              the operations if necessary.
43701da177e4SLinus Torvalds  *
43711da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
43721da177e4SLinus Torvalds 
4373391e2f25SKhalid Aziz static void FPT_phaseChkFifo(u32 port, unsigned char p_card)
43741da177e4SLinus Torvalds {
4375391e2f25SKhalid Aziz 	u32 xfercnt;
437669eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
43771da177e4SLinus Torvalds 
437847b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
43791da177e4SLinus Torvalds 
43805c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
43811da177e4SLinus Torvalds 
43821da177e4SLinus Torvalds 		while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
43835c04a7b8SAlexey Dobriyan 		       (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
43845c04a7b8SAlexey Dobriyan 		}
43851da177e4SLinus Torvalds 
43865c04a7b8SAlexey Dobriyan 		if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
43871da177e4SLinus Torvalds 			currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
43881da177e4SLinus Torvalds 
43891da177e4SLinus Torvalds 			currSCCB->Sccb_XferCnt = 0;
43901da177e4SLinus Torvalds 
43911da177e4SLinus Torvalds 			if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
43925c04a7b8SAlexey Dobriyan 			    (currSCCB->HostStatus == SCCB_COMPLETE)) {
43931da177e4SLinus Torvalds 				currSCCB->HostStatus = SCCB_PARITY_ERR;
43941da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PARITY);
43951da177e4SLinus Torvalds 			}
43961da177e4SLinus Torvalds 
439747b5d69cSJames Bottomley  			FPT_hostDataXferAbort(port, p_card, currSCCB);
43981da177e4SLinus Torvalds 
439947b5d69cSJames Bottomley  			FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
44001da177e4SLinus Torvalds 
44015c04a7b8SAlexey Dobriyan 			while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
44025c04a7b8SAlexey Dobriyan 			       && (RD_HARPOON(port + hp_ext_status) &
44035c04a7b8SAlexey Dobriyan 				   BM_CMD_BUSY)) {
44045c04a7b8SAlexey Dobriyan 			}
44051da177e4SLinus Torvalds 
44061da177e4SLinus Torvalds 		}
44075c04a7b8SAlexey Dobriyan 	}
44081da177e4SLinus Torvalds 
44095c04a7b8SAlexey Dobriyan 	/*End Data In specific code. */
44101da177e4SLinus Torvalds 	GET_XFER_CNT(port, xfercnt);
44111da177e4SLinus Torvalds 
44121da177e4SLinus Torvalds 	WR_HARPOON(port + hp_xfercnt_0, 0x00);
44131da177e4SLinus Torvalds 
44141da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, 0x00);
44151da177e4SLinus Torvalds 
44161da177e4SLinus Torvalds 	currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
44171da177e4SLinus Torvalds 
44181da177e4SLinus Torvalds 	currSCCB->Sccb_XferCnt = xfercnt;
44191da177e4SLinus Torvalds 
44201da177e4SLinus Torvalds 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
44211da177e4SLinus Torvalds 	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
44221da177e4SLinus Torvalds 
44231da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PARITY_ERR;
44241da177e4SLinus Torvalds 		WRW_HARPOON((port + hp_intstat), PARITY);
44251da177e4SLinus Torvalds 	}
44261da177e4SLinus Torvalds 
442747b5d69cSJames Bottomley  	FPT_hostDataXferAbort(port, p_card, currSCCB);
44281da177e4SLinus Torvalds 
44291da177e4SLinus Torvalds 	WR_HARPOON(port + hp_fifowrite, 0x00);
44301da177e4SLinus Torvalds 	WR_HARPOON(port + hp_fiforead, 0x00);
44311da177e4SLinus Torvalds 	WR_HARPOON(port + hp_xferstat, 0x00);
44321da177e4SLinus Torvalds 
44331da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
44341da177e4SLinus Torvalds }
44351da177e4SLinus Torvalds 
44361da177e4SLinus Torvalds /*---------------------------------------------------------------------
44371da177e4SLinus Torvalds  *
44381da177e4SLinus Torvalds  * Function: Phase Bus Free
44391da177e4SLinus Torvalds  *
44401da177e4SLinus Torvalds  * Description: We just went bus free so figure out if it was
44411da177e4SLinus Torvalds  *              because of command complete or from a disconnect.
44421da177e4SLinus Torvalds  *
44431da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
4444391e2f25SKhalid Aziz static void FPT_phaseBusFree(u32 port, unsigned char p_card)
44451da177e4SLinus Torvalds {
444669eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
44471da177e4SLinus Torvalds 
444847b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
44491da177e4SLinus Torvalds 
44505c04a7b8SAlexey Dobriyan 	if (currSCCB != NULL) {
44511da177e4SLinus Torvalds 
44521da177e4SLinus Torvalds 		DISABLE_AUTO(port);
44531da177e4SLinus Torvalds 
44545c04a7b8SAlexey Dobriyan 		if (currSCCB->OperationCode == RESET_COMMAND) {
44551da177e4SLinus Torvalds 
445647b5d69cSJames Bottomley  			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
44575c04a7b8SAlexey Dobriyan 			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44585c04a7b8SAlexey Dobriyan 			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
44595c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44605c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 0;
44611da177e4SLinus Torvalds 			else
44625c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44635c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 0;
44641da177e4SLinus Torvalds 
44655c04a7b8SAlexey Dobriyan 			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
44665c04a7b8SAlexey Dobriyan 					     p_card);
44671da177e4SLinus Torvalds 
446847b5d69cSJames Bottomley  			FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
44691da177e4SLinus Torvalds 
44701da177e4SLinus Torvalds 		}
44711da177e4SLinus Torvalds 
44725c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
447347b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4474db038cf8SAlexey Dobriyan 			    (unsigned char)SYNC_SUPPORTED;
44755c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
44765c04a7b8SAlexey Dobriyan 			    ~EE_SYNC_MASK;
44771da177e4SLinus Torvalds 		}
44781da177e4SLinus Torvalds 
44795c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
448047b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
448147b5d69cSJames Bottomley  			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44821da177e4SLinus Torvalds 			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
44831da177e4SLinus Torvalds 
44845c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
44855c04a7b8SAlexey Dobriyan 			    ~EE_WIDE_SCSI;
44861da177e4SLinus Torvalds 		}
44871da177e4SLinus Torvalds 
44885c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
44891da177e4SLinus Torvalds 			/* Make sure this is not a phony BUS_FREE.  If we were
44901da177e4SLinus Torvalds 			   reselected or if BUSY is NOT on then this is a
44911da177e4SLinus Torvalds 			   valid BUS FREE.  SRR Wednesday, 5/10/1995.     */
44921da177e4SLinus Torvalds 
44931da177e4SLinus Torvalds 			if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
44945c04a7b8SAlexey Dobriyan 			    (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
44955c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44965c04a7b8SAlexey Dobriyan 				    TarStatus &= ~TAR_TAG_Q_MASK;
44975c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44985c04a7b8SAlexey Dobriyan 				    TarStatus |= TAG_Q_REJECT;
44991da177e4SLinus Torvalds 			}
45001da177e4SLinus Torvalds 
45015c04a7b8SAlexey Dobriyan 			else {
45021da177e4SLinus Torvalds 				return;
45031da177e4SLinus Torvalds 			}
45041da177e4SLinus Torvalds 		}
45051da177e4SLinus Torvalds 
45065c04a7b8SAlexey Dobriyan 		else {
45071da177e4SLinus Torvalds 
45081da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
45091da177e4SLinus Torvalds 
45105c04a7b8SAlexey Dobriyan 			if (!currSCCB->HostStatus) {
45111da177e4SLinus Torvalds 				currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
45121da177e4SLinus Torvalds 			}
45131da177e4SLinus Torvalds 
451447b5d69cSJames Bottomley  			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
45155c04a7b8SAlexey Dobriyan 			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
45165c04a7b8SAlexey Dobriyan 			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
45175c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
45185c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 0;
45191da177e4SLinus Torvalds 			else
45205c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
45215c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 0;
45221da177e4SLinus Torvalds 
45235c04a7b8SAlexey Dobriyan 			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
45245c04a7b8SAlexey Dobriyan 					     p_card);
45251da177e4SLinus Torvalds 			return;
45261da177e4SLinus Torvalds 		}
45271da177e4SLinus Torvalds 
452847b5d69cSJames Bottomley  		FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
45291da177e4SLinus Torvalds 
45301da177e4SLinus Torvalds 	}			/*end if !=null */
45311da177e4SLinus Torvalds }
45321da177e4SLinus Torvalds 
45331da177e4SLinus Torvalds /*---------------------------------------------------------------------
45341da177e4SLinus Torvalds  *
45351da177e4SLinus Torvalds  * Function: Auto Load Default Map
45361da177e4SLinus Torvalds  *
45371da177e4SLinus Torvalds  * Description: Load the Automation RAM with the defualt map values.
45381da177e4SLinus Torvalds  *
45391da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
4540391e2f25SKhalid Aziz static void FPT_autoLoadDefaultMap(u32 p_port)
45411da177e4SLinus Torvalds {
4542391e2f25SKhalid Aziz 	u32 map_addr;
45431da177e4SLinus Torvalds 
45441da177e4SLinus Torvalds 	ARAM_ACCESS(p_port);
45451da177e4SLinus Torvalds 	map_addr = p_port + hp_aramBase;
45461da177e4SLinus Torvalds 
45471da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0));	/*ID MESSAGE */
45481da177e4SLinus Torvalds 	map_addr += 2;
45491da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20));	/*SIMPLE TAG QUEUEING MSG */
45501da177e4SLinus Torvalds 	map_addr += 2;
45511da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, RAT_OP);	/*RESET ATTENTION */
45521da177e4SLinus Torvalds 	map_addr += 2;
45531da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00));	/*TAG ID MSG */
45541da177e4SLinus Torvalds 	map_addr += 2;
45551da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 0 */
45561da177e4SLinus Torvalds 	map_addr += 2;
45571da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 1 */
45581da177e4SLinus Torvalds 	map_addr += 2;
45591da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 2 */
45601da177e4SLinus Torvalds 	map_addr += 2;
45611da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 3 */
45621da177e4SLinus Torvalds 	map_addr += 2;
45631da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 4 */
45641da177e4SLinus Torvalds 	map_addr += 2;
45651da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 5 */
45661da177e4SLinus Torvalds 	map_addr += 2;
45671da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 6 */
45681da177e4SLinus Torvalds 	map_addr += 2;
45691da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 7 */
45701da177e4SLinus Torvalds 	map_addr += 2;
45711da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 8 */
45721da177e4SLinus Torvalds 	map_addr += 2;
45731da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 9 */
45741da177e4SLinus Torvalds 	map_addr += 2;
45751da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 10 */
45761da177e4SLinus Torvalds 	map_addr += 2;
45771da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 11 */
45781da177e4SLinus Torvalds 	map_addr += 2;
45791da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT));	/*JUMP IF DATA OUT */
45801da177e4SLinus Torvalds 	map_addr += 2;
45811da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI));	/*JUMP IF NO DATA IN FIFO */
45821da177e4SLinus Torvalds 	map_addr += 2;		/*This means AYNC DATA IN */
45831da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT));	/*STOP AND INTERRUPT */
45841da177e4SLinus Torvalds 	map_addr += 2;
45851da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT));	/*JUMP IF NOT DATA IN PHZ */
45861da177e4SLinus Torvalds 	map_addr += 2;
45871da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK 4 DATA IN */
45881da177e4SLinus Torvalds 	map_addr += 2;
45891da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02));	/*SAVE DATA PTR MSG? */
45901da177e4SLinus Torvalds 	map_addr += 2;
45911da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC));	/*GO CHECK FOR DISCONNECT MSG */
45921da177e4SLinus Torvalds 	map_addr += 2;
45931da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1));	/*SAVE DATA PTRS MSG */
45941da177e4SLinus Torvalds 	map_addr += 2;
45951da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK DATA IN */
45961da177e4SLinus Torvalds 	map_addr += 2;
45971da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04));	/*DISCONNECT MSG? */
45981da177e4SLinus Torvalds 	map_addr += 2;
45991da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN));	/*UKNKNOWN MSG */
46001da177e4SLinus Torvalds 	map_addr += 2;
46011da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*XFER DISCONNECT MSG */
46021da177e4SLinus Torvalds 	map_addr += 2;
46031da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC));	/*STOP AND INTERRUPT */
46041da177e4SLinus Torvalds 	map_addr += 2;
46051da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN));	/*JUMP IF NOT STATUS PHZ. */
46061da177e4SLinus Torvalds 	map_addr += 2;
46071da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0));	/*GET STATUS BYTE */
46081da177e4SLinus Torvalds 	map_addr += 2;
46091da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC));	/*ERROR IF NOT MSG IN PHZ */
46101da177e4SLinus Torvalds 	map_addr += 2;
46111da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00));	/*CHECK FOR CMD COMPLETE MSG. */
46121da177e4SLinus Torvalds 	map_addr += 2;
46131da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC));	/*ERROR IF NOT CMD COMPLETE MSG. */
46141da177e4SLinus Torvalds 	map_addr += 2;
46151da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*GET CMD COMPLETE MSG */
46161da177e4SLinus Torvalds 	map_addr += 2;
46171da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP));	/*END OF COMMAND */
46181da177e4SLinus Torvalds 	map_addr += 2;
46191da177e4SLinus Torvalds 
46201da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN));	/*RECEIVED UNKNOWN MSG BYTE */
46211da177e4SLinus Torvalds 	map_addr += 2;
46221da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
46231da177e4SLinus Torvalds 	map_addr += 2;
46241da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE));	/*BIOS Tickled the Mgr */
46251da177e4SLinus Torvalds 	map_addr += 2;
46261da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL));	/*EXPECTED ID/TAG MESSAGES AND */
46271da177e4SLinus Torvalds 	map_addr += 2;		/* DIDN'T GET ONE */
46281da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG));	/* comp SCSI SEL ID & AR3 */
46291da177e4SLinus Torvalds 	map_addr += 2;
46301da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00));	/*SEL ID OK then Conti. */
46311da177e4SLinus Torvalds 	map_addr += 2;
46321da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
46331da177e4SLinus Torvalds 
46341da177e4SLinus Torvalds 	SGRAM_ACCESS(p_port);
46351da177e4SLinus Torvalds }
46361da177e4SLinus Torvalds 
46371da177e4SLinus Torvalds /*---------------------------------------------------------------------
46381da177e4SLinus Torvalds  *
46391da177e4SLinus Torvalds  * Function: Auto Command Complete
46401da177e4SLinus Torvalds  *
46411da177e4SLinus Torvalds  * Description: Post command back to host and find another command
46421da177e4SLinus Torvalds  *              to execute.
46431da177e4SLinus Torvalds  *
46441da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
46451da177e4SLinus Torvalds 
4646391e2f25SKhalid Aziz static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card)
46471da177e4SLinus Torvalds {
464869eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
4649db038cf8SAlexey Dobriyan 	unsigned char status_byte;
46501da177e4SLinus Torvalds 
465147b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
46521da177e4SLinus Torvalds 
46531da177e4SLinus Torvalds 	status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
46541da177e4SLinus Torvalds 
465547b5d69cSJames Bottomley  	FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
46561da177e4SLinus Torvalds 
46571da177e4SLinus Torvalds 	if (status_byte != SSGOOD) {
46581da177e4SLinus Torvalds 
46591da177e4SLinus Torvalds 		if (status_byte == SSQ_FULL) {
46601da177e4SLinus Torvalds 
466147b5d69cSJames Bottomley  			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
46625c04a7b8SAlexey Dobriyan 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46635c04a7b8SAlexey Dobriyan 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
46645c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46655c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 1;
466647b5d69cSJames Bottomley  				if (FPT_BL_Card[p_card].discQCount != 0)
466747b5d69cSJames Bottomley  					FPT_BL_Card[p_card].discQCount--;
46685c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].
46695c04a7b8SAlexey Dobriyan 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
46705c04a7b8SAlexey Dobriyan 					      [currSCCB->TargID].
46715c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[currSCCB->Lun]] =
46725c04a7b8SAlexey Dobriyan 				    NULL;
46735c04a7b8SAlexey Dobriyan 			} else {
46745c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46755c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 1;
46765c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_tag) {
467747b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
46785c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
46795c04a7b8SAlexey Dobriyan 						    discQCount--;
46805c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
46815c04a7b8SAlexey Dobriyan 								      Sccb_tag]
46825c04a7b8SAlexey Dobriyan 					    = NULL;
46835c04a7b8SAlexey Dobriyan 				} else {
468447b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
46855c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
46865c04a7b8SAlexey Dobriyan 						    discQCount--;
46875c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].
46885c04a7b8SAlexey Dobriyan 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
46895c04a7b8SAlexey Dobriyan 						      [currSCCB->TargID].
46905c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = NULL;
46911da177e4SLinus Torvalds 				}
46921da177e4SLinus Torvalds 			}
46931da177e4SLinus Torvalds 
46941da177e4SLinus Torvalds 			currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
46951da177e4SLinus Torvalds 
469647b5d69cSJames Bottomley  			FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
46971da177e4SLinus Torvalds 
46981da177e4SLinus Torvalds 			return;
46991da177e4SLinus Torvalds 		}
47001da177e4SLinus Torvalds 
47015c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
470247b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4703db038cf8SAlexey Dobriyan 			    (unsigned char)SYNC_SUPPORTED;
47041da177e4SLinus Torvalds 
47055c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
47065c04a7b8SAlexey Dobriyan 			    ~EE_SYNC_MASK;
470747b5d69cSJames Bottomley  			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
47081da177e4SLinus Torvalds 
470947b5d69cSJames Bottomley  			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
47105c04a7b8SAlexey Dobriyan 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47115c04a7b8SAlexey Dobriyan 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
47125c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47135c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 1;
471447b5d69cSJames Bottomley  				if (FPT_BL_Card[p_card].discQCount != 0)
471547b5d69cSJames Bottomley  					FPT_BL_Card[p_card].discQCount--;
47165c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].
47175c04a7b8SAlexey Dobriyan 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
47185c04a7b8SAlexey Dobriyan 					      [currSCCB->TargID].
47195c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[currSCCB->Lun]] =
47205c04a7b8SAlexey Dobriyan 				    NULL;
47215c04a7b8SAlexey Dobriyan 			} else {
47225c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47235c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 1;
47245c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_tag) {
472547b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47265c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
47275c04a7b8SAlexey Dobriyan 						    discQCount--;
47285c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
47295c04a7b8SAlexey Dobriyan 								      Sccb_tag]
47305c04a7b8SAlexey Dobriyan 					    = NULL;
47315c04a7b8SAlexey Dobriyan 				} else {
473247b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47335c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
47345c04a7b8SAlexey Dobriyan 						    discQCount--;
47355c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].
47365c04a7b8SAlexey Dobriyan 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
47375c04a7b8SAlexey Dobriyan 						      [currSCCB->TargID].
47385c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = NULL;
47391da177e4SLinus Torvalds 				}
47401da177e4SLinus Torvalds 			}
47411da177e4SLinus Torvalds 			return;
47421da177e4SLinus Torvalds 
47431da177e4SLinus Torvalds 		}
47441da177e4SLinus Torvalds 
47455c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
47461da177e4SLinus Torvalds 
474747b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
474847b5d69cSJames Bottomley  			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47491da177e4SLinus Torvalds 			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
47501da177e4SLinus Torvalds 
47515c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
47525c04a7b8SAlexey Dobriyan 			    ~EE_WIDE_SCSI;
475347b5d69cSJames Bottomley  			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
47541da177e4SLinus Torvalds 
475547b5d69cSJames Bottomley  			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
47565c04a7b8SAlexey Dobriyan 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47575c04a7b8SAlexey Dobriyan 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
47585c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47595c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 1;
476047b5d69cSJames Bottomley  				if (FPT_BL_Card[p_card].discQCount != 0)
476147b5d69cSJames Bottomley  					FPT_BL_Card[p_card].discQCount--;
47625c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].
47635c04a7b8SAlexey Dobriyan 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
47645c04a7b8SAlexey Dobriyan 					      [currSCCB->TargID].
47655c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[currSCCB->Lun]] =
47665c04a7b8SAlexey Dobriyan 				    NULL;
47675c04a7b8SAlexey Dobriyan 			} else {
47685c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47695c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 1;
47705c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_tag) {
477147b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47725c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
47735c04a7b8SAlexey Dobriyan 						    discQCount--;
47745c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
47755c04a7b8SAlexey Dobriyan 								      Sccb_tag]
47765c04a7b8SAlexey Dobriyan 					    = NULL;
47775c04a7b8SAlexey Dobriyan 				} else {
477847b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47795c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
47805c04a7b8SAlexey Dobriyan 						    discQCount--;
47815c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].
47825c04a7b8SAlexey Dobriyan 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
47835c04a7b8SAlexey Dobriyan 						      [currSCCB->TargID].
47845c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = NULL;
47851da177e4SLinus Torvalds 				}
47861da177e4SLinus Torvalds 			}
47871da177e4SLinus Torvalds 			return;
47881da177e4SLinus Torvalds 
47891da177e4SLinus Torvalds 		}
47901da177e4SLinus Torvalds 
47915c04a7b8SAlexey Dobriyan 		if (status_byte == SSCHECK) {
47925c04a7b8SAlexey Dobriyan 			if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
47935c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47945c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_SYNC_MASK) {
47955c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
47965c04a7b8SAlexey Dobriyan 							       TargID].
47975c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_SYNC_MASK;
47981da177e4SLinus Torvalds 				}
47995c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
48005c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_WIDE_SCSI) {
48015c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
48025c04a7b8SAlexey Dobriyan 							       TargID].
48035c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_WIDE_MASK;
48041da177e4SLinus Torvalds 				}
48051da177e4SLinus Torvalds 			}
48061da177e4SLinus Torvalds 		}
48071da177e4SLinus Torvalds 
48081da177e4SLinus Torvalds 		if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
48091da177e4SLinus Torvalds 
48101da177e4SLinus Torvalds 			currSCCB->SccbStatus = SCCB_ERROR;
48111da177e4SLinus Torvalds 			currSCCB->TargetStatus = status_byte;
48121da177e4SLinus Torvalds 
48131da177e4SLinus Torvalds 			if (status_byte == SSCHECK) {
48141da177e4SLinus Torvalds 
48155c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
48165c04a7b8SAlexey Dobriyan 				    TarLUN_CA = 1;
48171da177e4SLinus Torvalds 
48185c04a7b8SAlexey Dobriyan 				if (currSCCB->RequestSenseLength !=
48195c04a7b8SAlexey Dobriyan 				    NO_AUTO_REQUEST_SENSE) {
48201da177e4SLinus Torvalds 
48211da177e4SLinus Torvalds 					if (currSCCB->RequestSenseLength == 0)
48225c04a7b8SAlexey Dobriyan 						currSCCB->RequestSenseLength =
48235c04a7b8SAlexey Dobriyan 						    14;
48241da177e4SLinus Torvalds 
482547b5d69cSJames Bottomley  					FPT_ssenss(&FPT_BL_Card[p_card]);
48265c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].globalFlags |=
48275c04a7b8SAlexey Dobriyan 					    F_NEW_SCCB_CMD;
48281da177e4SLinus Torvalds 
48295c04a7b8SAlexey Dobriyan 					if (((FPT_BL_Card[p_card].
48305c04a7b8SAlexey Dobriyan 					      globalFlags & F_CONLUN_IO)
48315c04a7b8SAlexey Dobriyan 					     &&
48325c04a7b8SAlexey Dobriyan 					     ((FPT_sccbMgrTbl[p_card]
48335c04a7b8SAlexey Dobriyan 					       [currSCCB->TargID].
48345c04a7b8SAlexey Dobriyan 					       TarStatus & TAR_TAG_Q_MASK) !=
48355c04a7b8SAlexey Dobriyan 					      TAG_Q_TRYING))) {
48365c04a7b8SAlexey Dobriyan 						FPT_sccbMgrTbl[p_card]
48375c04a7b8SAlexey Dobriyan 						    [currSCCB->TargID].
48385c04a7b8SAlexey Dobriyan 						    TarLUNBusy[currSCCB->Lun] =
48395c04a7b8SAlexey Dobriyan 						    1;
48405c04a7b8SAlexey Dobriyan 						if (FPT_BL_Card[p_card].
48415c04a7b8SAlexey Dobriyan 						    discQCount != 0)
48425c04a7b8SAlexey Dobriyan 							FPT_BL_Card[p_card].
48435c04a7b8SAlexey Dobriyan 							    discQCount--;
48445c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
48455c04a7b8SAlexey Dobriyan 						    discQ_Tbl[FPT_sccbMgrTbl
48465c04a7b8SAlexey Dobriyan 							      [p_card]
48475c04a7b8SAlexey Dobriyan 							      [currSCCB->
48485c04a7b8SAlexey Dobriyan 							       TargID].
48495c04a7b8SAlexey Dobriyan 							      LunDiscQ_Idx
48505c04a7b8SAlexey Dobriyan 							      [currSCCB->Lun]] =
48515c04a7b8SAlexey Dobriyan 						    NULL;
48525c04a7b8SAlexey Dobriyan 					} else {
48535c04a7b8SAlexey Dobriyan 						FPT_sccbMgrTbl[p_card]
48545c04a7b8SAlexey Dobriyan 						    [currSCCB->TargID].
48555c04a7b8SAlexey Dobriyan 						    TarLUNBusy[0] = 1;
48565c04a7b8SAlexey Dobriyan 						if (currSCCB->Sccb_tag) {
48575c04a7b8SAlexey Dobriyan 							if (FPT_BL_Card[p_card].
48585c04a7b8SAlexey Dobriyan 							    discQCount != 0)
48595c04a7b8SAlexey Dobriyan 								FPT_BL_Card
48605c04a7b8SAlexey Dobriyan 								    [p_card].
48615c04a7b8SAlexey Dobriyan 								    discQCount--;
48625c04a7b8SAlexey Dobriyan 							FPT_BL_Card[p_card].
48635c04a7b8SAlexey Dobriyan 							    discQ_Tbl[currSCCB->
48645c04a7b8SAlexey Dobriyan 								      Sccb_tag]
48655c04a7b8SAlexey Dobriyan 							    = NULL;
48665c04a7b8SAlexey Dobriyan 						} else {
48675c04a7b8SAlexey Dobriyan 							if (FPT_BL_Card[p_card].
48685c04a7b8SAlexey Dobriyan 							    discQCount != 0)
48695c04a7b8SAlexey Dobriyan 								FPT_BL_Card
48705c04a7b8SAlexey Dobriyan 								    [p_card].
48715c04a7b8SAlexey Dobriyan 								    discQCount--;
48725c04a7b8SAlexey Dobriyan 							FPT_BL_Card[p_card].
48735c04a7b8SAlexey Dobriyan 							    discQ_Tbl
48745c04a7b8SAlexey Dobriyan 							    [FPT_sccbMgrTbl
48755c04a7b8SAlexey Dobriyan 							     [p_card][currSCCB->
48765c04a7b8SAlexey Dobriyan 								      TargID].
48775c04a7b8SAlexey Dobriyan 							     LunDiscQ_Idx[0]] =
48785c04a7b8SAlexey Dobriyan 							    NULL;
48791da177e4SLinus Torvalds 						}
48801da177e4SLinus Torvalds 					}
48811da177e4SLinus Torvalds 					return;
48821da177e4SLinus Torvalds 				}
48831da177e4SLinus Torvalds 			}
488447b5d69cSJames Bottomley  		}
488547b5d69cSJames Bottomley  	}
488647b5d69cSJames Bottomley  
488747b5d69cSJames Bottomley  	if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
48885c04a7b8SAlexey Dobriyan 	    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
48895c04a7b8SAlexey Dobriyan 	      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
48905c04a7b8SAlexey Dobriyan 		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
48915c04a7b8SAlexey Dobriyan 								    Lun] = 0;
48921da177e4SLinus Torvalds 	else
489347b5d69cSJames Bottomley  		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
489447b5d69cSJames Bottomley  
489547b5d69cSJames Bottomley  	FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
48961da177e4SLinus Torvalds }
48971da177e4SLinus Torvalds 
48981da177e4SLinus Torvalds #define SHORT_WAIT   0x0000000F
48991da177e4SLinus Torvalds #define LONG_WAIT    0x0000FFFFL
49001da177e4SLinus Torvalds 
49011da177e4SLinus Torvalds /*---------------------------------------------------------------------
49021da177e4SLinus Torvalds  *
49031da177e4SLinus Torvalds  * Function: Data Transfer Processor
49041da177e4SLinus Torvalds  *
49051da177e4SLinus Torvalds  * Description: This routine performs two tasks.
49061da177e4SLinus Torvalds  *              (1) Start data transfer by calling HOST_DATA_XFER_START
49071da177e4SLinus Torvalds  *              function.  Once data transfer is started, (2) Depends
49081da177e4SLinus Torvalds  *              on the type of data transfer mode Scatter/Gather mode
49091da177e4SLinus Torvalds  *              or NON Scatter/Gather mode.  In NON Scatter/Gather mode,
49101da177e4SLinus Torvalds  *              this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
49111da177e4SLinus Torvalds  *              data transfer done.  In Scatter/Gather mode, this routine
49121da177e4SLinus Torvalds  *              checks bus master command complete and dual rank busy
49131da177e4SLinus Torvalds  *              bit to keep chaining SC transfer command.  Similarly,
49141da177e4SLinus Torvalds  *              in Scatter/Gather mode, it checks Sccb_MGRFlag
49151da177e4SLinus Torvalds  *              (F_HOST_XFER_ACT bit) for data transfer done.
49161da177e4SLinus Torvalds  *
49171da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
49181da177e4SLinus Torvalds 
4919391e2f25SKhalid Aziz static void FPT_dataXferProcessor(u32 port, struct sccb_card *pCurrCard)
49201da177e4SLinus Torvalds {
492169eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
49221da177e4SLinus Torvalds 
49231da177e4SLinus Torvalds 	currSCCB = pCurrCard->currentSCCB;
49241da177e4SLinus Torvalds 
49255c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_XferState & F_SG_XFER) {
49261da177e4SLinus Torvalds 		if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
49271da177e4SLinus Torvalds 		{
4928db038cf8SAlexey Dobriyan 			currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
49291da177e4SLinus Torvalds 			currSCCB->Sccb_SGoffset = 0x00;
49301da177e4SLinus Torvalds 		}
49311da177e4SLinus Torvalds 		pCurrCard->globalFlags |= F_HOST_XFER_ACT;
49321da177e4SLinus Torvalds 
493347b5d69cSJames Bottomley  		FPT_busMstrSGDataXferStart(port, currSCCB);
49341da177e4SLinus Torvalds 	}
49351da177e4SLinus Torvalds 
49365c04a7b8SAlexey Dobriyan 	else {
49375c04a7b8SAlexey Dobriyan 		if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
49381da177e4SLinus Torvalds 			pCurrCard->globalFlags |= F_HOST_XFER_ACT;
49391da177e4SLinus Torvalds 
494047b5d69cSJames Bottomley  			FPT_busMstrDataXferStart(port, currSCCB);
49411da177e4SLinus Torvalds 		}
49421da177e4SLinus Torvalds 	}
49431da177e4SLinus Torvalds }
49441da177e4SLinus Torvalds 
49451da177e4SLinus Torvalds /*---------------------------------------------------------------------
49461da177e4SLinus Torvalds  *
49471da177e4SLinus Torvalds  * Function: BusMaster Scatter Gather Data Transfer Start
49481da177e4SLinus Torvalds  *
49491da177e4SLinus Torvalds  * Description:
49501da177e4SLinus Torvalds  *
49511da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
4952391e2f25SKhalid Aziz static void FPT_busMstrSGDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
49531da177e4SLinus Torvalds {
4954391e2f25SKhalid Aziz 	u32 count, addr, tmpSGCnt;
4955ce793215SAlexey Dobriyan 	unsigned int sg_index;
4956db038cf8SAlexey Dobriyan 	unsigned char sg_count, i;
4957391e2f25SKhalid Aziz 	u32 reg_offset;
4958391e2f25SKhalid Aziz 	struct blogic_sg_seg *segp;
49591da177e4SLinus Torvalds 
4960391e2f25SKhalid Aziz 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)
4961391e2f25SKhalid Aziz 		count = ((u32)HOST_RD_CMD) << 24;
4962391e2f25SKhalid Aziz 	else
4963391e2f25SKhalid Aziz 		count = ((u32)HOST_WRT_CMD) << 24;
49641da177e4SLinus Torvalds 
49651da177e4SLinus Torvalds 	sg_count = 0;
49661da177e4SLinus Torvalds 	tmpSGCnt = 0;
49671da177e4SLinus Torvalds 	sg_index = pcurrSCCB->Sccb_sgseg;
49681da177e4SLinus Torvalds 	reg_offset = hp_aramBase;
49691da177e4SLinus Torvalds 
49705c04a7b8SAlexey Dobriyan 	i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
49715c04a7b8SAlexey Dobriyan 			    ~(SGRAM_ARAM | SCATTER_EN));
49721da177e4SLinus Torvalds 
49731da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl, i);
49741da177e4SLinus Torvalds 
4975db038cf8SAlexey Dobriyan 	while ((sg_count < (unsigned char)SG_BUF_CNT) &&
4976391e2f25SKhalid Aziz 			((sg_index * (unsigned int)SG_ELEMENT_SIZE) <
49775c04a7b8SAlexey Dobriyan 			pcurrSCCB->DataLength)) {
49781da177e4SLinus Torvalds 
4979391e2f25SKhalid Aziz 		segp = (struct blogic_sg_seg *)(pcurrSCCB->DataPointer) +
4980391e2f25SKhalid Aziz 				sg_index;
4981391e2f25SKhalid Aziz 		tmpSGCnt += segp->segbytes;
4982391e2f25SKhalid Aziz 		count |= segp->segbytes;
4983391e2f25SKhalid Aziz 		addr = segp->segdata;
49841da177e4SLinus Torvalds 
49851da177e4SLinus Torvalds 		if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
49865c04a7b8SAlexey Dobriyan 			addr +=
49875c04a7b8SAlexey Dobriyan 			    ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
49885c04a7b8SAlexey Dobriyan 			count =
49895c04a7b8SAlexey Dobriyan 			    (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
49901da177e4SLinus Torvalds 			tmpSGCnt = count & 0x00FFFFFFL;
49911da177e4SLinus Torvalds 		}
49921da177e4SLinus Torvalds 
49931da177e4SLinus Torvalds 		WR_HARP32(p_port, reg_offset, addr);
49941da177e4SLinus Torvalds 		reg_offset += 4;
49951da177e4SLinus Torvalds 
49961da177e4SLinus Torvalds 		WR_HARP32(p_port, reg_offset, count);
49971da177e4SLinus Torvalds 		reg_offset += 4;
49981da177e4SLinus Torvalds 
49991da177e4SLinus Torvalds 		count &= 0xFF000000L;
50001da177e4SLinus Torvalds 		sg_index++;
50011da177e4SLinus Torvalds 		sg_count++;
50021da177e4SLinus Torvalds 
50031da177e4SLinus Torvalds 	}			/*End While */
50041da177e4SLinus Torvalds 
50051da177e4SLinus Torvalds 	pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
50061da177e4SLinus Torvalds 
50071da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
50081da177e4SLinus Torvalds 
50091da177e4SLinus Torvalds 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
50101da177e4SLinus Torvalds 
50111da177e4SLinus Torvalds 		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
50121da177e4SLinus Torvalds 
50135c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
50145c04a7b8SAlexey Dobriyan 			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
50151da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
50161da177e4SLinus Torvalds 	}
50171da177e4SLinus Torvalds 
50181da177e4SLinus Torvalds 	else {
50191da177e4SLinus Torvalds 
50201da177e4SLinus Torvalds 		if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
50215c04a7b8SAlexey Dobriyan 		    (tmpSGCnt & 0x000000001)) {
50221da177e4SLinus Torvalds 
50231da177e4SLinus Torvalds 			pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
50241da177e4SLinus Torvalds 			tmpSGCnt--;
50251da177e4SLinus Torvalds 		}
50261da177e4SLinus Torvalds 
50271da177e4SLinus Torvalds 		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
50281da177e4SLinus Torvalds 
50295c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
50305c04a7b8SAlexey Dobriyan 			   (SCSI_PORT | DMA_PORT | DMA_RD));
50311da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
50321da177e4SLinus Torvalds 	}
50331da177e4SLinus Torvalds 
5034db038cf8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
50351da177e4SLinus Torvalds 
50361da177e4SLinus Torvalds }
50371da177e4SLinus Torvalds 
50381da177e4SLinus Torvalds /*---------------------------------------------------------------------
50391da177e4SLinus Torvalds  *
50401da177e4SLinus Torvalds  * Function: BusMaster Data Transfer Start
50411da177e4SLinus Torvalds  *
50421da177e4SLinus Torvalds  * Description:
50431da177e4SLinus Torvalds  *
50441da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
5045391e2f25SKhalid Aziz static void FPT_busMstrDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
50461da177e4SLinus Torvalds {
5047391e2f25SKhalid Aziz 	u32 addr, count;
50481da177e4SLinus Torvalds 
50491da177e4SLinus Torvalds 	if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
50501da177e4SLinus Torvalds 
50511da177e4SLinus Torvalds 		count = pcurrSCCB->Sccb_XferCnt;
50521da177e4SLinus Torvalds 
5053391e2f25SKhalid Aziz 		addr = (u32)(unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
50541da177e4SLinus Torvalds 	}
50551da177e4SLinus Torvalds 
50561da177e4SLinus Torvalds 	else {
50571da177e4SLinus Torvalds 		addr = pcurrSCCB->SensePointer;
50581da177e4SLinus Torvalds 		count = pcurrSCCB->RequestSenseLength;
50591da177e4SLinus Torvalds 
50601da177e4SLinus Torvalds 	}
50611da177e4SLinus Torvalds 
50621da177e4SLinus Torvalds 	HP_SETUP_ADDR_CNT(p_port, addr, count);
50631da177e4SLinus Torvalds 
50641da177e4SLinus Torvalds 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
50651da177e4SLinus Torvalds 
50665c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
50675c04a7b8SAlexey Dobriyan 			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
50681da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
50691da177e4SLinus Torvalds 
50701da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_xfer_cmd,
50711da177e4SLinus Torvalds 			   (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
50721da177e4SLinus Torvalds 	}
50731da177e4SLinus Torvalds 
50741da177e4SLinus Torvalds 	else {
50751da177e4SLinus Torvalds 
50765c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
50775c04a7b8SAlexey Dobriyan 			   (SCSI_PORT | DMA_PORT | DMA_RD));
50781da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
50791da177e4SLinus Torvalds 
50801da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_xfer_cmd,
50811da177e4SLinus Torvalds 			   (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
50821da177e4SLinus Torvalds 
50831da177e4SLinus Torvalds 	}
50841da177e4SLinus Torvalds }
50851da177e4SLinus Torvalds 
50861da177e4SLinus Torvalds /*---------------------------------------------------------------------
50871da177e4SLinus Torvalds  *
50881da177e4SLinus Torvalds  * Function: BusMaster Timeout Handler
50891da177e4SLinus Torvalds  *
50901da177e4SLinus Torvalds  * Description: This function is called after a bus master command busy time
50911da177e4SLinus Torvalds  *               out is detected.  This routines issue halt state machine
50921da177e4SLinus Torvalds  *               with a software time out for command busy.  If command busy
50931da177e4SLinus Torvalds  *               is still asserted at the end of the time out, it issues
50941da177e4SLinus Torvalds  *               hard abort with another software time out.  It hard abort
50951da177e4SLinus Torvalds  *               command busy is also time out, it'll just give up.
50961da177e4SLinus Torvalds  *
50971da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
5098391e2f25SKhalid Aziz static unsigned char FPT_busMstrTimeOut(u32 p_port)
50991da177e4SLinus Torvalds {
5100d63a4cccSAlexey Dobriyan 	unsigned long timeout;
51011da177e4SLinus Torvalds 
51021da177e4SLinus Torvalds 	timeout = LONG_WAIT;
51031da177e4SLinus Torvalds 
51041da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
51051da177e4SLinus Torvalds 
51065c04a7b8SAlexey Dobriyan 	while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
51075c04a7b8SAlexey Dobriyan 	       && timeout--) {
51085c04a7b8SAlexey Dobriyan 	}
51091da177e4SLinus Torvalds 
51101da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
51111da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
51121da177e4SLinus Torvalds 
51131da177e4SLinus Torvalds 		timeout = LONG_WAIT;
51145c04a7b8SAlexey Dobriyan 		while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
51155c04a7b8SAlexey Dobriyan 		       && timeout--) {
51165c04a7b8SAlexey Dobriyan 		}
51171da177e4SLinus Torvalds 	}
51181da177e4SLinus Torvalds 
51191da177e4SLinus Torvalds 	RD_HARPOON(p_port + hp_int_status);	/*Clear command complete */
51201da177e4SLinus Torvalds 
51211da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
51225c1b85e2SAlexey Dobriyan 		return 1;
51231da177e4SLinus Torvalds 	}
51241da177e4SLinus Torvalds 
51251da177e4SLinus Torvalds 	else {
51265c1b85e2SAlexey Dobriyan 		return 0;
51271da177e4SLinus Torvalds 	}
51281da177e4SLinus Torvalds }
51291da177e4SLinus Torvalds 
51301da177e4SLinus Torvalds /*---------------------------------------------------------------------
51311da177e4SLinus Torvalds  *
51321da177e4SLinus Torvalds  * Function: Host Data Transfer Abort
51331da177e4SLinus Torvalds  *
51341da177e4SLinus Torvalds  * Description: Abort any in progress transfer.
51351da177e4SLinus Torvalds  *
51361da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
5137391e2f25SKhalid Aziz static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
51385c04a7b8SAlexey Dobriyan 				  struct sccb *pCurrSCCB)
51391da177e4SLinus Torvalds {
51401da177e4SLinus Torvalds 
5141d63a4cccSAlexey Dobriyan 	unsigned long timeout;
5142d63a4cccSAlexey Dobriyan 	unsigned long remain_cnt;
5143391e2f25SKhalid Aziz 	u32 sg_ptr;
5144391e2f25SKhalid Aziz 	struct blogic_sg_seg *segp;
51451da177e4SLinus Torvalds 
514647b5d69cSJames Bottomley  	FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
51471da177e4SLinus Torvalds 
51481da177e4SLinus Torvalds 	if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
51491da177e4SLinus Torvalds 
51501da177e4SLinus Torvalds 		if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
51511da177e4SLinus Torvalds 
51525c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_bm_ctrl,
51535c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_bm_ctrl) |
51545c04a7b8SAlexey Dobriyan 				    FLUSH_XFER_CNTR));
51551da177e4SLinus Torvalds 			timeout = LONG_WAIT;
51561da177e4SLinus Torvalds 
51575c04a7b8SAlexey Dobriyan 			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
51585c04a7b8SAlexey Dobriyan 			       && timeout--) {
51595c04a7b8SAlexey Dobriyan 			}
51601da177e4SLinus Torvalds 
51615c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_bm_ctrl,
51625c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_bm_ctrl) &
51635c04a7b8SAlexey Dobriyan 				    ~FLUSH_XFER_CNTR));
51641da177e4SLinus Torvalds 
51651da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
51661da177e4SLinus Torvalds 
516747b5d69cSJames Bottomley  				if (FPT_busMstrTimeOut(port)) {
51681da177e4SLinus Torvalds 
51691da177e4SLinus Torvalds 					if (pCurrSCCB->HostStatus == 0x00)
51701da177e4SLinus Torvalds 
51715c04a7b8SAlexey Dobriyan 						pCurrSCCB->HostStatus =
51725c04a7b8SAlexey Dobriyan 						    SCCB_BM_ERR;
51731da177e4SLinus Torvalds 
51741da177e4SLinus Torvalds 				}
51751da177e4SLinus Torvalds 
51765c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_int_status) &
51775c04a7b8SAlexey Dobriyan 				    INT_EXT_STATUS)
51781da177e4SLinus Torvalds 
51795c04a7b8SAlexey Dobriyan 					if (RD_HARPOON(port + hp_ext_status) &
51805c04a7b8SAlexey Dobriyan 					    BAD_EXT_STATUS)
51811da177e4SLinus Torvalds 
51825c04a7b8SAlexey Dobriyan 						if (pCurrSCCB->HostStatus ==
51835c04a7b8SAlexey Dobriyan 						    0x00)
51841da177e4SLinus Torvalds 						{
51855c04a7b8SAlexey Dobriyan 							pCurrSCCB->HostStatus =
51865c04a7b8SAlexey Dobriyan 							    SCCB_BM_ERR;
51871da177e4SLinus Torvalds 						}
51881da177e4SLinus Torvalds 			}
51891da177e4SLinus Torvalds 		}
51901da177e4SLinus Torvalds 	}
51911da177e4SLinus Torvalds 
51921da177e4SLinus Torvalds 	else if (pCurrSCCB->Sccb_XferCnt) {
51931da177e4SLinus Torvalds 
51941da177e4SLinus Torvalds 		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
51951da177e4SLinus Torvalds 
51965c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_page_ctrl,
51975c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_page_ctrl) &
51981da177e4SLinus Torvalds 				    ~SCATTER_EN));
51991da177e4SLinus Torvalds 
52001da177e4SLinus Torvalds 			WR_HARPOON(port + hp_sg_addr, 0x00);
52011da177e4SLinus Torvalds 
52021da177e4SLinus Torvalds 			sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
52031da177e4SLinus Torvalds 
52045c04a7b8SAlexey Dobriyan 			if (sg_ptr >
52055c04a7b8SAlexey Dobriyan 			    (unsigned int)(pCurrSCCB->DataLength /
52065c04a7b8SAlexey Dobriyan 					   SG_ELEMENT_SIZE)) {
52071da177e4SLinus Torvalds 
5208391e2f25SKhalid Aziz 				sg_ptr = (u32)(pCurrSCCB->DataLength /
52095c04a7b8SAlexey Dobriyan 							SG_ELEMENT_SIZE);
52101da177e4SLinus Torvalds 			}
52111da177e4SLinus Torvalds 
52121da177e4SLinus Torvalds 			remain_cnt = pCurrSCCB->Sccb_XferCnt;
52131da177e4SLinus Torvalds 
52141da177e4SLinus Torvalds 			while (remain_cnt < 0x01000000L) {
52151da177e4SLinus Torvalds 
52161da177e4SLinus Torvalds 				sg_ptr--;
5217391e2f25SKhalid Aziz 				segp = (struct blogic_sg_seg *)(pCurrSCCB->
5218391e2f25SKhalid Aziz 						DataPointer) + (sg_ptr * 2);
5219391e2f25SKhalid Aziz 				if (remain_cnt > (unsigned long)segp->segbytes)
52205c04a7b8SAlexey Dobriyan 					remain_cnt -=
5221391e2f25SKhalid Aziz 						(unsigned long)segp->segbytes;
5222391e2f25SKhalid Aziz 				else
52231da177e4SLinus Torvalds 					break;
52241da177e4SLinus Torvalds 			}
52251da177e4SLinus Torvalds 
52261da177e4SLinus Torvalds 			if (remain_cnt < 0x01000000L) {
52271da177e4SLinus Torvalds 
52281da177e4SLinus Torvalds 				pCurrSCCB->Sccb_SGoffset = remain_cnt;
52291da177e4SLinus Torvalds 
5230c823feebSAlexey Dobriyan 				pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
52311da177e4SLinus Torvalds 
52325c04a7b8SAlexey Dobriyan 				if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
52335c04a7b8SAlexey Dobriyan 				    pCurrSCCB->DataLength && (remain_cnt == 0))
52341da177e4SLinus Torvalds 
52355c04a7b8SAlexey Dobriyan 					pCurrSCCB->Sccb_XferState |=
52365c04a7b8SAlexey Dobriyan 					    F_ALL_XFERRED;
52371da177e4SLinus Torvalds 			}
52381da177e4SLinus Torvalds 
52391da177e4SLinus Torvalds 			else {
52401da177e4SLinus Torvalds 
52411da177e4SLinus Torvalds 				if (pCurrSCCB->HostStatus == 0x00) {
52421da177e4SLinus Torvalds 
52435c04a7b8SAlexey Dobriyan 					pCurrSCCB->HostStatus =
52445c04a7b8SAlexey Dobriyan 					    SCCB_GROSS_FW_ERR;
52451da177e4SLinus Torvalds 				}
52461da177e4SLinus Torvalds 			}
52471da177e4SLinus Torvalds 		}
52481da177e4SLinus Torvalds 
52491da177e4SLinus Torvalds 		if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
52501da177e4SLinus Torvalds 
52511da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
52521da177e4SLinus Torvalds 
525347b5d69cSJames Bottomley  				FPT_busMstrTimeOut(port);
52541da177e4SLinus Torvalds 			}
52551da177e4SLinus Torvalds 
52561da177e4SLinus Torvalds 			else {
52571da177e4SLinus Torvalds 
52585c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_int_status) &
52595c04a7b8SAlexey Dobriyan 				    INT_EXT_STATUS) {
52601da177e4SLinus Torvalds 
52615c04a7b8SAlexey Dobriyan 					if (RD_HARPOON(port + hp_ext_status) &
52625c04a7b8SAlexey Dobriyan 					    BAD_EXT_STATUS) {
52631da177e4SLinus Torvalds 
52645c04a7b8SAlexey Dobriyan 						if (pCurrSCCB->HostStatus ==
52655c04a7b8SAlexey Dobriyan 						    0x00) {
52661da177e4SLinus Torvalds 
52675c04a7b8SAlexey Dobriyan 							pCurrSCCB->HostStatus =
52685c04a7b8SAlexey Dobriyan 							    SCCB_BM_ERR;
52691da177e4SLinus Torvalds 						}
52701da177e4SLinus Torvalds 					}
52711da177e4SLinus Torvalds 				}
52721da177e4SLinus Torvalds 
52731da177e4SLinus Torvalds 			}
52741da177e4SLinus Torvalds 		}
52751da177e4SLinus Torvalds 
52761da177e4SLinus Torvalds 		else {
52771da177e4SLinus Torvalds 
52781da177e4SLinus Torvalds 			if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
52791da177e4SLinus Torvalds 
52801da177e4SLinus Torvalds 				timeout = SHORT_WAIT;
52811da177e4SLinus Torvalds 
52825c04a7b8SAlexey Dobriyan 				while ((RD_HARPOON(port + hp_ext_status) &
52835c04a7b8SAlexey Dobriyan 					BM_CMD_BUSY)
52845c04a7b8SAlexey Dobriyan 				       && ((RD_HARPOON(port + hp_fifo_cnt)) >=
52855c04a7b8SAlexey Dobriyan 					   BM_THRESHOLD) && timeout--) {
52865c04a7b8SAlexey Dobriyan 				}
52871da177e4SLinus Torvalds 			}
52881da177e4SLinus Torvalds 
52891da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
52901da177e4SLinus Torvalds 
52915c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_bm_ctrl,
52925c04a7b8SAlexey Dobriyan 					   (RD_HARPOON(port + hp_bm_ctrl) |
52931da177e4SLinus Torvalds 					    FLUSH_XFER_CNTR));
52941da177e4SLinus Torvalds 
52951da177e4SLinus Torvalds 				timeout = LONG_WAIT;
52961da177e4SLinus Torvalds 
52975c04a7b8SAlexey Dobriyan 				while ((RD_HARPOON(port + hp_ext_status) &
52985c04a7b8SAlexey Dobriyan 					BM_CMD_BUSY) && timeout--) {
52995c04a7b8SAlexey Dobriyan 				}
53001da177e4SLinus Torvalds 
53015c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_bm_ctrl,
53025c04a7b8SAlexey Dobriyan 					   (RD_HARPOON(port + hp_bm_ctrl) &
53031da177e4SLinus Torvalds 					    ~FLUSH_XFER_CNTR));
53041da177e4SLinus Torvalds 
53055c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_ext_status) &
53065c04a7b8SAlexey Dobriyan 				    BM_CMD_BUSY) {
53071da177e4SLinus Torvalds 
53081da177e4SLinus Torvalds 					if (pCurrSCCB->HostStatus == 0x00) {
53091da177e4SLinus Torvalds 
53105c04a7b8SAlexey Dobriyan 						pCurrSCCB->HostStatus =
53115c04a7b8SAlexey Dobriyan 						    SCCB_BM_ERR;
53121da177e4SLinus Torvalds 					}
53131da177e4SLinus Torvalds 
531447b5d69cSJames Bottomley  					FPT_busMstrTimeOut(port);
53151da177e4SLinus Torvalds 				}
53161da177e4SLinus Torvalds 			}
53171da177e4SLinus Torvalds 
53181da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
53191da177e4SLinus Torvalds 
53205c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_ext_status) &
53215c04a7b8SAlexey Dobriyan 				    BAD_EXT_STATUS) {
53221da177e4SLinus Torvalds 
53231da177e4SLinus Torvalds 					if (pCurrSCCB->HostStatus == 0x00) {
53241da177e4SLinus Torvalds 
53255c04a7b8SAlexey Dobriyan 						pCurrSCCB->HostStatus =
53265c04a7b8SAlexey Dobriyan 						    SCCB_BM_ERR;
53271da177e4SLinus Torvalds 					}
53281da177e4SLinus Torvalds 				}
53291da177e4SLinus Torvalds 			}
53301da177e4SLinus Torvalds 		}
53311da177e4SLinus Torvalds 
53321da177e4SLinus Torvalds 	}
53331da177e4SLinus Torvalds 
53341da177e4SLinus Torvalds 	else {
53351da177e4SLinus Torvalds 
53361da177e4SLinus Torvalds 		if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
53371da177e4SLinus Torvalds 
53381da177e4SLinus Torvalds 			timeout = LONG_WAIT;
53391da177e4SLinus Torvalds 
53405c04a7b8SAlexey Dobriyan 			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
53415c04a7b8SAlexey Dobriyan 			       && timeout--) {
53425c04a7b8SAlexey Dobriyan 			}
53431da177e4SLinus Torvalds 
53441da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
53451da177e4SLinus Torvalds 
53461da177e4SLinus Torvalds 				if (pCurrSCCB->HostStatus == 0x00) {
53471da177e4SLinus Torvalds 
53481da177e4SLinus Torvalds 					pCurrSCCB->HostStatus = SCCB_BM_ERR;
53491da177e4SLinus Torvalds 				}
53501da177e4SLinus Torvalds 
535147b5d69cSJames Bottomley  				FPT_busMstrTimeOut(port);
53521da177e4SLinus Torvalds 			}
53531da177e4SLinus Torvalds 		}
53541da177e4SLinus Torvalds 
53551da177e4SLinus Torvalds 		if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
53561da177e4SLinus Torvalds 
53571da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
53581da177e4SLinus Torvalds 
53591da177e4SLinus Torvalds 				if (pCurrSCCB->HostStatus == 0x00) {
53601da177e4SLinus Torvalds 
53611da177e4SLinus Torvalds 					pCurrSCCB->HostStatus = SCCB_BM_ERR;
53621da177e4SLinus Torvalds 				}
53631da177e4SLinus Torvalds 			}
53641da177e4SLinus Torvalds 
53651da177e4SLinus Torvalds 		}
53661da177e4SLinus Torvalds 
53671da177e4SLinus Torvalds 		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
53681da177e4SLinus Torvalds 
53695c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_page_ctrl,
53705c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_page_ctrl) &
53711da177e4SLinus Torvalds 				    ~SCATTER_EN));
53721da177e4SLinus Torvalds 
53731da177e4SLinus Torvalds 			WR_HARPOON(port + hp_sg_addr, 0x00);
53741da177e4SLinus Torvalds 
53751da177e4SLinus Torvalds 			pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
53761da177e4SLinus Torvalds 
53771da177e4SLinus Torvalds 			pCurrSCCB->Sccb_SGoffset = 0x00;
53781da177e4SLinus Torvalds 
5379391e2f25SKhalid Aziz 			if ((u32)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >=
53801da177e4SLinus Torvalds 					pCurrSCCB->DataLength) {
53811da177e4SLinus Torvalds 
53821da177e4SLinus Torvalds 				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
53835c04a7b8SAlexey Dobriyan 				pCurrSCCB->Sccb_sgseg =
53845c04a7b8SAlexey Dobriyan 				    (unsigned short)(pCurrSCCB->DataLength /
53855c04a7b8SAlexey Dobriyan 						     SG_ELEMENT_SIZE);
53861da177e4SLinus Torvalds 			}
53871da177e4SLinus Torvalds 		}
53881da177e4SLinus Torvalds 
53891da177e4SLinus Torvalds 		else {
53901da177e4SLinus Torvalds 			if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
53911da177e4SLinus Torvalds 				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
53921da177e4SLinus Torvalds 		}
53931da177e4SLinus Torvalds 	}
53941da177e4SLinus Torvalds 
53951da177e4SLinus Torvalds 	WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
53961da177e4SLinus Torvalds }
53971da177e4SLinus Torvalds 
53981da177e4SLinus Torvalds /*---------------------------------------------------------------------
53991da177e4SLinus Torvalds  *
54001da177e4SLinus Torvalds  * Function: Host Data Transfer Restart
54011da177e4SLinus Torvalds  *
54021da177e4SLinus Torvalds  * Description: Reset the available count due to a restore data
54031da177e4SLinus Torvalds  *              pointers message.
54041da177e4SLinus Torvalds  *
54051da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
540669eb2ea4SAlexey Dobriyan static void FPT_hostDataXferRestart(struct sccb *currSCCB)
54071da177e4SLinus Torvalds {
5408d63a4cccSAlexey Dobriyan 	unsigned long data_count;
5409ce793215SAlexey Dobriyan 	unsigned int sg_index;
5410391e2f25SKhalid Aziz 	struct blogic_sg_seg *segp;
54111da177e4SLinus Torvalds 
54121da177e4SLinus Torvalds 	if (currSCCB->Sccb_XferState & F_SG_XFER) {
54131da177e4SLinus Torvalds 
54141da177e4SLinus Torvalds 		currSCCB->Sccb_XferCnt = 0;
54151da177e4SLinus Torvalds 
54161da177e4SLinus Torvalds 		sg_index = 0xffff;	/*Index by long words into sg list. */
54171da177e4SLinus Torvalds 		data_count = 0;		/*Running count of SG xfer counts. */
54181da177e4SLinus Torvalds 
54191da177e4SLinus Torvalds 
54201da177e4SLinus Torvalds 		while (data_count < currSCCB->Sccb_ATC) {
54211da177e4SLinus Torvalds 
54221da177e4SLinus Torvalds 			sg_index++;
5423391e2f25SKhalid Aziz 			segp = (struct blogic_sg_seg *)(currSCCB->DataPointer) +
5424391e2f25SKhalid Aziz 						(sg_index * 2);
5425391e2f25SKhalid Aziz 			data_count += segp->segbytes;
54261da177e4SLinus Torvalds 		}
54271da177e4SLinus Torvalds 
54281da177e4SLinus Torvalds 		if (data_count == currSCCB->Sccb_ATC) {
54291da177e4SLinus Torvalds 
54301da177e4SLinus Torvalds 			currSCCB->Sccb_SGoffset = 0;
54311da177e4SLinus Torvalds 			sg_index++;
54321da177e4SLinus Torvalds 		}
54331da177e4SLinus Torvalds 
54341da177e4SLinus Torvalds 		else {
54355c04a7b8SAlexey Dobriyan 			currSCCB->Sccb_SGoffset =
54365c04a7b8SAlexey Dobriyan 			    data_count - currSCCB->Sccb_ATC;
54371da177e4SLinus Torvalds 		}
54381da177e4SLinus Torvalds 
5439c823feebSAlexey Dobriyan 		currSCCB->Sccb_sgseg = (unsigned short)sg_index;
54401da177e4SLinus Torvalds 	}
54411da177e4SLinus Torvalds 
54421da177e4SLinus Torvalds 	else {
54435c04a7b8SAlexey Dobriyan 		currSCCB->Sccb_XferCnt =
54445c04a7b8SAlexey Dobriyan 		    currSCCB->DataLength - currSCCB->Sccb_ATC;
54451da177e4SLinus Torvalds 	}
54461da177e4SLinus Torvalds }
54471da177e4SLinus Torvalds 
54481da177e4SLinus Torvalds /*---------------------------------------------------------------------
54491da177e4SLinus Torvalds  *
545047b5d69cSJames Bottomley   * Function: FPT_scini
54511da177e4SLinus Torvalds  *
54521da177e4SLinus Torvalds  * Description: Setup all data structures necessary for SCAM selection.
54531da177e4SLinus Torvalds  *
54541da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
54551da177e4SLinus Torvalds 
54565c04a7b8SAlexey Dobriyan static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
54575c04a7b8SAlexey Dobriyan 		      unsigned char p_power_up)
54581da177e4SLinus Torvalds {
54591da177e4SLinus Torvalds 
5460db038cf8SAlexey Dobriyan 	unsigned char loser, assigned_id;
5461391e2f25SKhalid Aziz 	u32 p_port;
54621da177e4SLinus Torvalds 
5463db038cf8SAlexey Dobriyan 	unsigned char i, k, ScamFlg;
546413e6851aSAlexey Dobriyan 	struct sccb_card *currCard;
546568d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
54661da177e4SLinus Torvalds 
546747b5d69cSJames Bottomley  	currCard = &FPT_BL_Card[p_card];
54681da177e4SLinus Torvalds 	p_port = currCard->ioPort;
54691da177e4SLinus Torvalds 	pCurrNvRam = currCard->pNvRamInfo;
54701da177e4SLinus Torvalds 
54711da177e4SLinus Torvalds 	if (pCurrNvRam) {
54721da177e4SLinus Torvalds 		ScamFlg = pCurrNvRam->niScamConf;
54731da177e4SLinus Torvalds 		i = pCurrNvRam->niSysConf;
54745c04a7b8SAlexey Dobriyan 	} else {
54755c04a7b8SAlexey Dobriyan 		ScamFlg =
54765c04a7b8SAlexey Dobriyan 		    (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
54775c04a7b8SAlexey Dobriyan 		i = (unsigned
54785c04a7b8SAlexey Dobriyan 		     char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
54791da177e4SLinus Torvalds 	}
54801da177e4SLinus Torvalds 	if (!(i & 0x02))	/* check if reset bus in AutoSCSI parameter set */
54811da177e4SLinus Torvalds 		return;
54821da177e4SLinus Torvalds 
548347b5d69cSJames Bottomley  	FPT_inisci(p_card, p_port, p_our_id);
54841da177e4SLinus Torvalds 
54851da177e4SLinus Torvalds 	/* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
54861da177e4SLinus Torvalds 	   too slow to return to SCAM selection */
54871da177e4SLinus Torvalds 
54881da177e4SLinus Torvalds 	/* if (p_power_up)
548947b5d69cSJames Bottomley  	   FPT_Wait1Second(p_port);
54901da177e4SLinus Torvalds 	   else
549147b5d69cSJames Bottomley  	   FPT_Wait(p_port, TO_250ms); */
54921da177e4SLinus Torvalds 
549347b5d69cSJames Bottomley  	FPT_Wait1Second(p_port);
54941da177e4SLinus Torvalds 
54955c04a7b8SAlexey Dobriyan 	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
54965c04a7b8SAlexey Dobriyan 		while (!(FPT_scarb(p_port, INIT_SELTD))) {
54975c04a7b8SAlexey Dobriyan 		}
54981da177e4SLinus Torvalds 
549947b5d69cSJames Bottomley  		FPT_scsel(p_port);
55001da177e4SLinus Torvalds 
55011da177e4SLinus Torvalds 		do {
550247b5d69cSJames Bottomley  			FPT_scxferc(p_port, SYNC_PTRN);
550347b5d69cSJames Bottomley  			FPT_scxferc(p_port, DOM_MSTR);
55045c04a7b8SAlexey Dobriyan 			loser =
55055c04a7b8SAlexey Dobriyan 			    FPT_scsendi(p_port,
55065c04a7b8SAlexey Dobriyan 					&FPT_scamInfo[p_our_id].id_string[0]);
55071da177e4SLinus Torvalds 		} while (loser == 0xFF);
55081da177e4SLinus Torvalds 
550947b5d69cSJames Bottomley  		FPT_scbusf(p_port);
55101da177e4SLinus Torvalds 
55115c04a7b8SAlexey Dobriyan 		if ((p_power_up) && (!loser)) {
551247b5d69cSJames Bottomley  			FPT_sresb(p_port, p_card);
551347b5d69cSJames Bottomley  			FPT_Wait(p_port, TO_250ms);
55141da177e4SLinus Torvalds 
55155c04a7b8SAlexey Dobriyan 			while (!(FPT_scarb(p_port, INIT_SELTD))) {
55165c04a7b8SAlexey Dobriyan 			}
55171da177e4SLinus Torvalds 
551847b5d69cSJames Bottomley  			FPT_scsel(p_port);
55191da177e4SLinus Torvalds 
55201da177e4SLinus Torvalds 			do {
552147b5d69cSJames Bottomley  				FPT_scxferc(p_port, SYNC_PTRN);
552247b5d69cSJames Bottomley  				FPT_scxferc(p_port, DOM_MSTR);
55235c04a7b8SAlexey Dobriyan 				loser =
55245c04a7b8SAlexey Dobriyan 				    FPT_scsendi(p_port,
55255c04a7b8SAlexey Dobriyan 						&FPT_scamInfo[p_our_id].
55261da177e4SLinus Torvalds 						id_string[0]);
55271da177e4SLinus Torvalds 			} while (loser == 0xFF);
55281da177e4SLinus Torvalds 
552947b5d69cSJames Bottomley  			FPT_scbusf(p_port);
55301da177e4SLinus Torvalds 		}
55311da177e4SLinus Torvalds 	}
55321da177e4SLinus Torvalds 
55335c04a7b8SAlexey Dobriyan 	else {
553447b5d69cSJames Bottomley  		loser = 0;
55351da177e4SLinus Torvalds 	}
55361da177e4SLinus Torvalds 
55375c04a7b8SAlexey Dobriyan 	if (!loser) {
55381da177e4SLinus Torvalds 
553947b5d69cSJames Bottomley  		FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
55401da177e4SLinus Torvalds 
55415c04a7b8SAlexey Dobriyan 		if (ScamFlg & SCAM_ENABLED) {
55421da177e4SLinus Torvalds 
55435c04a7b8SAlexey Dobriyan 			for (i = 0; i < MAX_SCSI_TAR; i++) {
554447b5d69cSJames Bottomley  				if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
55455c04a7b8SAlexey Dobriyan 				    (FPT_scamInfo[i].state == ID_UNUSED)) {
55465c04a7b8SAlexey Dobriyan 					if (FPT_scsell(p_port, i)) {
554747b5d69cSJames Bottomley  						FPT_scamInfo[i].state = LEGACY;
55485c04a7b8SAlexey Dobriyan 						if ((FPT_scamInfo[i].
55495c04a7b8SAlexey Dobriyan 						     id_string[0] != 0xFF)
55505c04a7b8SAlexey Dobriyan 						    || (FPT_scamInfo[i].
55515c04a7b8SAlexey Dobriyan 							id_string[1] != 0xFA)) {
55521da177e4SLinus Torvalds 
55535c04a7b8SAlexey Dobriyan 							FPT_scamInfo[i].
55545c04a7b8SAlexey Dobriyan 							    id_string[0] = 0xFF;
55555c04a7b8SAlexey Dobriyan 							FPT_scamInfo[i].
55565c04a7b8SAlexey Dobriyan 							    id_string[1] = 0xFA;
55571da177e4SLinus Torvalds 							if (pCurrNvRam == NULL)
55585c04a7b8SAlexey Dobriyan 								currCard->
55595c04a7b8SAlexey Dobriyan 								    globalFlags
55605c04a7b8SAlexey Dobriyan 								    |=
55615c04a7b8SAlexey Dobriyan 								    F_UPDATE_EEPROM;
55621da177e4SLinus Torvalds 						}
55631da177e4SLinus Torvalds 					}
55641da177e4SLinus Torvalds 				}
55651da177e4SLinus Torvalds 			}
55661da177e4SLinus Torvalds 
556747b5d69cSJames Bottomley  			FPT_sresb(p_port, p_card);
556847b5d69cSJames Bottomley  			FPT_Wait1Second(p_port);
55695c04a7b8SAlexey Dobriyan 			while (!(FPT_scarb(p_port, INIT_SELTD))) {
55705c04a7b8SAlexey Dobriyan 			}
557147b5d69cSJames Bottomley  			FPT_scsel(p_port);
557247b5d69cSJames Bottomley  			FPT_scasid(p_card, p_port);
55731da177e4SLinus Torvalds 		}
55741da177e4SLinus Torvalds 
55751da177e4SLinus Torvalds 	}
55761da177e4SLinus Torvalds 
55775c04a7b8SAlexey Dobriyan 	else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
557847b5d69cSJames Bottomley  		FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
557947b5d69cSJames Bottomley  		assigned_id = 0;
558047b5d69cSJames Bottomley  		FPT_scwtsel(p_port);
55811da177e4SLinus Torvalds 
55821da177e4SLinus Torvalds 		do {
55835c04a7b8SAlexey Dobriyan 			while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
55845c04a7b8SAlexey Dobriyan 			}
55851da177e4SLinus Torvalds 
558647b5d69cSJames Bottomley  			i = FPT_scxferc(p_port, 0x00);
55875c04a7b8SAlexey Dobriyan 			if (i == ASSIGN_ID) {
55885c04a7b8SAlexey Dobriyan 				if (!
55895c04a7b8SAlexey Dobriyan 				    (FPT_scsendi
55905c04a7b8SAlexey Dobriyan 				     (p_port,
55915c04a7b8SAlexey Dobriyan 				      &FPT_scamInfo[p_our_id].id_string[0]))) {
559247b5d69cSJames Bottomley  					i = FPT_scxferc(p_port, 0x00);
55935c04a7b8SAlexey Dobriyan 					if (FPT_scvalq(i)) {
559447b5d69cSJames Bottomley  						k = FPT_scxferc(p_port, 0x00);
55951da177e4SLinus Torvalds 
55965c04a7b8SAlexey Dobriyan 						if (FPT_scvalq(k)) {
55971da177e4SLinus Torvalds 							currCard->ourId =
55985c04a7b8SAlexey Dobriyan 							    ((unsigned char)(i
55995c04a7b8SAlexey Dobriyan 									     <<
56005c04a7b8SAlexey Dobriyan 									     3)
56015c04a7b8SAlexey Dobriyan 							     +
56025c04a7b8SAlexey Dobriyan 							     (k &
56035c04a7b8SAlexey Dobriyan 							      (unsigned char)7))
56045c04a7b8SAlexey Dobriyan 							    & (unsigned char)
56055c04a7b8SAlexey Dobriyan 							    0x3F;
56065c04a7b8SAlexey Dobriyan 							FPT_inisci(p_card,
56075c04a7b8SAlexey Dobriyan 								   p_port,
56085c04a7b8SAlexey Dobriyan 								   p_our_id);
56095c04a7b8SAlexey Dobriyan 							FPT_scamInfo[currCard->
56105c04a7b8SAlexey Dobriyan 								     ourId].
56115c04a7b8SAlexey Dobriyan 							    state = ID_ASSIGNED;
56125c04a7b8SAlexey Dobriyan 							FPT_scamInfo[currCard->
56135c04a7b8SAlexey Dobriyan 								     ourId].
56145c04a7b8SAlexey Dobriyan 							    id_string[0]
56151da177e4SLinus Torvalds 							    = SLV_TYPE_CODE0;
561647b5d69cSJames Bottomley  							assigned_id = 1;
56171da177e4SLinus Torvalds 						}
56181da177e4SLinus Torvalds 					}
56191da177e4SLinus Torvalds 				}
56201da177e4SLinus Torvalds 			}
56211da177e4SLinus Torvalds 
56225c04a7b8SAlexey Dobriyan 			else if (i == SET_P_FLAG) {
562347b5d69cSJames Bottomley  				if (!(FPT_scsendi(p_port,
56245c04a7b8SAlexey Dobriyan 						  &FPT_scamInfo[p_our_id].
56255c04a7b8SAlexey Dobriyan 						  id_string[0])))
56265c04a7b8SAlexey Dobriyan 					FPT_scamInfo[p_our_id].id_string[0] |=
56275c04a7b8SAlexey Dobriyan 					    0x80;
56281da177e4SLinus Torvalds 			}
56291da177e4SLinus Torvalds 		} while (!assigned_id);
56301da177e4SLinus Torvalds 
56315c04a7b8SAlexey Dobriyan 		while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
56325c04a7b8SAlexey Dobriyan 		}
56331da177e4SLinus Torvalds 	}
56341da177e4SLinus Torvalds 
56355c04a7b8SAlexey Dobriyan 	if (ScamFlg & SCAM_ENABLED) {
563647b5d69cSJames Bottomley  		FPT_scbusf(p_port);
56375c04a7b8SAlexey Dobriyan 		if (currCard->globalFlags & F_UPDATE_EEPROM) {
563847b5d69cSJames Bottomley  			FPT_scsavdi(p_card, p_port);
56391da177e4SLinus Torvalds 			currCard->globalFlags &= ~F_UPDATE_EEPROM;
56401da177e4SLinus Torvalds 		}
56411da177e4SLinus Torvalds 	}
56421da177e4SLinus Torvalds 
56431da177e4SLinus Torvalds /*
56441da177e4SLinus Torvalds    for (i=0,k=0; i < MAX_SCSI_TAR; i++)
56451da177e4SLinus Torvalds       {
564647b5d69cSJames Bottomley        if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
564747b5d69cSJames Bottomley           (FPT_scamInfo[i].state == LEGACY))
56481da177e4SLinus Torvalds          k++;
56491da177e4SLinus Torvalds       }
56501da177e4SLinus Torvalds 
56511da177e4SLinus Torvalds    if (k==2)
56521da177e4SLinus Torvalds       currCard->globalFlags |= F_SINGLE_DEVICE;
56531da177e4SLinus Torvalds    else
56541da177e4SLinus Torvalds       currCard->globalFlags &= ~F_SINGLE_DEVICE;
56551da177e4SLinus Torvalds */
56561da177e4SLinus Torvalds }
56571da177e4SLinus Torvalds 
56581da177e4SLinus Torvalds /*---------------------------------------------------------------------
56591da177e4SLinus Torvalds  *
566047b5d69cSJames Bottomley   * Function: FPT_scarb
56611da177e4SLinus Torvalds  *
56621da177e4SLinus Torvalds  * Description: Gain control of the bus and wait SCAM select time (250ms)
56631da177e4SLinus Torvalds  *
56641da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
56651da177e4SLinus Torvalds 
5666391e2f25SKhalid Aziz static int FPT_scarb(u32 p_port, unsigned char p_sel_type)
56671da177e4SLinus Torvalds {
56685c04a7b8SAlexey Dobriyan 	if (p_sel_type == INIT_SELTD) {
56691da177e4SLinus Torvalds 
56705c04a7b8SAlexey Dobriyan 		while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
56715c04a7b8SAlexey Dobriyan 		}
56721da177e4SLinus Torvalds 
56731da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
56745c1b85e2SAlexey Dobriyan 			return 0;
56751da177e4SLinus Torvalds 
56761da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
56775c1b85e2SAlexey Dobriyan 			return 0;
56781da177e4SLinus Torvalds 
56795c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_scsisig,
56805c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
56811da177e4SLinus Torvalds 
56821da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
56831da177e4SLinus Torvalds 
56845c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_scsisig,
56855c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(p_port + hp_scsisig) &
56861da177e4SLinus Torvalds 				    ~SCSI_BSY));
56875c1b85e2SAlexey Dobriyan 			return 0;
56881da177e4SLinus Torvalds 		}
56891da177e4SLinus Torvalds 
56905c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_scsisig,
56915c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
56921da177e4SLinus Torvalds 
56931da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
56941da177e4SLinus Torvalds 
56955c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_scsisig,
56965c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(p_port + hp_scsisig) &
56971da177e4SLinus Torvalds 				    ~(SCSI_BSY | SCSI_SEL)));
56985c1b85e2SAlexey Dobriyan 			return 0;
56991da177e4SLinus Torvalds 		}
57001da177e4SLinus Torvalds 	}
57011da177e4SLinus Torvalds 
57021da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
57031da177e4SLinus Torvalds 					   & ~ACTdeassert));
57041da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
57051da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
57061da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_1, 0x00);
57071da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
57081da177e4SLinus Torvalds 
57095c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsisig,
57105c04a7b8SAlexey Dobriyan 		   (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
57111da177e4SLinus Torvalds 
57121da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
57131da177e4SLinus Torvalds 					 & ~SCSI_BSY));
57141da177e4SLinus Torvalds 
571547b5d69cSJames Bottomley  	FPT_Wait(p_port, TO_250ms);
57161da177e4SLinus Torvalds 
57175c1b85e2SAlexey Dobriyan 	return 1;
57181da177e4SLinus Torvalds }
57191da177e4SLinus Torvalds 
57201da177e4SLinus Torvalds /*---------------------------------------------------------------------
57211da177e4SLinus Torvalds  *
572247b5d69cSJames Bottomley   * Function: FPT_scbusf
57231da177e4SLinus Torvalds  *
57241da177e4SLinus Torvalds  * Description: Release the SCSI bus and disable SCAM selection.
57251da177e4SLinus Torvalds  *
57261da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
57271da177e4SLinus Torvalds 
5728391e2f25SKhalid Aziz static void FPT_scbusf(u32 p_port)
57291da177e4SLinus Torvalds {
57301da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl,
57311da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
57321da177e4SLinus Torvalds 
57331da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
57341da177e4SLinus Torvalds 
57351da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
57361da177e4SLinus Torvalds 					    & ~SCSI_BUS_EN));
57371da177e4SLinus Torvalds 
57381da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, 0x00);
57391da177e4SLinus Torvalds 
57401da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
57411da177e4SLinus Torvalds 					   & ~SCAM_EN));
57421da177e4SLinus Torvalds 
57431da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
57441da177e4SLinus Torvalds 					   | ACTdeassert));
57451da177e4SLinus Torvalds 
57461da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
57471da177e4SLinus Torvalds 
57481da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl,
57491da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
57501da177e4SLinus Torvalds }
57511da177e4SLinus Torvalds 
57521da177e4SLinus Torvalds /*---------------------------------------------------------------------
57531da177e4SLinus Torvalds  *
575447b5d69cSJames Bottomley   * Function: FPT_scasid
57551da177e4SLinus Torvalds  *
57561da177e4SLinus Torvalds  * Description: Assign an ID to all the SCAM devices.
57571da177e4SLinus Torvalds  *
57581da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
57591da177e4SLinus Torvalds 
5760391e2f25SKhalid Aziz static void FPT_scasid(unsigned char p_card, u32 p_port)
57611da177e4SLinus Torvalds {
5762db038cf8SAlexey Dobriyan 	unsigned char temp_id_string[ID_STRING_LENGTH];
57631da177e4SLinus Torvalds 
5764db038cf8SAlexey Dobriyan 	unsigned char i, k, scam_id;
5765db038cf8SAlexey Dobriyan 	unsigned char crcBytes[3];
576668d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
5767fd1e29edSAlexey Dobriyan 	unsigned short *pCrcBytes;
57681da177e4SLinus Torvalds 
576947b5d69cSJames Bottomley  	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
57701da177e4SLinus Torvalds 
577147b5d69cSJames Bottomley  	i = 0;
57721da177e4SLinus Torvalds 
57735c04a7b8SAlexey Dobriyan 	while (!i) {
57741da177e4SLinus Torvalds 
57755c04a7b8SAlexey Dobriyan 		for (k = 0; k < ID_STRING_LENGTH; k++) {
5776db038cf8SAlexey Dobriyan 			temp_id_string[k] = (unsigned char)0x00;
57771da177e4SLinus Torvalds 		}
57781da177e4SLinus Torvalds 
577947b5d69cSJames Bottomley  		FPT_scxferc(p_port, SYNC_PTRN);
578047b5d69cSJames Bottomley  		FPT_scxferc(p_port, ASSIGN_ID);
57811da177e4SLinus Torvalds 
57825c04a7b8SAlexey Dobriyan 		if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
57831da177e4SLinus Torvalds 			if (pCurrNvRam) {
5784fd1e29edSAlexey Dobriyan 				pCrcBytes = (unsigned short *)&crcBytes[0];
578547b5d69cSJames Bottomley  				*pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
578647b5d69cSJames Bottomley  				crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
57871da177e4SLinus Torvalds 				temp_id_string[1] = crcBytes[2];
57881da177e4SLinus Torvalds 				temp_id_string[2] = crcBytes[0];
57891da177e4SLinus Torvalds 				temp_id_string[3] = crcBytes[1];
57901da177e4SLinus Torvalds 				for (k = 4; k < ID_STRING_LENGTH; k++)
5791db038cf8SAlexey Dobriyan 					temp_id_string[k] = (unsigned char)0x00;
57921da177e4SLinus Torvalds 			}
579347b5d69cSJames Bottomley  			i = FPT_scmachid(p_card, temp_id_string);
57941da177e4SLinus Torvalds 
57955c04a7b8SAlexey Dobriyan 			if (i == CLR_PRIORITY) {
579647b5d69cSJames Bottomley  				FPT_scxferc(p_port, MISC_CODE);
579747b5d69cSJames Bottomley  				FPT_scxferc(p_port, CLR_P_FLAG);
579847b5d69cSJames Bottomley  				i = 0;	/*Not the last ID yet. */
57991da177e4SLinus Torvalds 			}
58001da177e4SLinus Torvalds 
58015c04a7b8SAlexey Dobriyan 			else if (i != NO_ID_AVAIL) {
58021da177e4SLinus Torvalds 				if (i < 8)
580347b5d69cSJames Bottomley  					FPT_scxferc(p_port, ID_0_7);
58041da177e4SLinus Torvalds 				else
580547b5d69cSJames Bottomley  					FPT_scxferc(p_port, ID_8_F);
58061da177e4SLinus Torvalds 
5807db038cf8SAlexey Dobriyan 				scam_id = (i & (unsigned char)0x07);
58081da177e4SLinus Torvalds 
58091da177e4SLinus Torvalds 				for (k = 1; k < 0x08; k <<= 1)
58101da177e4SLinus Torvalds 					if (!(k & i))
58111da177e4SLinus Torvalds 						scam_id += 0x08;	/*Count number of zeros in DB0-3. */
58121da177e4SLinus Torvalds 
581347b5d69cSJames Bottomley  				FPT_scxferc(p_port, scam_id);
58141da177e4SLinus Torvalds 
581547b5d69cSJames Bottomley  				i = 0;	/*Not the last ID yet. */
58161da177e4SLinus Torvalds 			}
58171da177e4SLinus Torvalds 		}
58181da177e4SLinus Torvalds 
58195c04a7b8SAlexey Dobriyan 		else {
582047b5d69cSJames Bottomley  			i = 1;
58211da177e4SLinus Torvalds 		}
58221da177e4SLinus Torvalds 
58231da177e4SLinus Torvalds 	}			/*End while */
58241da177e4SLinus Torvalds 
582547b5d69cSJames Bottomley  	FPT_scxferc(p_port, SYNC_PTRN);
582647b5d69cSJames Bottomley  	FPT_scxferc(p_port, CFG_CMPLT);
58271da177e4SLinus Torvalds }
58281da177e4SLinus Torvalds 
58291da177e4SLinus Torvalds /*---------------------------------------------------------------------
58301da177e4SLinus Torvalds  *
583147b5d69cSJames Bottomley   * Function: FPT_scsel
58321da177e4SLinus Torvalds  *
58331da177e4SLinus Torvalds  * Description: Select all the SCAM devices.
58341da177e4SLinus Torvalds  *
58351da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
58361da177e4SLinus Torvalds 
5837391e2f25SKhalid Aziz static void FPT_scsel(u32 p_port)
58381da177e4SLinus Torvalds {
58391da177e4SLinus Torvalds 
58401da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
584147b5d69cSJames Bottomley  	FPT_scwiros(p_port, SCSI_MSG);
58421da177e4SLinus Torvalds 
58431da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
58441da177e4SLinus Torvalds 
58455c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsisig,
58465c04a7b8SAlexey Dobriyan 		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
58475c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsidata_0,
58485c04a7b8SAlexey Dobriyan 		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5849db038cf8SAlexey Dobriyan 				   (unsigned char)(BIT(7) + BIT(6))));
58501da177e4SLinus Torvalds 
58511da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
585247b5d69cSJames Bottomley  	FPT_scwiros(p_port, SCSI_SEL);
58531da177e4SLinus Torvalds 
58545c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsidata_0,
58555c04a7b8SAlexey Dobriyan 		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5856db038cf8SAlexey Dobriyan 				   ~(unsigned char)BIT(6)));
585747b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(6));
58581da177e4SLinus Torvalds 
58595c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsisig,
58605c04a7b8SAlexey Dobriyan 		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
58611da177e4SLinus Torvalds }
58621da177e4SLinus Torvalds 
58631da177e4SLinus Torvalds /*---------------------------------------------------------------------
58641da177e4SLinus Torvalds  *
586547b5d69cSJames Bottomley   * Function: FPT_scxferc
58661da177e4SLinus Torvalds  *
58671da177e4SLinus Torvalds  * Description: Handshake the p_data (DB4-0) across the bus.
58681da177e4SLinus Torvalds  *
58691da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
58701da177e4SLinus Torvalds 
5871391e2f25SKhalid Aziz static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data)
58721da177e4SLinus Torvalds {
5873db038cf8SAlexey Dobriyan 	unsigned char curr_data, ret_data;
58741da177e4SLinus Torvalds 
58751da177e4SLinus Torvalds 	curr_data = p_data | BIT(7) | BIT(5);	/*Start with DB7 & DB5 asserted. */
58761da177e4SLinus Torvalds 
58771da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
58781da177e4SLinus Torvalds 
58791da177e4SLinus Torvalds 	curr_data &= ~BIT(7);
58801da177e4SLinus Torvalds 
58811da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
58821da177e4SLinus Torvalds 
588347b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(7));	/*Wait for DB7 to be released. */
58841da177e4SLinus Torvalds 	while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
58851da177e4SLinus Torvalds 
5886db038cf8SAlexey Dobriyan 	ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
58871da177e4SLinus Torvalds 
58881da177e4SLinus Torvalds 	curr_data |= BIT(6);
58891da177e4SLinus Torvalds 
58901da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
58911da177e4SLinus Torvalds 
58921da177e4SLinus Torvalds 	curr_data &= ~BIT(5);
58931da177e4SLinus Torvalds 
58941da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
58951da177e4SLinus Torvalds 
589647b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(5));	/*Wait for DB5 to be released. */
58971da177e4SLinus Torvalds 
58981da177e4SLinus Torvalds 	curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));	/*Release data bits */
58991da177e4SLinus Torvalds 	curr_data |= BIT(7);
59001da177e4SLinus Torvalds 
59011da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
59021da177e4SLinus Torvalds 
59031da177e4SLinus Torvalds 	curr_data &= ~BIT(6);
59041da177e4SLinus Torvalds 
59051da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
59061da177e4SLinus Torvalds 
590747b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(6));	/*Wait for DB6 to be released. */
59081da177e4SLinus Torvalds 
59095c1b85e2SAlexey Dobriyan 	return ret_data;
59101da177e4SLinus Torvalds }
59111da177e4SLinus Torvalds 
59121da177e4SLinus Torvalds /*---------------------------------------------------------------------
59131da177e4SLinus Torvalds  *
591447b5d69cSJames Bottomley   * Function: FPT_scsendi
59151da177e4SLinus Torvalds  *
59161da177e4SLinus Torvalds  * Description: Transfer our Identification string to determine if we
59171da177e4SLinus Torvalds  *              will be the dominant master.
59181da177e4SLinus Torvalds  *
59191da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
59201da177e4SLinus Torvalds 
5921391e2f25SKhalid Aziz static unsigned char FPT_scsendi(u32 p_port, unsigned char p_id_string[])
59221da177e4SLinus Torvalds {
5923db038cf8SAlexey Dobriyan 	unsigned char ret_data, byte_cnt, bit_cnt, defer;
59241da177e4SLinus Torvalds 
592547b5d69cSJames Bottomley  	defer = 0;
59261da177e4SLinus Torvalds 
59271da177e4SLinus Torvalds 	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
59281da177e4SLinus Torvalds 
59291da177e4SLinus Torvalds 		for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
59301da177e4SLinus Torvalds 
59311da177e4SLinus Torvalds 			if (defer)
593247b5d69cSJames Bottomley  				ret_data = FPT_scxferc(p_port, 00);
59331da177e4SLinus Torvalds 
59341da177e4SLinus Torvalds 			else if (p_id_string[byte_cnt] & bit_cnt)
59351da177e4SLinus Torvalds 
593647b5d69cSJames Bottomley  				ret_data = FPT_scxferc(p_port, 02);
59371da177e4SLinus Torvalds 
59381da177e4SLinus Torvalds 			else {
59391da177e4SLinus Torvalds 
594047b5d69cSJames Bottomley  				ret_data = FPT_scxferc(p_port, 01);
59411da177e4SLinus Torvalds 				if (ret_data & 02)
594247b5d69cSJames Bottomley  					defer = 1;
59431da177e4SLinus Torvalds 			}
59441da177e4SLinus Torvalds 
59451da177e4SLinus Torvalds 			if ((ret_data & 0x1C) == 0x10)
59465c1b85e2SAlexey Dobriyan 				return 0x00;	/*End of isolation stage, we won! */
59471da177e4SLinus Torvalds 
59481da177e4SLinus Torvalds 			if (ret_data & 0x1C)
59495c1b85e2SAlexey Dobriyan 				return 0xFF;
59501da177e4SLinus Torvalds 
59511da177e4SLinus Torvalds 			if ((defer) && (!(ret_data & 0x1F)))
59525c1b85e2SAlexey Dobriyan 				return 0x01;	/*End of isolation stage, we lost. */
59531da177e4SLinus Torvalds 
59541da177e4SLinus Torvalds 		}		/*bit loop */
59551da177e4SLinus Torvalds 
59561da177e4SLinus Torvalds 	}			/*byte loop */
59571da177e4SLinus Torvalds 
59581da177e4SLinus Torvalds 	if (defer)
59595c1b85e2SAlexey Dobriyan 		return 0x01;	/*We lost */
59601da177e4SLinus Torvalds 	else
59615c1b85e2SAlexey Dobriyan 		return 0;	/*We WON! Yeeessss! */
59621da177e4SLinus Torvalds }
59631da177e4SLinus Torvalds 
59641da177e4SLinus Torvalds /*---------------------------------------------------------------------
59651da177e4SLinus Torvalds  *
596647b5d69cSJames Bottomley   * Function: FPT_sciso
59671da177e4SLinus Torvalds  *
59681da177e4SLinus Torvalds  * Description: Transfer the Identification string.
59691da177e4SLinus Torvalds  *
59701da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
59711da177e4SLinus Torvalds 
5972391e2f25SKhalid Aziz static unsigned char FPT_sciso(u32 p_port, unsigned char p_id_string[])
59731da177e4SLinus Torvalds {
5974db038cf8SAlexey Dobriyan 	unsigned char ret_data, the_data, byte_cnt, bit_cnt;
59751da177e4SLinus Torvalds 
59761da177e4SLinus Torvalds 	the_data = 0;
59771da177e4SLinus Torvalds 
59781da177e4SLinus Torvalds 	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
59791da177e4SLinus Torvalds 
59801da177e4SLinus Torvalds 		for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
59811da177e4SLinus Torvalds 
598247b5d69cSJames Bottomley  			ret_data = FPT_scxferc(p_port, 0);
59831da177e4SLinus Torvalds 
59841da177e4SLinus Torvalds 			if (ret_data & 0xFC)
59855c1b85e2SAlexey Dobriyan 				return 0xFF;
59861da177e4SLinus Torvalds 
59871da177e4SLinus Torvalds 			else {
59881da177e4SLinus Torvalds 
59891da177e4SLinus Torvalds 				the_data <<= 1;
59901da177e4SLinus Torvalds 				if (ret_data & BIT(1)) {
59911da177e4SLinus Torvalds 					the_data |= 1;
59921da177e4SLinus Torvalds 				}
59931da177e4SLinus Torvalds 			}
59941da177e4SLinus Torvalds 
59955c04a7b8SAlexey Dobriyan 			if ((ret_data & 0x1F) == 0) {
59961da177e4SLinus Torvalds /*
59971da177e4SLinus Torvalds 				if(bit_cnt != 0 || bit_cnt != 8)
59981da177e4SLinus Torvalds 				{
59991da177e4SLinus Torvalds 					byte_cnt = 0;
60001da177e4SLinus Torvalds 					bit_cnt = 0;
600147b5d69cSJames Bottomley  					FPT_scxferc(p_port, SYNC_PTRN);
600247b5d69cSJames Bottomley  					FPT_scxferc(p_port, ASSIGN_ID);
60031da177e4SLinus Torvalds 					continue;
60041da177e4SLinus Torvalds 				}
60051da177e4SLinus Torvalds */
60061da177e4SLinus Torvalds 				if (byte_cnt)
60075c1b85e2SAlexey Dobriyan 					return 0x00;
60081da177e4SLinus Torvalds 				else
60095c1b85e2SAlexey Dobriyan 					return 0xFF;
60101da177e4SLinus Torvalds 			}
60111da177e4SLinus Torvalds 
60121da177e4SLinus Torvalds 		}		/*bit loop */
60131da177e4SLinus Torvalds 
60141da177e4SLinus Torvalds 		p_id_string[byte_cnt] = the_data;
60151da177e4SLinus Torvalds 
60161da177e4SLinus Torvalds 	}			/*byte loop */
60171da177e4SLinus Torvalds 
60185c1b85e2SAlexey Dobriyan 	return 0;
60191da177e4SLinus Torvalds }
60201da177e4SLinus Torvalds 
60211da177e4SLinus Torvalds /*---------------------------------------------------------------------
60221da177e4SLinus Torvalds  *
602347b5d69cSJames Bottomley   * Function: FPT_scwirod
60241da177e4SLinus Torvalds  *
60251da177e4SLinus Torvalds  * Description: Sample the SCSI data bus making sure the signal has been
60261da177e4SLinus Torvalds  *              deasserted for the correct number of consecutive samples.
60271da177e4SLinus Torvalds  *
60281da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
60291da177e4SLinus Torvalds 
6030391e2f25SKhalid Aziz static void FPT_scwirod(u32 p_port, unsigned char p_data_bit)
60311da177e4SLinus Torvalds {
6032db038cf8SAlexey Dobriyan 	unsigned char i;
60331da177e4SLinus Torvalds 
60341da177e4SLinus Torvalds 	i = 0;
60351da177e4SLinus Torvalds 	while (i < MAX_SCSI_TAR) {
60361da177e4SLinus Torvalds 
60371da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
60381da177e4SLinus Torvalds 
60391da177e4SLinus Torvalds 			i = 0;
60401da177e4SLinus Torvalds 
60411da177e4SLinus Torvalds 		else
60421da177e4SLinus Torvalds 
60431da177e4SLinus Torvalds 			i++;
60441da177e4SLinus Torvalds 
60451da177e4SLinus Torvalds 	}
60461da177e4SLinus Torvalds }
60471da177e4SLinus Torvalds 
60481da177e4SLinus Torvalds /*---------------------------------------------------------------------
60491da177e4SLinus Torvalds  *
605047b5d69cSJames Bottomley   * Function: FPT_scwiros
60511da177e4SLinus Torvalds  *
60521da177e4SLinus Torvalds  * Description: Sample the SCSI Signal lines making sure the signal has been
60531da177e4SLinus Torvalds  *              deasserted for the correct number of consecutive samples.
60541da177e4SLinus Torvalds  *
60551da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
60561da177e4SLinus Torvalds 
6057391e2f25SKhalid Aziz static void FPT_scwiros(u32 p_port, unsigned char p_data_bit)
60581da177e4SLinus Torvalds {
6059db038cf8SAlexey Dobriyan 	unsigned char i;
60601da177e4SLinus Torvalds 
60611da177e4SLinus Torvalds 	i = 0;
60621da177e4SLinus Torvalds 	while (i < MAX_SCSI_TAR) {
60631da177e4SLinus Torvalds 
60641da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
60651da177e4SLinus Torvalds 
60661da177e4SLinus Torvalds 			i = 0;
60671da177e4SLinus Torvalds 
60681da177e4SLinus Torvalds 		else
60691da177e4SLinus Torvalds 
60701da177e4SLinus Torvalds 			i++;
60711da177e4SLinus Torvalds 
60721da177e4SLinus Torvalds 	}
60731da177e4SLinus Torvalds }
60741da177e4SLinus Torvalds 
60751da177e4SLinus Torvalds /*---------------------------------------------------------------------
60761da177e4SLinus Torvalds  *
607747b5d69cSJames Bottomley   * Function: FPT_scvalq
60781da177e4SLinus Torvalds  *
60791da177e4SLinus Torvalds  * Description: Make sure we received a valid data byte.
60801da177e4SLinus Torvalds  *
60811da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
60821da177e4SLinus Torvalds 
6083db038cf8SAlexey Dobriyan static unsigned char FPT_scvalq(unsigned char p_quintet)
60841da177e4SLinus Torvalds {
6085db038cf8SAlexey Dobriyan 	unsigned char count;
60861da177e4SLinus Torvalds 
60871da177e4SLinus Torvalds 	for (count = 1; count < 0x08; count <<= 1) {
60881da177e4SLinus Torvalds 		if (!(p_quintet & count))
60891da177e4SLinus Torvalds 			p_quintet -= 0x80;
60901da177e4SLinus Torvalds 	}
60911da177e4SLinus Torvalds 
60921da177e4SLinus Torvalds 	if (p_quintet & 0x18)
60935c1b85e2SAlexey Dobriyan 		return 0;
60941da177e4SLinus Torvalds 
60951da177e4SLinus Torvalds 	else
60965c1b85e2SAlexey Dobriyan 		return 1;
60971da177e4SLinus Torvalds }
60981da177e4SLinus Torvalds 
60991da177e4SLinus Torvalds /*---------------------------------------------------------------------
61001da177e4SLinus Torvalds  *
610147b5d69cSJames Bottomley   * Function: FPT_scsell
61021da177e4SLinus Torvalds  *
61031da177e4SLinus Torvalds  * Description: Select the specified device ID using a selection timeout
61041da177e4SLinus Torvalds  *              less than 4ms.  If somebody responds then it is a legacy
61051da177e4SLinus Torvalds  *              drive and this ID must be marked as such.
61061da177e4SLinus Torvalds  *
61071da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
61081da177e4SLinus Torvalds 
6109391e2f25SKhalid Aziz static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id)
61101da177e4SLinus Torvalds {
6111d63a4cccSAlexey Dobriyan 	unsigned long i;
61121da177e4SLinus Torvalds 
61131da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl,
61141da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
61151da177e4SLinus Torvalds 
61161da177e4SLinus Torvalds 	ARAM_ACCESS(p_port);
61171da177e4SLinus Torvalds 
61185c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_addstat,
61195c04a7b8SAlexey Dobriyan 		   (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
61201da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
61211da177e4SLinus Torvalds 
61221da177e4SLinus Torvalds 	for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
61231da177e4SLinus Torvalds 		WRW_HARPOON(i, (MPM_OP + ACOMMAND));
61241da177e4SLinus Torvalds 	}
61251da177e4SLinus Torvalds 	WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
61261da177e4SLinus Torvalds 
61271da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat),
61281da177e4SLinus Torvalds 		    (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
61291da177e4SLinus Torvalds 
61301da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_select_id, targ_id);
61311da177e4SLinus Torvalds 
61321da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
61331da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
61341da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
61351da177e4SLinus Torvalds 
61361da177e4SLinus Torvalds 	while (!(RDW_HARPOON((p_port + hp_intstat)) &
61375c04a7b8SAlexey Dobriyan 		 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
61385c04a7b8SAlexey Dobriyan 	}
61391da177e4SLinus Torvalds 
61401da177e4SLinus Torvalds 	if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
614147b5d69cSJames Bottomley  		FPT_Wait(p_port, TO_250ms);
61421da177e4SLinus Torvalds 
61431da177e4SLinus Torvalds 	DISABLE_AUTO(p_port);
61441da177e4SLinus Torvalds 
61455c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_addstat,
61465c04a7b8SAlexey Dobriyan 		   (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
61471da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
61481da177e4SLinus Torvalds 
61491da177e4SLinus Torvalds 	SGRAM_ACCESS(p_port);
61501da177e4SLinus Torvalds 
61511da177e4SLinus Torvalds 	if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
61521da177e4SLinus Torvalds 
61531da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat),
61541da177e4SLinus Torvalds 			    (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
61551da177e4SLinus Torvalds 
61561da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_page_ctrl,
61575c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_page_ctrl) &
61585c04a7b8SAlexey Dobriyan 			    ~G_INT_DISABLE));
61591da177e4SLinus Torvalds 
61605c1b85e2SAlexey Dobriyan 		return 0;	/*No legacy device */
61611da177e4SLinus Torvalds 	}
61621da177e4SLinus Torvalds 
61631da177e4SLinus Torvalds 	else {
61641da177e4SLinus Torvalds 
61651da177e4SLinus Torvalds 		while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
61665c04a7b8SAlexey Dobriyan 			if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
61675c04a7b8SAlexey Dobriyan 				WR_HARPOON(p_port + hp_scsisig,
61685c04a7b8SAlexey Dobriyan 					   (SCSI_ACK + S_ILL_PH));
61691da177e4SLinus Torvalds 				ACCEPT_MSG(p_port);
61701da177e4SLinus Torvalds 			}
61711da177e4SLinus Torvalds 		}
61721da177e4SLinus Torvalds 
61731da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
61741da177e4SLinus Torvalds 
61751da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_page_ctrl,
61765c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_page_ctrl) &
61775c04a7b8SAlexey Dobriyan 			    ~G_INT_DISABLE));
61781da177e4SLinus Torvalds 
61795c1b85e2SAlexey Dobriyan 		return 1;	/*Found one of them oldies! */
61801da177e4SLinus Torvalds 	}
61811da177e4SLinus Torvalds }
61821da177e4SLinus Torvalds 
61831da177e4SLinus Torvalds /*---------------------------------------------------------------------
61841da177e4SLinus Torvalds  *
618547b5d69cSJames Bottomley   * Function: FPT_scwtsel
61861da177e4SLinus Torvalds  *
61871da177e4SLinus Torvalds  * Description: Wait to be selected by another SCAM initiator.
61881da177e4SLinus Torvalds  *
61891da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
61901da177e4SLinus Torvalds 
6191391e2f25SKhalid Aziz static void FPT_scwtsel(u32 p_port)
61921da177e4SLinus Torvalds {
61935c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
61941da177e4SLinus Torvalds 	}
61955c04a7b8SAlexey Dobriyan }
61961da177e4SLinus Torvalds 
61971da177e4SLinus Torvalds /*---------------------------------------------------------------------
61981da177e4SLinus Torvalds  *
619947b5d69cSJames Bottomley   * Function: FPT_inisci
62001da177e4SLinus Torvalds  *
62011da177e4SLinus Torvalds  * Description: Setup the data Structure with the info from the EEPROM.
62021da177e4SLinus Torvalds  *
62031da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
62041da177e4SLinus Torvalds 
6205391e2f25SKhalid Aziz static void FPT_inisci(unsigned char p_card, u32 p_port, unsigned char p_our_id)
62061da177e4SLinus Torvalds {
6207db038cf8SAlexey Dobriyan 	unsigned char i, k, max_id;
6208c823feebSAlexey Dobriyan 	unsigned short ee_data;
620968d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
62101da177e4SLinus Torvalds 
621147b5d69cSJames Bottomley  	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
62121da177e4SLinus Torvalds 
62131da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
62141da177e4SLinus Torvalds 		max_id = 0x08;
62151da177e4SLinus Torvalds 
62161da177e4SLinus Torvalds 	else
62171da177e4SLinus Torvalds 		max_id = 0x10;
62181da177e4SLinus Torvalds 
62191da177e4SLinus Torvalds 	if (pCurrNvRam) {
62201da177e4SLinus Torvalds 		for (i = 0; i < max_id; i++) {
62211da177e4SLinus Torvalds 
62221da177e4SLinus Torvalds 			for (k = 0; k < 4; k++)
62235c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k] =
62245c04a7b8SAlexey Dobriyan 				    pCurrNvRam->niScamTbl[i][k];
62251da177e4SLinus Torvalds 			for (k = 4; k < ID_STRING_LENGTH; k++)
62265c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k] =
62275c04a7b8SAlexey Dobriyan 				    (unsigned char)0x00;
62281da177e4SLinus Torvalds 
622947b5d69cSJames Bottomley  			if (FPT_scamInfo[i].id_string[0] == 0x00)
623047b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
62311da177e4SLinus Torvalds 			else
623247b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
62331da177e4SLinus Torvalds 
62341da177e4SLinus Torvalds 		}
62351da177e4SLinus Torvalds 	} else {
62365c04a7b8SAlexey Dobriyan 		for (i = 0; i < max_id; i++) {
62375c04a7b8SAlexey Dobriyan 			for (k = 0; k < ID_STRING_LENGTH; k += 2) {
62385c04a7b8SAlexey Dobriyan 				ee_data =
62395c04a7b8SAlexey Dobriyan 				    FPT_utilEERead(p_port,
62405c04a7b8SAlexey Dobriyan 						   (unsigned
62415c04a7b8SAlexey Dobriyan 						    short)((EE_SCAMBASE / 2) +
62425c04a7b8SAlexey Dobriyan 							   (unsigned short)(i *
62435c04a7b8SAlexey Dobriyan 									    ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
62445c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k] =
62455c04a7b8SAlexey Dobriyan 				    (unsigned char)ee_data;
62461da177e4SLinus Torvalds 				ee_data >>= 8;
62475c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k + 1] =
62485c04a7b8SAlexey Dobriyan 				    (unsigned char)ee_data;
62491da177e4SLinus Torvalds 			}
62501da177e4SLinus Torvalds 
625147b5d69cSJames Bottomley  			if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
625247b5d69cSJames Bottomley  			    (FPT_scamInfo[i].id_string[0] == 0xFF))
62531da177e4SLinus Torvalds 
625447b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
62551da177e4SLinus Torvalds 
62561da177e4SLinus Torvalds 			else
625747b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
62581da177e4SLinus Torvalds 
62591da177e4SLinus Torvalds 		}
62601da177e4SLinus Torvalds 	}
62611da177e4SLinus Torvalds 	for (k = 0; k < ID_STRING_LENGTH; k++)
626247b5d69cSJames Bottomley  		FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
62631da177e4SLinus Torvalds 
62641da177e4SLinus Torvalds }
62651da177e4SLinus Torvalds 
62661da177e4SLinus Torvalds /*---------------------------------------------------------------------
62671da177e4SLinus Torvalds  *
626847b5d69cSJames Bottomley   * Function: FPT_scmachid
62691da177e4SLinus Torvalds  *
62701da177e4SLinus Torvalds  * Description: Match the Device ID string with our values stored in
62711da177e4SLinus Torvalds  *              the EEPROM.
62721da177e4SLinus Torvalds  *
62731da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
62741da177e4SLinus Torvalds 
62755c04a7b8SAlexey Dobriyan static unsigned char FPT_scmachid(unsigned char p_card,
62765c04a7b8SAlexey Dobriyan 				  unsigned char p_id_string[])
62771da177e4SLinus Torvalds {
62781da177e4SLinus Torvalds 
6279db038cf8SAlexey Dobriyan 	unsigned char i, k, match;
62801da177e4SLinus Torvalds 
62811da177e4SLinus Torvalds 	for (i = 0; i < MAX_SCSI_TAR; i++) {
62821da177e4SLinus Torvalds 
628347b5d69cSJames Bottomley  		match = 1;
62841da177e4SLinus Torvalds 
62855c04a7b8SAlexey Dobriyan 		for (k = 0; k < ID_STRING_LENGTH; k++) {
628647b5d69cSJames Bottomley  			if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
628747b5d69cSJames Bottomley  				match = 0;
62881da177e4SLinus Torvalds 		}
62891da177e4SLinus Torvalds 
62905c04a7b8SAlexey Dobriyan 		if (match) {
629147b5d69cSJames Bottomley  			FPT_scamInfo[i].state = ID_ASSIGNED;
62925c1b85e2SAlexey Dobriyan 			return i;
62931da177e4SLinus Torvalds 		}
62941da177e4SLinus Torvalds 
62951da177e4SLinus Torvalds 	}
62961da177e4SLinus Torvalds 
62971da177e4SLinus Torvalds 	if (p_id_string[0] & BIT(5))
62981da177e4SLinus Torvalds 		i = 8;
62991da177e4SLinus Torvalds 	else
63001da177e4SLinus Torvalds 		i = MAX_SCSI_TAR;
63011da177e4SLinus Torvalds 
63025c04a7b8SAlexey Dobriyan 	if (((p_id_string[0] & 0x06) == 0x02)
63035c04a7b8SAlexey Dobriyan 	    || ((p_id_string[0] & 0x06) == 0x04))
6304db038cf8SAlexey Dobriyan 		match = p_id_string[1] & (unsigned char)0x1F;
63051da177e4SLinus Torvalds 	else
63061da177e4SLinus Torvalds 		match = 7;
63071da177e4SLinus Torvalds 
63085c04a7b8SAlexey Dobriyan 	while (i > 0) {
63091da177e4SLinus Torvalds 		i--;
63101da177e4SLinus Torvalds 
63115c04a7b8SAlexey Dobriyan 		if (FPT_scamInfo[match].state == ID_UNUSED) {
63125c04a7b8SAlexey Dobriyan 			for (k = 0; k < ID_STRING_LENGTH; k++) {
63135c04a7b8SAlexey Dobriyan 				FPT_scamInfo[match].id_string[k] =
63145c04a7b8SAlexey Dobriyan 				    p_id_string[k];
63151da177e4SLinus Torvalds 			}
63161da177e4SLinus Torvalds 
631747b5d69cSJames Bottomley  			FPT_scamInfo[match].state = ID_ASSIGNED;
63181da177e4SLinus Torvalds 
631947b5d69cSJames Bottomley  			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
63205c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].globalFlags |=
63215c04a7b8SAlexey Dobriyan 				    F_UPDATE_EEPROM;
63225c1b85e2SAlexey Dobriyan 			return match;
63231da177e4SLinus Torvalds 
63241da177e4SLinus Torvalds 		}
63251da177e4SLinus Torvalds 
63261da177e4SLinus Torvalds 		match--;
63271da177e4SLinus Torvalds 
63285c04a7b8SAlexey Dobriyan 		if (match == 0xFF) {
63291da177e4SLinus Torvalds 			if (p_id_string[0] & BIT(5))
63301da177e4SLinus Torvalds 				match = 7;
63311da177e4SLinus Torvalds 			else
63321da177e4SLinus Torvalds 				match = MAX_SCSI_TAR - 1;
63331da177e4SLinus Torvalds 		}
63341da177e4SLinus Torvalds 	}
63351da177e4SLinus Torvalds 
63365c04a7b8SAlexey Dobriyan 	if (p_id_string[0] & BIT(7)) {
63375c1b85e2SAlexey Dobriyan 		return CLR_PRIORITY;
63381da177e4SLinus Torvalds 	}
63391da177e4SLinus Torvalds 
63401da177e4SLinus Torvalds 	if (p_id_string[0] & BIT(5))
63411da177e4SLinus Torvalds 		i = 8;
63421da177e4SLinus Torvalds 	else
63431da177e4SLinus Torvalds 		i = MAX_SCSI_TAR;
63441da177e4SLinus Torvalds 
63455c04a7b8SAlexey Dobriyan 	if (((p_id_string[0] & 0x06) == 0x02)
63465c04a7b8SAlexey Dobriyan 	    || ((p_id_string[0] & 0x06) == 0x04))
6347db038cf8SAlexey Dobriyan 		match = p_id_string[1] & (unsigned char)0x1F;
63481da177e4SLinus Torvalds 	else
63491da177e4SLinus Torvalds 		match = 7;
63501da177e4SLinus Torvalds 
63515c04a7b8SAlexey Dobriyan 	while (i > 0) {
63521da177e4SLinus Torvalds 
63531da177e4SLinus Torvalds 		i--;
63541da177e4SLinus Torvalds 
63555c04a7b8SAlexey Dobriyan 		if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
63565c04a7b8SAlexey Dobriyan 			for (k = 0; k < ID_STRING_LENGTH; k++) {
63575c04a7b8SAlexey Dobriyan 				FPT_scamInfo[match].id_string[k] =
63585c04a7b8SAlexey Dobriyan 				    p_id_string[k];
63591da177e4SLinus Torvalds 			}
63601da177e4SLinus Torvalds 
636147b5d69cSJames Bottomley  			FPT_scamInfo[match].id_string[0] |= BIT(7);
636247b5d69cSJames Bottomley  			FPT_scamInfo[match].state = ID_ASSIGNED;
636347b5d69cSJames Bottomley  			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
63645c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].globalFlags |=
63655c04a7b8SAlexey Dobriyan 				    F_UPDATE_EEPROM;
63665c1b85e2SAlexey Dobriyan 			return match;
63671da177e4SLinus Torvalds 
63681da177e4SLinus Torvalds 		}
63691da177e4SLinus Torvalds 
63701da177e4SLinus Torvalds 		match--;
63711da177e4SLinus Torvalds 
63725c04a7b8SAlexey Dobriyan 		if (match == 0xFF) {
63731da177e4SLinus Torvalds 			if (p_id_string[0] & BIT(5))
63741da177e4SLinus Torvalds 				match = 7;
63751da177e4SLinus Torvalds 			else
63761da177e4SLinus Torvalds 				match = MAX_SCSI_TAR - 1;
63771da177e4SLinus Torvalds 		}
63781da177e4SLinus Torvalds 	}
63791da177e4SLinus Torvalds 
63805c1b85e2SAlexey Dobriyan 	return NO_ID_AVAIL;
63811da177e4SLinus Torvalds }
63821da177e4SLinus Torvalds 
63831da177e4SLinus Torvalds /*---------------------------------------------------------------------
63841da177e4SLinus Torvalds  *
638547b5d69cSJames Bottomley   * Function: FPT_scsavdi
63861da177e4SLinus Torvalds  *
63871da177e4SLinus Torvalds  * Description: Save off the device SCAM ID strings.
63881da177e4SLinus Torvalds  *
63891da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
63901da177e4SLinus Torvalds 
6391391e2f25SKhalid Aziz static void FPT_scsavdi(unsigned char p_card, u32 p_port)
63921da177e4SLinus Torvalds {
6393db038cf8SAlexey Dobriyan 	unsigned char i, k, max_id;
6394c823feebSAlexey Dobriyan 	unsigned short ee_data, sum_data;
63951da177e4SLinus Torvalds 
63961da177e4SLinus Torvalds 	sum_data = 0x0000;
63971da177e4SLinus Torvalds 
63985c04a7b8SAlexey Dobriyan 	for (i = 1; i < EE_SCAMBASE / 2; i++) {
639947b5d69cSJames Bottomley  		sum_data += FPT_utilEERead(p_port, i);
64001da177e4SLinus Torvalds 	}
64011da177e4SLinus Torvalds 
640247b5d69cSJames Bottomley  	FPT_utilEEWriteOnOff(p_port, 1);	/* Enable write access to the EEPROM */
64031da177e4SLinus Torvalds 
64041da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
64051da177e4SLinus Torvalds 		max_id = 0x08;
64061da177e4SLinus Torvalds 
64071da177e4SLinus Torvalds 	else
64081da177e4SLinus Torvalds 		max_id = 0x10;
64091da177e4SLinus Torvalds 
64105c04a7b8SAlexey Dobriyan 	for (i = 0; i < max_id; i++) {
64111da177e4SLinus Torvalds 
64125c04a7b8SAlexey Dobriyan 		for (k = 0; k < ID_STRING_LENGTH; k += 2) {
641347b5d69cSJames Bottomley  			ee_data = FPT_scamInfo[i].id_string[k + 1];
64141da177e4SLinus Torvalds 			ee_data <<= 8;
641547b5d69cSJames Bottomley  			ee_data |= FPT_scamInfo[i].id_string[k];
64161da177e4SLinus Torvalds 			sum_data += ee_data;
64175c04a7b8SAlexey Dobriyan 			FPT_utilEEWrite(p_port, ee_data,
64185c04a7b8SAlexey Dobriyan 					(unsigned short)((EE_SCAMBASE / 2) +
64195c04a7b8SAlexey Dobriyan 							 (unsigned short)(i *
64205c04a7b8SAlexey Dobriyan 									  ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
64211da177e4SLinus Torvalds 		}
64221da177e4SLinus Torvalds 	}
64231da177e4SLinus Torvalds 
642447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
642547b5d69cSJames Bottomley  	FPT_utilEEWriteOnOff(p_port, 0);	/* Turn off write access */
64261da177e4SLinus Torvalds }
64271da177e4SLinus Torvalds 
64281da177e4SLinus Torvalds /*---------------------------------------------------------------------
64291da177e4SLinus Torvalds  *
643047b5d69cSJames Bottomley   * Function: FPT_XbowInit
64311da177e4SLinus Torvalds  *
64321da177e4SLinus Torvalds  * Description: Setup the Xbow for normal operation.
64331da177e4SLinus Torvalds  *
64341da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
64351da177e4SLinus Torvalds 
6436391e2f25SKhalid Aziz static void FPT_XbowInit(u32 port, unsigned char ScamFlg)
64371da177e4SLinus Torvalds {
6438db038cf8SAlexey Dobriyan 	unsigned char i;
64391da177e4SLinus Torvalds 
64401da177e4SLinus Torvalds 	i = RD_HARPOON(port + hp_page_ctrl);
6441db038cf8SAlexey Dobriyan 	WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
64421da177e4SLinus Torvalds 
64431da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsireset, 0x00);
64441da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
64451da177e4SLinus Torvalds 
64465c04a7b8SAlexey Dobriyan 	WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
64471da177e4SLinus Torvalds 					 FIFO_CLR));
64481da177e4SLinus Torvalds 
64491da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsireset, SCSI_INI);
64501da177e4SLinus Torvalds 
64511da177e4SLinus Torvalds 	WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
64521da177e4SLinus Torvalds 
64531da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, 0x00);	/*  Clear any signals we might */
64541da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
64551da177e4SLinus Torvalds 
64561da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
64571da177e4SLinus Torvalds 
645847b5d69cSJames Bottomley  	FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
64591da177e4SLinus Torvalds 	    BUS_FREE | XFER_CNT_0 | AUTO_INT;
64601da177e4SLinus Torvalds 
64611da177e4SLinus Torvalds 	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
646247b5d69cSJames Bottomley  		FPT_default_intena |= SCAM_SEL;
64631da177e4SLinus Torvalds 
646447b5d69cSJames Bottomley  	WRW_HARPOON((port + hp_intena), FPT_default_intena);
64651da177e4SLinus Torvalds 
64661da177e4SLinus Torvalds 	WR_HARPOON(port + hp_seltimeout, TO_290ms);
64671da177e4SLinus Torvalds 
64681da177e4SLinus Torvalds 	/* Turn on SCSI_MODE8 for narrow cards to fix the
64691da177e4SLinus Torvalds 	   strapping issue with the DUAL CHANNEL card */
64701da177e4SLinus Torvalds 	if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
64711da177e4SLinus Torvalds 		WR_HARPOON(port + hp_addstat, SCSI_MODE8);
64721da177e4SLinus Torvalds 
64731da177e4SLinus Torvalds 	WR_HARPOON(port + hp_page_ctrl, i);
64741da177e4SLinus Torvalds 
64751da177e4SLinus Torvalds }
64761da177e4SLinus Torvalds 
64771da177e4SLinus Torvalds /*---------------------------------------------------------------------
64781da177e4SLinus Torvalds  *
647947b5d69cSJames Bottomley   * Function: FPT_BusMasterInit
64801da177e4SLinus Torvalds  *
64811da177e4SLinus Torvalds  * Description: Initialize the BusMaster for normal operations.
64821da177e4SLinus Torvalds  *
64831da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
64841da177e4SLinus Torvalds 
6485391e2f25SKhalid Aziz static void FPT_BusMasterInit(u32 p_port)
64861da177e4SLinus Torvalds {
64871da177e4SLinus Torvalds 
64881da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
64891da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
64901da177e4SLinus Torvalds 
64911da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
64921da177e4SLinus Torvalds 
64931da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
64941da177e4SLinus Torvalds 
64951da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
64961da177e4SLinus Torvalds 
64971da177e4SLinus Torvalds 	RD_HARPOON(p_port + hp_int_status);	/*Clear interrupts. */
64981da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
64991da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
65001da177e4SLinus Torvalds 					   ~SCATTER_EN));
65011da177e4SLinus Torvalds }
65021da177e4SLinus Torvalds 
65031da177e4SLinus Torvalds /*---------------------------------------------------------------------
65041da177e4SLinus Torvalds  *
650547b5d69cSJames Bottomley   * Function: FPT_DiagEEPROM
65061da177e4SLinus Torvalds  *
65071da177e4SLinus Torvalds  * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
65081da177e4SLinus Torvalds  *              necessary.
65091da177e4SLinus Torvalds  *
65101da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
65111da177e4SLinus Torvalds 
6512391e2f25SKhalid Aziz static void FPT_DiagEEPROM(u32 p_port)
65131da177e4SLinus Torvalds {
6514c823feebSAlexey Dobriyan 	unsigned short index, temp, max_wd_cnt;
65151da177e4SLinus Torvalds 
65161da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
65171da177e4SLinus Torvalds 		max_wd_cnt = EEPROM_WD_CNT;
65181da177e4SLinus Torvalds 	else
65191da177e4SLinus Torvalds 		max_wd_cnt = EEPROM_WD_CNT * 2;
65201da177e4SLinus Torvalds 
652147b5d69cSJames Bottomley  	temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
65221da177e4SLinus Torvalds 
65231da177e4SLinus Torvalds 	if (temp == 0x4641) {
65241da177e4SLinus Torvalds 
65251da177e4SLinus Torvalds 		for (index = 2; index < max_wd_cnt; index++) {
65261da177e4SLinus Torvalds 
652747b5d69cSJames Bottomley  			temp += FPT_utilEERead(p_port, index);
65281da177e4SLinus Torvalds 
65291da177e4SLinus Torvalds 		}
65301da177e4SLinus Torvalds 
653147b5d69cSJames Bottomley  		if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
65321da177e4SLinus Torvalds 
65331da177e4SLinus Torvalds 			return;	/*EEPROM is Okay so return now! */
65341da177e4SLinus Torvalds 		}
65351da177e4SLinus Torvalds 	}
65361da177e4SLinus Torvalds 
6537db038cf8SAlexey Dobriyan 	FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
65381da177e4SLinus Torvalds 
65391da177e4SLinus Torvalds 	for (index = 0; index < max_wd_cnt; index++) {
65401da177e4SLinus Torvalds 
654147b5d69cSJames Bottomley  		FPT_utilEEWrite(p_port, 0x0000, index);
65421da177e4SLinus Torvalds 	}
65431da177e4SLinus Torvalds 
65441da177e4SLinus Torvalds 	temp = 0;
65451da177e4SLinus Torvalds 
654647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
65471da177e4SLinus Torvalds 	temp += 0x4641;
654847b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
65491da177e4SLinus Torvalds 	temp += 0x3920;
655047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
65511da177e4SLinus Torvalds 	temp += 0x3033;
655247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
65531da177e4SLinus Torvalds 	temp += 0x2020;
655447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
65551da177e4SLinus Torvalds 	temp += 0x70D3;
655647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
65571da177e4SLinus Torvalds 	temp += 0x0010;
655847b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
65591da177e4SLinus Torvalds 	temp += 0x0003;
656047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
65611da177e4SLinus Torvalds 	temp += 0x0007;
65621da177e4SLinus Torvalds 
656347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
65641da177e4SLinus Torvalds 	temp += 0x0000;
656547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
65661da177e4SLinus Torvalds 	temp += 0x0000;
656747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
65681da177e4SLinus Torvalds 	temp += 0x0000;
65691da177e4SLinus Torvalds 
657047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
65711da177e4SLinus Torvalds 	temp += 0x4242;
657247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
65731da177e4SLinus Torvalds 	temp += 0x4242;
657447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
65751da177e4SLinus Torvalds 	temp += 0x4242;
657647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
65771da177e4SLinus Torvalds 	temp += 0x4242;
657847b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
65791da177e4SLinus Torvalds 	temp += 0x4242;
658047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
65811da177e4SLinus Torvalds 	temp += 0x4242;
658247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
65831da177e4SLinus Torvalds 	temp += 0x4242;
658447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
65851da177e4SLinus Torvalds 	temp += 0x4242;
65861da177e4SLinus Torvalds 
658747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x6C46, 64 / 2);	/*PRODUCT ID */
65881da177e4SLinus Torvalds 	temp += 0x6C46;
658947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x7361, 66 / 2);	/* FlashPoint LT   */
65901da177e4SLinus Torvalds 	temp += 0x7361;
659147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
65921da177e4SLinus Torvalds 	temp += 0x5068;
659347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
65941da177e4SLinus Torvalds 	temp += 0x696F;
659547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
65961da177e4SLinus Torvalds 	temp += 0x746E;
659747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
65981da177e4SLinus Torvalds 	temp += 0x4C20;
659947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
66001da177e4SLinus Torvalds 	temp += 0x2054;
660147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
66021da177e4SLinus Torvalds 	temp += 0x2020;
66031da177e4SLinus Torvalds 
66041da177e4SLinus Torvalds 	index = ((EE_SCAMBASE / 2) + (7 * 16));
660547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
66061da177e4SLinus Torvalds 	temp += (0x0700 + TYPE_CODE0);
66071da177e4SLinus Torvalds 	index++;
660847b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5542, index);	/*Vendor ID code */
66091da177e4SLinus Torvalds 	temp += 0x5542;		/* BUSLOGIC      */
66101da177e4SLinus Torvalds 	index++;
661147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4C53, index);
66121da177e4SLinus Torvalds 	temp += 0x4C53;
66131da177e4SLinus Torvalds 	index++;
661447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x474F, index);
66151da177e4SLinus Torvalds 	temp += 0x474F;
66161da177e4SLinus Torvalds 	index++;
661747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4349, index);
66181da177e4SLinus Torvalds 	temp += 0x4349;
66191da177e4SLinus Torvalds 	index++;
662047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5442, index);	/*Vendor unique code */
66211da177e4SLinus Torvalds 	temp += 0x5442;		/* BT- 930           */
66221da177e4SLinus Torvalds 	index++;
662347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x202D, index);
66241da177e4SLinus Torvalds 	temp += 0x202D;
66251da177e4SLinus Torvalds 	index++;
662647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3339, index);
66271da177e4SLinus Torvalds 	temp += 0x3339;
66281da177e4SLinus Torvalds 	index++;		/*Serial #          */
662947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2030, index);	/* 01234567         */
66301da177e4SLinus Torvalds 	temp += 0x2030;
66311da177e4SLinus Torvalds 	index++;
663247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5453, index);
66331da177e4SLinus Torvalds 	temp += 0x5453;
66341da177e4SLinus Torvalds 	index++;
663547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5645, index);
66361da177e4SLinus Torvalds 	temp += 0x5645;
66371da177e4SLinus Torvalds 	index++;
663847b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2045, index);
66391da177e4SLinus Torvalds 	temp += 0x2045;
66401da177e4SLinus Torvalds 	index++;
664147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x202F, index);
66421da177e4SLinus Torvalds 	temp += 0x202F;
66431da177e4SLinus Torvalds 	index++;
664447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4F4A, index);
66451da177e4SLinus Torvalds 	temp += 0x4F4A;
66461da177e4SLinus Torvalds 	index++;
664747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x204E, index);
66481da177e4SLinus Torvalds 	temp += 0x204E;
66491da177e4SLinus Torvalds 	index++;
665047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3539, index);
66511da177e4SLinus Torvalds 	temp += 0x3539;
66521da177e4SLinus Torvalds 
665347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
66541da177e4SLinus Torvalds 
6655db038cf8SAlexey Dobriyan 	FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
66561da177e4SLinus Torvalds 
66571da177e4SLinus Torvalds }
66581da177e4SLinus Torvalds 
66591da177e4SLinus Torvalds /*---------------------------------------------------------------------
66601da177e4SLinus Torvalds  *
66611da177e4SLinus Torvalds  * Function: Queue Search Select
66621da177e4SLinus Torvalds  *
66631da177e4SLinus Torvalds  * Description: Try to find a new command to execute.
66641da177e4SLinus Torvalds  *
66651da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
66661da177e4SLinus Torvalds 
66675c04a7b8SAlexey Dobriyan static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
66685c04a7b8SAlexey Dobriyan 				  unsigned char p_card)
66691da177e4SLinus Torvalds {
6670db038cf8SAlexey Dobriyan 	unsigned char scan_ptr, lun;
6671f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
667269eb2ea4SAlexey Dobriyan 	struct sccb *pOldSccb;
66731da177e4SLinus Torvalds 
66741da177e4SLinus Torvalds 	scan_ptr = pCurrCard->scanIndex;
66755c04a7b8SAlexey Dobriyan 	do {
667647b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
66771da177e4SLinus Torvalds 		if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
66785c04a7b8SAlexey Dobriyan 		    ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
66795c04a7b8SAlexey Dobriyan 		     TAG_Q_TRYING)) {
66805c04a7b8SAlexey Dobriyan 			if (currTar_Info->TarSelQ_Cnt != 0) {
66811da177e4SLinus Torvalds 
66821da177e4SLinus Torvalds 				scan_ptr++;
66831da177e4SLinus Torvalds 				if (scan_ptr == MAX_SCSI_TAR)
66841da177e4SLinus Torvalds 					scan_ptr = 0;
66851da177e4SLinus Torvalds 
66865c04a7b8SAlexey Dobriyan 				for (lun = 0; lun < MAX_LUN; lun++) {
66875c04a7b8SAlexey Dobriyan 					if (currTar_Info->TarLUNBusy[lun] == 0) {
66881da177e4SLinus Torvalds 
66895c04a7b8SAlexey Dobriyan 						pCurrCard->currentSCCB =
66905c04a7b8SAlexey Dobriyan 						    currTar_Info->TarSelQ_Head;
66911da177e4SLinus Torvalds 						pOldSccb = NULL;
66921da177e4SLinus Torvalds 
66935c04a7b8SAlexey Dobriyan 						while ((pCurrCard->
66945c04a7b8SAlexey Dobriyan 							currentSCCB != NULL)
66955c04a7b8SAlexey Dobriyan 						       && (lun !=
66965c04a7b8SAlexey Dobriyan 							   pCurrCard->
66975c04a7b8SAlexey Dobriyan 							   currentSCCB->Lun)) {
66985c04a7b8SAlexey Dobriyan 							pOldSccb =
66995c04a7b8SAlexey Dobriyan 							    pCurrCard->
67005c04a7b8SAlexey Dobriyan 							    currentSCCB;
67015c04a7b8SAlexey Dobriyan 							pCurrCard->currentSCCB =
67025c04a7b8SAlexey Dobriyan 							    (struct sccb
67035c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
67045c04a7b8SAlexey Dobriyan 								currentSCCB)->
67051da177e4SLinus Torvalds 							    Sccb_forwardlink;
67061da177e4SLinus Torvalds 						}
67075c04a7b8SAlexey Dobriyan 						if (pCurrCard->currentSCCB ==
67085c04a7b8SAlexey Dobriyan 						    NULL)
67091da177e4SLinus Torvalds 							continue;
67105c04a7b8SAlexey Dobriyan 						if (pOldSccb != NULL) {
67115c04a7b8SAlexey Dobriyan 							pOldSccb->
67125c04a7b8SAlexey Dobriyan 							    Sccb_forwardlink =
67135c04a7b8SAlexey Dobriyan 							    (struct sccb
67145c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
67155c04a7b8SAlexey Dobriyan 								currentSCCB)->
67161da177e4SLinus Torvalds 							    Sccb_forwardlink;
67175c04a7b8SAlexey Dobriyan 							pOldSccb->
67185c04a7b8SAlexey Dobriyan 							    Sccb_backlink =
67195c04a7b8SAlexey Dobriyan 							    (struct sccb
67205c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
67215c04a7b8SAlexey Dobriyan 								currentSCCB)->
67221da177e4SLinus Torvalds 							    Sccb_backlink;
67235c04a7b8SAlexey Dobriyan 							currTar_Info->
67245c04a7b8SAlexey Dobriyan 							    TarSelQ_Cnt--;
67255c04a7b8SAlexey Dobriyan 						} else {
67265c04a7b8SAlexey Dobriyan 							currTar_Info->
67275c04a7b8SAlexey Dobriyan 							    TarSelQ_Head =
67285c04a7b8SAlexey Dobriyan 							    (struct sccb
67295c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
67305c04a7b8SAlexey Dobriyan 								currentSCCB)->
67315c04a7b8SAlexey Dobriyan 							    Sccb_forwardlink;
67321da177e4SLinus Torvalds 
67335c04a7b8SAlexey Dobriyan 							if (currTar_Info->
67345c04a7b8SAlexey Dobriyan 							    TarSelQ_Head ==
67355c04a7b8SAlexey Dobriyan 							    NULL) {
67365c04a7b8SAlexey Dobriyan 								currTar_Info->
67375c04a7b8SAlexey Dobriyan 								    TarSelQ_Tail
67385c04a7b8SAlexey Dobriyan 								    = NULL;
67395c04a7b8SAlexey Dobriyan 								currTar_Info->
67405c04a7b8SAlexey Dobriyan 								    TarSelQ_Cnt
67415c04a7b8SAlexey Dobriyan 								    = 0;
67425c04a7b8SAlexey Dobriyan 							} else {
67435c04a7b8SAlexey Dobriyan 								currTar_Info->
67445c04a7b8SAlexey Dobriyan 								    TarSelQ_Cnt--;
67455c04a7b8SAlexey Dobriyan 								currTar_Info->
67465c04a7b8SAlexey Dobriyan 								    TarSelQ_Head->
67475c04a7b8SAlexey Dobriyan 								    Sccb_backlink
67485c04a7b8SAlexey Dobriyan 								    =
67495c04a7b8SAlexey Dobriyan 								    (struct sccb
67505c04a7b8SAlexey Dobriyan 								     *)NULL;
67511da177e4SLinus Torvalds 							}
67521da177e4SLinus Torvalds 						}
67531da177e4SLinus Torvalds 						pCurrCard->scanIndex = scan_ptr;
67541da177e4SLinus Torvalds 
67555c04a7b8SAlexey Dobriyan 						pCurrCard->globalFlags |=
67565c04a7b8SAlexey Dobriyan 						    F_NEW_SCCB_CMD;
67571da177e4SLinus Torvalds 
67581da177e4SLinus Torvalds 						break;
67591da177e4SLinus Torvalds 					}
67601da177e4SLinus Torvalds 				}
67611da177e4SLinus Torvalds 			}
67621da177e4SLinus Torvalds 
67635c04a7b8SAlexey Dobriyan 			else {
67641da177e4SLinus Torvalds 				scan_ptr++;
67651da177e4SLinus Torvalds 				if (scan_ptr == MAX_SCSI_TAR) {
67661da177e4SLinus Torvalds 					scan_ptr = 0;
67671da177e4SLinus Torvalds 				}
67681da177e4SLinus Torvalds 			}
67691da177e4SLinus Torvalds 
67705c04a7b8SAlexey Dobriyan 		} else {
67711da177e4SLinus Torvalds 			if ((currTar_Info->TarSelQ_Cnt != 0) &&
67725c04a7b8SAlexey Dobriyan 			    (currTar_Info->TarLUNBusy[0] == 0)) {
67731da177e4SLinus Torvalds 
67745c04a7b8SAlexey Dobriyan 				pCurrCard->currentSCCB =
67755c04a7b8SAlexey Dobriyan 				    currTar_Info->TarSelQ_Head;
67761da177e4SLinus Torvalds 
67775c04a7b8SAlexey Dobriyan 				currTar_Info->TarSelQ_Head =
67785c04a7b8SAlexey Dobriyan 				    (struct sccb *)(pCurrCard->currentSCCB)->
67795c04a7b8SAlexey Dobriyan 				    Sccb_forwardlink;
67801da177e4SLinus Torvalds 
67815c04a7b8SAlexey Dobriyan 				if (currTar_Info->TarSelQ_Head == NULL) {
67821da177e4SLinus Torvalds 					currTar_Info->TarSelQ_Tail = NULL;
67831da177e4SLinus Torvalds 					currTar_Info->TarSelQ_Cnt = 0;
67845c04a7b8SAlexey Dobriyan 				} else {
67851da177e4SLinus Torvalds 					currTar_Info->TarSelQ_Cnt--;
67865c04a7b8SAlexey Dobriyan 					currTar_Info->TarSelQ_Head->
67875c04a7b8SAlexey Dobriyan 					    Sccb_backlink = (struct sccb *)NULL;
67881da177e4SLinus Torvalds 				}
67891da177e4SLinus Torvalds 
67901da177e4SLinus Torvalds 				scan_ptr++;
67911da177e4SLinus Torvalds 				if (scan_ptr == MAX_SCSI_TAR)
67921da177e4SLinus Torvalds 					scan_ptr = 0;
67931da177e4SLinus Torvalds 
67941da177e4SLinus Torvalds 				pCurrCard->scanIndex = scan_ptr;
67951da177e4SLinus Torvalds 
67961da177e4SLinus Torvalds 				pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
67971da177e4SLinus Torvalds 
67981da177e4SLinus Torvalds 				break;
67991da177e4SLinus Torvalds 			}
68001da177e4SLinus Torvalds 
68015c04a7b8SAlexey Dobriyan 			else {
68021da177e4SLinus Torvalds 				scan_ptr++;
68035c04a7b8SAlexey Dobriyan 				if (scan_ptr == MAX_SCSI_TAR) {
68041da177e4SLinus Torvalds 					scan_ptr = 0;
68051da177e4SLinus Torvalds 				}
68061da177e4SLinus Torvalds 			}
68071da177e4SLinus Torvalds 		}
68081da177e4SLinus Torvalds 	} while (scan_ptr != pCurrCard->scanIndex);
68091da177e4SLinus Torvalds }
68101da177e4SLinus Torvalds 
68111da177e4SLinus Torvalds /*---------------------------------------------------------------------
68121da177e4SLinus Torvalds  *
68131da177e4SLinus Torvalds  * Function: Queue Select Fail
68141da177e4SLinus Torvalds  *
68151da177e4SLinus Torvalds  * Description: Add the current SCCB to the head of the Queue.
68161da177e4SLinus Torvalds  *
68171da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
68181da177e4SLinus Torvalds 
68195c04a7b8SAlexey Dobriyan static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
68205c04a7b8SAlexey Dobriyan 				unsigned char p_card)
68211da177e4SLinus Torvalds {
6822db038cf8SAlexey Dobriyan 	unsigned char thisTarg;
6823f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
68241da177e4SLinus Torvalds 
68255c04a7b8SAlexey Dobriyan 	if (pCurrCard->currentSCCB != NULL) {
68265c04a7b8SAlexey Dobriyan 		thisTarg =
68275c04a7b8SAlexey Dobriyan 		    (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
68285c04a7b8SAlexey Dobriyan 				    TargID);
682947b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
68301da177e4SLinus Torvalds 
683169eb2ea4SAlexey Dobriyan 		pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
68321da177e4SLinus Torvalds 
68335c04a7b8SAlexey Dobriyan 		pCurrCard->currentSCCB->Sccb_forwardlink =
68345c04a7b8SAlexey Dobriyan 		    currTar_Info->TarSelQ_Head;
68351da177e4SLinus Torvalds 
68365c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarSelQ_Cnt == 0) {
68371da177e4SLinus Torvalds 			currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
68381da177e4SLinus Torvalds 		}
68391da177e4SLinus Torvalds 
68405c04a7b8SAlexey Dobriyan 		else {
68415c04a7b8SAlexey Dobriyan 			currTar_Info->TarSelQ_Head->Sccb_backlink =
68425c04a7b8SAlexey Dobriyan 			    pCurrCard->currentSCCB;
68431da177e4SLinus Torvalds 		}
68441da177e4SLinus Torvalds 
68451da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
68461da177e4SLinus Torvalds 
68471da177e4SLinus Torvalds 		pCurrCard->currentSCCB = NULL;
68481da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Cnt++;
68491da177e4SLinus Torvalds 	}
68501da177e4SLinus Torvalds }
68515c04a7b8SAlexey Dobriyan 
68521da177e4SLinus Torvalds /*---------------------------------------------------------------------
68531da177e4SLinus Torvalds  *
68541da177e4SLinus Torvalds  * Function: Queue Command Complete
68551da177e4SLinus Torvalds  *
68561da177e4SLinus Torvalds  * Description: Call the callback function with the current SCCB.
68571da177e4SLinus Torvalds  *
68581da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
68591da177e4SLinus Torvalds 
68605c04a7b8SAlexey Dobriyan static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
68615c04a7b8SAlexey Dobriyan 				 struct sccb *p_sccb, unsigned char p_card)
68621da177e4SLinus Torvalds {
68631da177e4SLinus Torvalds 
6864db038cf8SAlexey Dobriyan 	unsigned char i, SCSIcmd;
68651da177e4SLinus Torvalds 	CALL_BK_FN callback;
6866f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
68671da177e4SLinus Torvalds 
68681da177e4SLinus Torvalds 	SCSIcmd = p_sccb->Cdb[0];
68691da177e4SLinus Torvalds 
68701da177e4SLinus Torvalds 	if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
68711da177e4SLinus Torvalds 
68725c04a7b8SAlexey Dobriyan 		if ((p_sccb->
68735c04a7b8SAlexey Dobriyan 		     ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
68745c04a7b8SAlexey Dobriyan 		    && (p_sccb->HostStatus == SCCB_COMPLETE)
68755c04a7b8SAlexey Dobriyan 		    && (p_sccb->TargetStatus != SSCHECK))
68761da177e4SLinus Torvalds 
68771da177e4SLinus Torvalds 			if ((SCSIcmd == SCSI_READ) ||
68781da177e4SLinus Torvalds 			    (SCSIcmd == SCSI_WRITE) ||
68791da177e4SLinus Torvalds 			    (SCSIcmd == SCSI_READ_EXTENDED) ||
68801da177e4SLinus Torvalds 			    (SCSIcmd == SCSI_WRITE_EXTENDED) ||
68811da177e4SLinus Torvalds 			    (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
68821da177e4SLinus Torvalds 			    (SCSIcmd == SCSI_START_STOP_UNIT) ||
68831da177e4SLinus Torvalds 			    (pCurrCard->globalFlags & F_NO_FILTER)
68841da177e4SLinus Torvalds 			    )
68851da177e4SLinus Torvalds 				p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
68861da177e4SLinus Torvalds 	}
68871da177e4SLinus Torvalds 
68885c04a7b8SAlexey Dobriyan 	if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
68891da177e4SLinus Torvalds 		if (p_sccb->HostStatus || p_sccb->TargetStatus)
68901da177e4SLinus Torvalds 			p_sccb->SccbStatus = SCCB_ERROR;
68911da177e4SLinus Torvalds 		else
68921da177e4SLinus Torvalds 			p_sccb->SccbStatus = SCCB_SUCCESS;
68931da177e4SLinus Torvalds 	}
68941da177e4SLinus Torvalds 
68951da177e4SLinus Torvalds 	if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
68961da177e4SLinus Torvalds 
68971da177e4SLinus Torvalds 		p_sccb->CdbLength = p_sccb->Save_CdbLen;
68981da177e4SLinus Torvalds 		for (i = 0; i < 6; i++) {
68991da177e4SLinus Torvalds 			p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
69001da177e4SLinus Torvalds 		}
69011da177e4SLinus Torvalds 	}
69021da177e4SLinus Torvalds 
69031da177e4SLinus Torvalds 	if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
69041da177e4SLinus Torvalds 	    (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
69051da177e4SLinus Torvalds 
690647b5d69cSJames Bottomley  		FPT_utilUpdateResidual(p_sccb);
69071da177e4SLinus Torvalds 	}
69081da177e4SLinus Torvalds 
69091da177e4SLinus Torvalds 	pCurrCard->cmdCounter--;
69101da177e4SLinus Torvalds 	if (!pCurrCard->cmdCounter) {
69111da177e4SLinus Torvalds 
69121da177e4SLinus Torvalds 		if (pCurrCard->globalFlags & F_GREEN_PC) {
69135c04a7b8SAlexey Dobriyan 			WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
69145c04a7b8SAlexey Dobriyan 				   (PWR_DWN | CLKCTRL_DEFAULT));
69151da177e4SLinus Torvalds 			WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
69161da177e4SLinus Torvalds 		}
69171da177e4SLinus Torvalds 
69181da177e4SLinus Torvalds 		WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
69195c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
69205c04a7b8SAlexey Dobriyan 			    ~SCCB_MGR_ACTIVE));
69211da177e4SLinus Torvalds 
69221da177e4SLinus Torvalds 	}
69231da177e4SLinus Torvalds 
69245c04a7b8SAlexey Dobriyan 	if (pCurrCard->discQCount != 0) {
692547b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
69261da177e4SLinus Torvalds 		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
69275c04a7b8SAlexey Dobriyan 		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
69285c04a7b8SAlexey Dobriyan 		      TAG_Q_TRYING))) {
69291da177e4SLinus Torvalds 			pCurrCard->discQCount--;
69305c04a7b8SAlexey Dobriyan 			pCurrCard->discQ_Tbl[currTar_Info->
69315c04a7b8SAlexey Dobriyan 					     LunDiscQ_Idx[p_sccb->Lun]] = NULL;
69325c04a7b8SAlexey Dobriyan 		} else {
69335c04a7b8SAlexey Dobriyan 			if (p_sccb->Sccb_tag) {
69341da177e4SLinus Torvalds 				pCurrCard->discQCount--;
69351da177e4SLinus Torvalds 				pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
69365c04a7b8SAlexey Dobriyan 			} else {
69371da177e4SLinus Torvalds 				pCurrCard->discQCount--;
69385c04a7b8SAlexey Dobriyan 				pCurrCard->discQ_Tbl[currTar_Info->
69395c04a7b8SAlexey Dobriyan 						     LunDiscQ_Idx[0]] = NULL;
69401da177e4SLinus Torvalds 			}
69411da177e4SLinus Torvalds 		}
69421da177e4SLinus Torvalds 
69431da177e4SLinus Torvalds 	}
69441da177e4SLinus Torvalds 
69451da177e4SLinus Torvalds 	callback = (CALL_BK_FN) p_sccb->SccbCallback;
69461da177e4SLinus Torvalds 	callback(p_sccb);
69471da177e4SLinus Torvalds 	pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
69481da177e4SLinus Torvalds 	pCurrCard->currentSCCB = NULL;
69491da177e4SLinus Torvalds }
69501da177e4SLinus Torvalds 
69511da177e4SLinus Torvalds /*---------------------------------------------------------------------
69521da177e4SLinus Torvalds  *
69531da177e4SLinus Torvalds  * Function: Queue Disconnect
69541da177e4SLinus Torvalds  *
69551da177e4SLinus Torvalds  * Description: Add SCCB to our disconnect array.
69561da177e4SLinus Torvalds  *
69571da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
695869eb2ea4SAlexey Dobriyan static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
69591da177e4SLinus Torvalds {
6960f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
69611da177e4SLinus Torvalds 
696247b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
69631da177e4SLinus Torvalds 
696447b5d69cSJames Bottomley  	if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
69655c04a7b8SAlexey Dobriyan 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
69665c04a7b8SAlexey Dobriyan 		FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
69675c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[p_sccb->Lun]] =
69685c04a7b8SAlexey Dobriyan 		    p_sccb;
69695c04a7b8SAlexey Dobriyan 	} else {
69705c04a7b8SAlexey Dobriyan 		if (p_sccb->Sccb_tag) {
69715c04a7b8SAlexey Dobriyan 			FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
69725c04a7b8SAlexey Dobriyan 			    p_sccb;
69735c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
69745c04a7b8SAlexey Dobriyan 			    0;
697547b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
69765c04a7b8SAlexey Dobriyan 		} else {
69775c04a7b8SAlexey Dobriyan 			FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
69785c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = p_sccb;
69791da177e4SLinus Torvalds 		}
69801da177e4SLinus Torvalds 	}
698147b5d69cSJames Bottomley  	FPT_BL_Card[p_card].currentSCCB = NULL;
69821da177e4SLinus Torvalds }
69831da177e4SLinus Torvalds 
69841da177e4SLinus Torvalds /*---------------------------------------------------------------------
69851da177e4SLinus Torvalds  *
69861da177e4SLinus Torvalds  * Function: Queue Flush SCCB
69871da177e4SLinus Torvalds  *
69881da177e4SLinus Torvalds  * Description: Flush all SCCB's back to the host driver for this target.
69891da177e4SLinus Torvalds  *
69901da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
69911da177e4SLinus Torvalds 
6992db038cf8SAlexey Dobriyan static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
69931da177e4SLinus Torvalds {
6994db038cf8SAlexey Dobriyan 	unsigned char qtag, thisTarg;
699569eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
6996f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
69971da177e4SLinus Torvalds 
699847b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
69995c04a7b8SAlexey Dobriyan 	if (currSCCB != NULL) {
7000db038cf8SAlexey Dobriyan 		thisTarg = (unsigned char)currSCCB->TargID;
700147b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
70021da177e4SLinus Torvalds 
70031da177e4SLinus Torvalds 		for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
70041da177e4SLinus Torvalds 
700547b5d69cSJames Bottomley  			if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
70065c04a7b8SAlexey Dobriyan 			    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
70075c04a7b8SAlexey Dobriyan 			     thisTarg)) {
70081da177e4SLinus Torvalds 
70095c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].discQ_Tbl[qtag]->
70105c04a7b8SAlexey Dobriyan 				    HostStatus = (unsigned char)error_code;
70111da177e4SLinus Torvalds 
70125c04a7b8SAlexey Dobriyan 				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
70135c04a7b8SAlexey Dobriyan 						     FPT_BL_Card[p_card].
70145c04a7b8SAlexey Dobriyan 						     discQ_Tbl[qtag], p_card);
70151da177e4SLinus Torvalds 
701647b5d69cSJames Bottomley  				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
70171da177e4SLinus Torvalds 				currTar_Info->TarTagQ_Cnt--;
70181da177e4SLinus Torvalds 
70191da177e4SLinus Torvalds 			}
70201da177e4SLinus Torvalds 		}
70211da177e4SLinus Torvalds 	}
70221da177e4SLinus Torvalds 
70231da177e4SLinus Torvalds }
70241da177e4SLinus Torvalds 
70251da177e4SLinus Torvalds /*---------------------------------------------------------------------
70261da177e4SLinus Torvalds  *
70271da177e4SLinus Torvalds  * Function: Queue Flush Target SCCB
70281da177e4SLinus Torvalds  *
70291da177e4SLinus Torvalds  * Description: Flush all SCCB's back to the host driver for this target.
70301da177e4SLinus Torvalds  *
70311da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
70321da177e4SLinus Torvalds 
7033db038cf8SAlexey Dobriyan static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7034db038cf8SAlexey Dobriyan 				   unsigned char error_code)
70351da177e4SLinus Torvalds {
7036db038cf8SAlexey Dobriyan 	unsigned char qtag;
7037f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
70381da177e4SLinus Torvalds 
703947b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
70401da177e4SLinus Torvalds 
70411da177e4SLinus Torvalds 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
70421da177e4SLinus Torvalds 
704347b5d69cSJames Bottomley  		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
70445c04a7b8SAlexey Dobriyan 		    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
70451da177e4SLinus Torvalds 
70465c04a7b8SAlexey Dobriyan 			FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
70475c04a7b8SAlexey Dobriyan 			    (unsigned char)error_code;
70481da177e4SLinus Torvalds 
70495c04a7b8SAlexey Dobriyan 			FPT_queueCmdComplete(&FPT_BL_Card[p_card],
70505c04a7b8SAlexey Dobriyan 					     FPT_BL_Card[p_card].
70515c04a7b8SAlexey Dobriyan 					     discQ_Tbl[qtag], p_card);
70521da177e4SLinus Torvalds 
705347b5d69cSJames Bottomley  			FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
70541da177e4SLinus Torvalds 			currTar_Info->TarTagQ_Cnt--;
70551da177e4SLinus Torvalds 
70561da177e4SLinus Torvalds 		}
70571da177e4SLinus Torvalds 	}
70581da177e4SLinus Torvalds 
70591da177e4SLinus Torvalds }
70601da177e4SLinus Torvalds 
706169eb2ea4SAlexey Dobriyan static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
70621da177e4SLinus Torvalds {
7063f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
706447b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
70651da177e4SLinus Torvalds 
70661da177e4SLinus Torvalds 	p_SCCB->Sccb_forwardlink = NULL;
70671da177e4SLinus Torvalds 
70681da177e4SLinus Torvalds 	p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
70691da177e4SLinus Torvalds 
70701da177e4SLinus Torvalds 	if (currTar_Info->TarSelQ_Cnt == 0) {
70711da177e4SLinus Torvalds 
70721da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Head = p_SCCB;
70731da177e4SLinus Torvalds 	}
70741da177e4SLinus Torvalds 
70751da177e4SLinus Torvalds 	else {
70761da177e4SLinus Torvalds 
70771da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
70781da177e4SLinus Torvalds 	}
70791da177e4SLinus Torvalds 
70801da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Tail = p_SCCB;
70811da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Cnt++;
70821da177e4SLinus Torvalds }
70831da177e4SLinus Torvalds 
70841da177e4SLinus Torvalds /*---------------------------------------------------------------------
70851da177e4SLinus Torvalds  *
70861da177e4SLinus Torvalds  * Function: Queue Find SCCB
70871da177e4SLinus Torvalds  *
70881da177e4SLinus Torvalds  * Description: Search the target select Queue for this SCCB, and
70891da177e4SLinus Torvalds  *              remove it if found.
70901da177e4SLinus Torvalds  *
70911da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
70921da177e4SLinus Torvalds 
70935c04a7b8SAlexey Dobriyan static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
70945c04a7b8SAlexey Dobriyan 				       unsigned char p_card)
70951da177e4SLinus Torvalds {
709669eb2ea4SAlexey Dobriyan 	struct sccb *q_ptr;
7097f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
70981da177e4SLinus Torvalds 
709947b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
71001da177e4SLinus Torvalds 
71011da177e4SLinus Torvalds 	q_ptr = currTar_Info->TarSelQ_Head;
71021da177e4SLinus Torvalds 
71031da177e4SLinus Torvalds 	while (q_ptr != NULL) {
71041da177e4SLinus Torvalds 
71051da177e4SLinus Torvalds 		if (q_ptr == p_SCCB) {
71061da177e4SLinus Torvalds 
71071da177e4SLinus Torvalds 			if (currTar_Info->TarSelQ_Head == q_ptr) {
71081da177e4SLinus Torvalds 
71095c04a7b8SAlexey Dobriyan 				currTar_Info->TarSelQ_Head =
71105c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_forwardlink;
71111da177e4SLinus Torvalds 			}
71121da177e4SLinus Torvalds 
71131da177e4SLinus Torvalds 			if (currTar_Info->TarSelQ_Tail == q_ptr) {
71141da177e4SLinus Torvalds 
71155c04a7b8SAlexey Dobriyan 				currTar_Info->TarSelQ_Tail =
71165c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_backlink;
71171da177e4SLinus Torvalds 			}
71181da177e4SLinus Torvalds 
71191da177e4SLinus Torvalds 			if (q_ptr->Sccb_forwardlink != NULL) {
71205c04a7b8SAlexey Dobriyan 				q_ptr->Sccb_forwardlink->Sccb_backlink =
71215c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_backlink;
71221da177e4SLinus Torvalds 			}
71231da177e4SLinus Torvalds 
71241da177e4SLinus Torvalds 			if (q_ptr->Sccb_backlink != NULL) {
71255c04a7b8SAlexey Dobriyan 				q_ptr->Sccb_backlink->Sccb_forwardlink =
71265c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_forwardlink;
71271da177e4SLinus Torvalds 			}
71281da177e4SLinus Torvalds 
71291da177e4SLinus Torvalds 			currTar_Info->TarSelQ_Cnt--;
71301da177e4SLinus Torvalds 
71315c1b85e2SAlexey Dobriyan 			return 1;
71321da177e4SLinus Torvalds 		}
71331da177e4SLinus Torvalds 
71341da177e4SLinus Torvalds 		else {
71351da177e4SLinus Torvalds 			q_ptr = q_ptr->Sccb_forwardlink;
71361da177e4SLinus Torvalds 		}
71371da177e4SLinus Torvalds 	}
71381da177e4SLinus Torvalds 
71395c1b85e2SAlexey Dobriyan 	return 0;
71401da177e4SLinus Torvalds 
71411da177e4SLinus Torvalds }
71421da177e4SLinus Torvalds 
71431da177e4SLinus Torvalds /*---------------------------------------------------------------------
71441da177e4SLinus Torvalds  *
71451da177e4SLinus Torvalds  * Function: Utility Update Residual Count
71461da177e4SLinus Torvalds  *
71471da177e4SLinus Torvalds  * Description: Update the XferCnt to the remaining byte count.
71481da177e4SLinus Torvalds  *              If we transferred all the data then just write zero.
71491da177e4SLinus Torvalds  *              If Non-SG transfer then report Total Cnt - Actual Transfer
71501da177e4SLinus Torvalds  *              Cnt.  For SG transfers add the count fields of all
71511da177e4SLinus Torvalds  *              remaining SG elements, as well as any partial remaining
71521da177e4SLinus Torvalds  *              element.
71531da177e4SLinus Torvalds  *
71541da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
71551da177e4SLinus Torvalds 
715669eb2ea4SAlexey Dobriyan static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
71571da177e4SLinus Torvalds {
7158d63a4cccSAlexey Dobriyan 	unsigned long partial_cnt;
7159ce793215SAlexey Dobriyan 	unsigned int sg_index;
7160391e2f25SKhalid Aziz 	struct blogic_sg_seg *segp;
71611da177e4SLinus Torvalds 
71621da177e4SLinus Torvalds 	if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
71631da177e4SLinus Torvalds 
71641da177e4SLinus Torvalds 		p_SCCB->DataLength = 0x0000;
71651da177e4SLinus Torvalds 	}
71661da177e4SLinus Torvalds 
71671da177e4SLinus Torvalds 	else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
71681da177e4SLinus Torvalds 
71691da177e4SLinus Torvalds 		partial_cnt = 0x0000;
71701da177e4SLinus Torvalds 
71711da177e4SLinus Torvalds 		sg_index = p_SCCB->Sccb_sgseg;
71721da177e4SLinus Torvalds 
71731da177e4SLinus Torvalds 
71741da177e4SLinus Torvalds 		if (p_SCCB->Sccb_SGoffset) {
71751da177e4SLinus Torvalds 
71761da177e4SLinus Torvalds 			partial_cnt = p_SCCB->Sccb_SGoffset;
71771da177e4SLinus Torvalds 			sg_index++;
71781da177e4SLinus Torvalds 		}
71791da177e4SLinus Torvalds 
71805c04a7b8SAlexey Dobriyan 		while (((unsigned long)sg_index *
71815c04a7b8SAlexey Dobriyan 			(unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
7182391e2f25SKhalid Aziz 			segp = (struct blogic_sg_seg *)(p_SCCB->DataPointer) +
7183391e2f25SKhalid Aziz 					(sg_index * 2);
7184391e2f25SKhalid Aziz 			partial_cnt += segp->segbytes;
71851da177e4SLinus Torvalds 			sg_index++;
71861da177e4SLinus Torvalds 		}
71871da177e4SLinus Torvalds 
71881da177e4SLinus Torvalds 		p_SCCB->DataLength = partial_cnt;
71891da177e4SLinus Torvalds 	}
71901da177e4SLinus Torvalds 
71911da177e4SLinus Torvalds 	else {
71921da177e4SLinus Torvalds 
71931da177e4SLinus Torvalds 		p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
71941da177e4SLinus Torvalds 	}
71951da177e4SLinus Torvalds }
71961da177e4SLinus Torvalds 
71971da177e4SLinus Torvalds /*---------------------------------------------------------------------
71981da177e4SLinus Torvalds  *
71991da177e4SLinus Torvalds  * Function: Wait 1 Second
72001da177e4SLinus Torvalds  *
72011da177e4SLinus Torvalds  * Description: Wait for 1 second.
72021da177e4SLinus Torvalds  *
72031da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
72041da177e4SLinus Torvalds 
7205391e2f25SKhalid Aziz static void FPT_Wait1Second(u32 p_port)
72061da177e4SLinus Torvalds {
7207db038cf8SAlexey Dobriyan 	unsigned char i;
72081da177e4SLinus Torvalds 
72091da177e4SLinus Torvalds 	for (i = 0; i < 4; i++) {
72101da177e4SLinus Torvalds 
721147b5d69cSJames Bottomley  		FPT_Wait(p_port, TO_250ms);
72121da177e4SLinus Torvalds 
72131da177e4SLinus Torvalds 		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
72141da177e4SLinus Torvalds 			break;
72151da177e4SLinus Torvalds 
72161da177e4SLinus Torvalds 		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
72171da177e4SLinus Torvalds 			break;
72181da177e4SLinus Torvalds 	}
72191da177e4SLinus Torvalds }
72201da177e4SLinus Torvalds 
72211da177e4SLinus Torvalds /*---------------------------------------------------------------------
72221da177e4SLinus Torvalds  *
722347b5d69cSJames Bottomley   * Function: FPT_Wait
72241da177e4SLinus Torvalds  *
72251da177e4SLinus Torvalds  * Description: Wait the desired delay.
72261da177e4SLinus Torvalds  *
72271da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
72281da177e4SLinus Torvalds 
7229391e2f25SKhalid Aziz static void FPT_Wait(u32 p_port, unsigned char p_delay)
72301da177e4SLinus Torvalds {
7231db038cf8SAlexey Dobriyan 	unsigned char old_timer;
7232db038cf8SAlexey Dobriyan 	unsigned char green_flag;
72331da177e4SLinus Torvalds 
72341da177e4SLinus Torvalds 	old_timer = RD_HARPOON(p_port + hp_seltimeout);
72351da177e4SLinus Torvalds 
72361da177e4SLinus Torvalds 	green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
72371da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
72381da177e4SLinus Torvalds 
72391da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, p_delay);
72401da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
724147b5d69cSJames Bottomley  	WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
72421da177e4SLinus Torvalds 
72431da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0,
72441da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
72451da177e4SLinus Torvalds 
72461da177e4SLinus Torvalds 	while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
72471da177e4SLinus Torvalds 
72481da177e4SLinus Torvalds 		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
72491da177e4SLinus Torvalds 			break;
72501da177e4SLinus Torvalds 
72511da177e4SLinus Torvalds 		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
72521da177e4SLinus Torvalds 			break;
72531da177e4SLinus Torvalds 	}
72541da177e4SLinus Torvalds 
72551da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0,
72561da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
72571da177e4SLinus Torvalds 
72581da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
725947b5d69cSJames Bottomley  	WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
72601da177e4SLinus Torvalds 
72611da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
72621da177e4SLinus Torvalds 
72631da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, old_timer);
72641da177e4SLinus Torvalds }
72651da177e4SLinus Torvalds 
72661da177e4SLinus Torvalds /*---------------------------------------------------------------------
72671da177e4SLinus Torvalds  *
72681da177e4SLinus Torvalds  * Function: Enable/Disable Write to EEPROM
72691da177e4SLinus Torvalds  *
72701da177e4SLinus Torvalds  * Description: The EEPROM must first be enabled for writes
72711da177e4SLinus Torvalds  *              A total of 9 clocks are needed.
72721da177e4SLinus Torvalds  *
72731da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
72741da177e4SLinus Torvalds 
7275391e2f25SKhalid Aziz static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode)
72761da177e4SLinus Torvalds {
7277db038cf8SAlexey Dobriyan 	unsigned char ee_value;
72781da177e4SLinus Torvalds 
72795c04a7b8SAlexey Dobriyan 	ee_value =
72805c04a7b8SAlexey Dobriyan 	    (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
72815c04a7b8SAlexey Dobriyan 			    (EXT_ARB_ACK | SCSI_TERM_ENA_H));
72821da177e4SLinus Torvalds 
72831da177e4SLinus Torvalds 	if (p_mode)
72841da177e4SLinus Torvalds 
728547b5d69cSJames Bottomley  		FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
72861da177e4SLinus Torvalds 
72871da177e4SLinus Torvalds 	else
72881da177e4SLinus Torvalds 
728947b5d69cSJames Bottomley  		FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
72901da177e4SLinus Torvalds 
72911da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
72921da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
72931da177e4SLinus Torvalds }
72941da177e4SLinus Torvalds 
72951da177e4SLinus Torvalds /*---------------------------------------------------------------------
72961da177e4SLinus Torvalds  *
72971da177e4SLinus Torvalds  * Function: Write EEPROM
72981da177e4SLinus Torvalds  *
72991da177e4SLinus Torvalds  * Description: Write a word to the EEPROM at the specified
73001da177e4SLinus Torvalds  *              address.
73011da177e4SLinus Torvalds  *
73021da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
73031da177e4SLinus Torvalds 
7304391e2f25SKhalid Aziz static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
73055c04a7b8SAlexey Dobriyan 			    unsigned short ee_addr)
73061da177e4SLinus Torvalds {
73071da177e4SLinus Torvalds 
7308db038cf8SAlexey Dobriyan 	unsigned char ee_value;
7309c823feebSAlexey Dobriyan 	unsigned short i;
73101da177e4SLinus Torvalds 
73115c04a7b8SAlexey Dobriyan 	ee_value =
73125c04a7b8SAlexey Dobriyan 	    (unsigned
73135c04a7b8SAlexey Dobriyan 	     char)((RD_HARPOON(p_port + hp_ee_ctrl) &
73145c04a7b8SAlexey Dobriyan 		    (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
73151da177e4SLinus Torvalds 
731647b5d69cSJames Bottomley  	FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
73171da177e4SLinus Torvalds 
73181da177e4SLinus Torvalds 	ee_value |= (SEE_MS + SEE_CS);
73191da177e4SLinus Torvalds 
73201da177e4SLinus Torvalds 	for (i = 0x8000; i != 0; i >>= 1) {
73211da177e4SLinus Torvalds 
73221da177e4SLinus Torvalds 		if (i & ee_data)
73231da177e4SLinus Torvalds 			ee_value |= SEE_DO;
73241da177e4SLinus Torvalds 		else
73251da177e4SLinus Torvalds 			ee_value &= ~SEE_DO;
73261da177e4SLinus Torvalds 
73271da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73281da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73291da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
73301da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73311da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73321da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
73331da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73341da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73351da177e4SLinus Torvalds 	}
73361da177e4SLinus Torvalds 	ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
73371da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
73381da177e4SLinus Torvalds 
733947b5d69cSJames Bottomley  	FPT_Wait(p_port, TO_10ms);
73401da177e4SLinus Torvalds 
73411da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS));	/* Set CS to EEPROM */
73421da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/* Turn off CS */
73431da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/* Turn off Master Select */
73441da177e4SLinus Torvalds }
73451da177e4SLinus Torvalds 
73461da177e4SLinus Torvalds /*---------------------------------------------------------------------
73471da177e4SLinus Torvalds  *
73481da177e4SLinus Torvalds  * Function: Read EEPROM
73491da177e4SLinus Torvalds  *
73501da177e4SLinus Torvalds  * Description: Read a word from the EEPROM at the desired
73511da177e4SLinus Torvalds  *              address.
73521da177e4SLinus Torvalds  *
73531da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
73541da177e4SLinus Torvalds 
7355391e2f25SKhalid Aziz static unsigned short FPT_utilEERead(u32 p_port,
73565c04a7b8SAlexey Dobriyan 				     unsigned short ee_addr)
73571da177e4SLinus Torvalds {
7358c823feebSAlexey Dobriyan 	unsigned short i, ee_data1, ee_data2;
73591da177e4SLinus Torvalds 
73601da177e4SLinus Torvalds 	i = 0;
736147b5d69cSJames Bottomley  	ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
73625c04a7b8SAlexey Dobriyan 	do {
736347b5d69cSJames Bottomley  		ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
73641da177e4SLinus Torvalds 
73651da177e4SLinus Torvalds 		if (ee_data1 == ee_data2)
73665c1b85e2SAlexey Dobriyan 			return ee_data1;
73671da177e4SLinus Torvalds 
73681da177e4SLinus Torvalds 		ee_data1 = ee_data2;
73691da177e4SLinus Torvalds 		i++;
73701da177e4SLinus Torvalds 
73711da177e4SLinus Torvalds 	} while (i < 4);
73721da177e4SLinus Torvalds 
73735c1b85e2SAlexey Dobriyan 	return ee_data1;
73741da177e4SLinus Torvalds }
73751da177e4SLinus Torvalds 
73761da177e4SLinus Torvalds /*---------------------------------------------------------------------
73771da177e4SLinus Torvalds  *
73781da177e4SLinus Torvalds  * Function: Read EEPROM Original
73791da177e4SLinus Torvalds  *
73801da177e4SLinus Torvalds  * Description: Read a word from the EEPROM at the desired
73811da177e4SLinus Torvalds  *              address.
73821da177e4SLinus Torvalds  *
73831da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
73841da177e4SLinus Torvalds 
7385391e2f25SKhalid Aziz static unsigned short FPT_utilEEReadOrg(u32 p_port, unsigned short ee_addr)
73861da177e4SLinus Torvalds {
73871da177e4SLinus Torvalds 
7388db038cf8SAlexey Dobriyan 	unsigned char ee_value;
7389c823feebSAlexey Dobriyan 	unsigned short i, ee_data;
73901da177e4SLinus Torvalds 
73915c04a7b8SAlexey Dobriyan 	ee_value =
73925c04a7b8SAlexey Dobriyan 	    (unsigned
73935c04a7b8SAlexey Dobriyan 	     char)((RD_HARPOON(p_port + hp_ee_ctrl) &
73945c04a7b8SAlexey Dobriyan 		    (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
73951da177e4SLinus Torvalds 
739647b5d69cSJames Bottomley  	FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
73971da177e4SLinus Torvalds 
73981da177e4SLinus Torvalds 	ee_value |= (SEE_MS + SEE_CS);
73991da177e4SLinus Torvalds 	ee_data = 0;
74001da177e4SLinus Torvalds 
74011da177e4SLinus Torvalds 	for (i = 1; i <= 16; i++) {
74021da177e4SLinus Torvalds 
74031da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
74041da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74051da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74061da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
74071da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74081da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74091da177e4SLinus Torvalds 
74101da177e4SLinus Torvalds 		ee_data <<= 1;
74111da177e4SLinus Torvalds 
74121da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
74131da177e4SLinus Torvalds 			ee_data |= 1;
74141da177e4SLinus Torvalds 	}
74151da177e4SLinus Torvalds 
74161da177e4SLinus Torvalds 	ee_value &= ~(SEE_MS + SEE_CS);
74171da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
74181da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
74191da177e4SLinus Torvalds 
74205c1b85e2SAlexey Dobriyan 	return ee_data;
74211da177e4SLinus Torvalds }
74221da177e4SLinus Torvalds 
74231da177e4SLinus Torvalds /*---------------------------------------------------------------------
74241da177e4SLinus Torvalds  *
74251da177e4SLinus Torvalds  * Function: Send EE command and Address to the EEPROM
74261da177e4SLinus Torvalds  *
74271da177e4SLinus Torvalds  * Description: Transfers the correct command and sends the address
74281da177e4SLinus Torvalds  *              to the eeprom.
74291da177e4SLinus Torvalds  *
74301da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
74311da177e4SLinus Torvalds 
7432391e2f25SKhalid Aziz static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
74335c04a7b8SAlexey Dobriyan 				  unsigned short ee_addr)
74341da177e4SLinus Torvalds {
7435db038cf8SAlexey Dobriyan 	unsigned char ee_value;
7436db038cf8SAlexey Dobriyan 	unsigned char narrow_flg;
74371da177e4SLinus Torvalds 
7438c823feebSAlexey Dobriyan 	unsigned short i;
74391da177e4SLinus Torvalds 
74405c04a7b8SAlexey Dobriyan 	narrow_flg =
74415c04a7b8SAlexey Dobriyan 	    (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
74425c04a7b8SAlexey Dobriyan 			    NARROW_SCSI_CARD);
74431da177e4SLinus Torvalds 
74441da177e4SLinus Torvalds 	ee_value = SEE_MS;
74451da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74461da177e4SLinus Torvalds 
74471da177e4SLinus Torvalds 	ee_value |= SEE_CS;	/* Set CS to EEPROM */
74481da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74491da177e4SLinus Torvalds 
74501da177e4SLinus Torvalds 	for (i = 0x04; i != 0; i >>= 1) {
74511da177e4SLinus Torvalds 
74521da177e4SLinus Torvalds 		if (i & ee_cmd)
74531da177e4SLinus Torvalds 			ee_value |= SEE_DO;
74541da177e4SLinus Torvalds 		else
74551da177e4SLinus Torvalds 			ee_value &= ~SEE_DO;
74561da177e4SLinus Torvalds 
74571da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74581da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74591da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
74601da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74611da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74621da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
74631da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74641da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74651da177e4SLinus Torvalds 	}
74661da177e4SLinus Torvalds 
74671da177e4SLinus Torvalds 	if (narrow_flg)
74681da177e4SLinus Torvalds 		i = 0x0080;
74691da177e4SLinus Torvalds 
74701da177e4SLinus Torvalds 	else
74711da177e4SLinus Torvalds 		i = 0x0200;
74721da177e4SLinus Torvalds 
74731da177e4SLinus Torvalds 	while (i != 0) {
74741da177e4SLinus Torvalds 
74751da177e4SLinus Torvalds 		if (i & ee_addr)
74761da177e4SLinus Torvalds 			ee_value |= SEE_DO;
74771da177e4SLinus Torvalds 		else
74781da177e4SLinus Torvalds 			ee_value &= ~SEE_DO;
74791da177e4SLinus Torvalds 
74801da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74811da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74821da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
74831da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74841da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74851da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
74861da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74871da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74881da177e4SLinus Torvalds 
74891da177e4SLinus Torvalds 		i >>= 1;
74901da177e4SLinus Torvalds 	}
74911da177e4SLinus Torvalds }
74921da177e4SLinus Torvalds 
7493c823feebSAlexey Dobriyan static unsigned short FPT_CalcCrc16(unsigned char buffer[])
74941da177e4SLinus Torvalds {
7495c823feebSAlexey Dobriyan 	unsigned short crc = 0;
74961da177e4SLinus Torvalds 	int i, j;
7497c823feebSAlexey Dobriyan 	unsigned short ch;
74985c04a7b8SAlexey Dobriyan 	for (i = 0; i < ID_STRING_LENGTH; i++) {
7499c823feebSAlexey Dobriyan 		ch = (unsigned short)buffer[i];
75005c04a7b8SAlexey Dobriyan 		for (j = 0; j < 8; j++) {
75011da177e4SLinus Torvalds 			if ((crc ^ ch) & 1)
75021da177e4SLinus Torvalds 				crc = (crc >> 1) ^ CRCMASK;
75031da177e4SLinus Torvalds 			else
75041da177e4SLinus Torvalds 				crc >>= 1;
75051da177e4SLinus Torvalds 			ch >>= 1;
75061da177e4SLinus Torvalds 		}
75071da177e4SLinus Torvalds 	}
75085c1b85e2SAlexey Dobriyan 	return crc;
75091da177e4SLinus Torvalds }
75101da177e4SLinus Torvalds 
7511db038cf8SAlexey Dobriyan static unsigned char FPT_CalcLrc(unsigned char buffer[])
75121da177e4SLinus Torvalds {
75131da177e4SLinus Torvalds 	int i;
7514db038cf8SAlexey Dobriyan 	unsigned char lrc;
75151da177e4SLinus Torvalds 	lrc = 0;
75161da177e4SLinus Torvalds 	for (i = 0; i < ID_STRING_LENGTH; i++)
75171da177e4SLinus Torvalds 		lrc ^= buffer[i];
75185c1b85e2SAlexey Dobriyan 	return lrc;
75191da177e4SLinus Torvalds }
75201da177e4SLinus Torvalds 
75211da177e4SLinus Torvalds /*
75221da177e4SLinus Torvalds   The following inline definitions avoid type conflicts.
75231da177e4SLinus Torvalds */
75241da177e4SLinus Torvalds 
75251da177e4SLinus Torvalds static inline unsigned char
7526839cb99eSKhalid Aziz FlashPoint__ProbeHostAdapter(struct fpoint_info *FlashPointInfo)
75271da177e4SLinus Torvalds {
75285c04a7b8SAlexey Dobriyan 	return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
75295c04a7b8SAlexey Dobriyan 					   FlashPointInfo);
75301da177e4SLinus Torvalds }
75311da177e4SLinus Torvalds 
7532391e2f25SKhalid Aziz static inline void *
7533839cb99eSKhalid Aziz FlashPoint__HardwareResetHostAdapter(struct fpoint_info *FlashPointInfo)
75341da177e4SLinus Torvalds {
75355c04a7b8SAlexey Dobriyan 	return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
75365c04a7b8SAlexey Dobriyan 						   FlashPointInfo);
75371da177e4SLinus Torvalds }
75381da177e4SLinus Torvalds 
75391da177e4SLinus Torvalds static inline void
7540391e2f25SKhalid Aziz FlashPoint__ReleaseHostAdapter(void *CardHandle)
75411da177e4SLinus Torvalds {
75421da177e4SLinus Torvalds 	FlashPoint_ReleaseHostAdapter(CardHandle);
75431da177e4SLinus Torvalds }
75441da177e4SLinus Torvalds 
75451da177e4SLinus Torvalds static inline void
7546391e2f25SKhalid Aziz FlashPoint__StartCCB(void *CardHandle, struct blogic_ccb *CCB)
75471da177e4SLinus Torvalds {
754869eb2ea4SAlexey Dobriyan 	FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
75491da177e4SLinus Torvalds }
75501da177e4SLinus Torvalds 
75511da177e4SLinus Torvalds static inline void
7552391e2f25SKhalid Aziz FlashPoint__AbortCCB(void *CardHandle, struct blogic_ccb *CCB)
75531da177e4SLinus Torvalds {
755469eb2ea4SAlexey Dobriyan 	FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
75551da177e4SLinus Torvalds }
75561da177e4SLinus Torvalds 
75572065e310SRichard Knutsson static inline bool
7558391e2f25SKhalid Aziz FlashPoint__InterruptPending(void *CardHandle)
75591da177e4SLinus Torvalds {
75601da177e4SLinus Torvalds 	return FlashPoint_InterruptPending(CardHandle);
75611da177e4SLinus Torvalds }
75621da177e4SLinus Torvalds 
75631da177e4SLinus Torvalds static inline int
7564391e2f25SKhalid Aziz FlashPoint__HandleInterrupt(void *CardHandle)
75651da177e4SLinus Torvalds {
75661da177e4SLinus Torvalds 	return FlashPoint_HandleInterrupt(CardHandle);
75671da177e4SLinus Torvalds }
75681da177e4SLinus Torvalds 
75691da177e4SLinus Torvalds #define FlashPoint_ProbeHostAdapter	    FlashPoint__ProbeHostAdapter
75701da177e4SLinus Torvalds #define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
75711da177e4SLinus Torvalds #define FlashPoint_ReleaseHostAdapter	    FlashPoint__ReleaseHostAdapter
75721da177e4SLinus Torvalds #define FlashPoint_StartCCB		    FlashPoint__StartCCB
75731da177e4SLinus Torvalds #define FlashPoint_AbortCCB		    FlashPoint__AbortCCB
75741da177e4SLinus Torvalds #define FlashPoint_InterruptPending	    FlashPoint__InterruptPending
75751da177e4SLinus Torvalds #define FlashPoint_HandleInterrupt	    FlashPoint__HandleInterrupt
75761da177e4SLinus Torvalds 
757778b4b05dSMatthew Wilcox #else				/* !CONFIG_SCSI_FLASHPOINT */
75781da177e4SLinus Torvalds 
75791da177e4SLinus Torvalds /*
75801da177e4SLinus Torvalds   Define prototypes for the FlashPoint SCCB Manager Functions.
75811da177e4SLinus Torvalds */
75821da177e4SLinus Torvalds 
7583839cb99eSKhalid Aziz extern unsigned char FlashPoint_ProbeHostAdapter(struct fpoint_info *);
7584391e2f25SKhalid Aziz extern void *FlashPoint_HardwareResetHostAdapter(struct fpoint_info *);
7585391e2f25SKhalid Aziz extern void FlashPoint_StartCCB(void *, struct blogic_ccb *);
7586391e2f25SKhalid Aziz extern int FlashPoint_AbortCCB(void *, struct blogic_ccb *);
7587391e2f25SKhalid Aziz extern bool FlashPoint_InterruptPending(void *);
7588391e2f25SKhalid Aziz extern int FlashPoint_HandleInterrupt(void *);
7589391e2f25SKhalid Aziz extern void FlashPoint_ReleaseHostAdapter(void *);
75901da177e4SLinus Torvalds 
759178b4b05dSMatthew Wilcox #endif				/* CONFIG_SCSI_FLASHPOINT */
7592