xref: /openbmc/linux/drivers/scsi/FlashPoint.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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;
434d431153SRandy Dunlap 	u16 si_mflags;
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 
3081da177e4SLinus Torvalds #define  SMIDENT                 0x80
3091da177e4SLinus Torvalds #define  DISC_PRIV               0x40
3101da177e4SLinus Torvalds 
3111da177e4SLinus Torvalds #define  SM8BIT                  0x00
3121da177e4SLinus Torvalds #define  SM16BIT                 0x01
3131da177e4SLinus Torvalds 
3141da177e4SLinus Torvalds #define  SIX_BYTE_CMD            0x06
3151da177e4SLinus Torvalds #define  TWELVE_BYTE_CMD         0x0C
3161da177e4SLinus Torvalds 
3171da177e4SLinus Torvalds #define  ASYNC                   0x00
3181da177e4SLinus Torvalds #define  MAX_OFFSET              0x0F	/* Maxbyteoffset for Sync Xfers */
3191da177e4SLinus Torvalds 
3201da177e4SLinus Torvalds #define  EEPROM_WD_CNT     256
3211da177e4SLinus Torvalds 
3221da177e4SLinus Torvalds #define  EEPROM_CHECK_SUM  0
3231da177e4SLinus Torvalds #define  FW_SIGNATURE      2
3241da177e4SLinus Torvalds #define  MODEL_NUMB_0      4
3251da177e4SLinus Torvalds #define  MODEL_NUMB_2      6
3261da177e4SLinus Torvalds #define  MODEL_NUMB_4      8
3271da177e4SLinus Torvalds #define  SYSTEM_CONFIG     16
3281da177e4SLinus Torvalds #define  SCSI_CONFIG       17
3291da177e4SLinus Torvalds #define  BIOS_CONFIG       18
3301da177e4SLinus Torvalds #define  SCAM_CONFIG       20
3311da177e4SLinus Torvalds #define  ADAPTER_SCSI_ID   24
3321da177e4SLinus Torvalds 
3331da177e4SLinus Torvalds #define  IGNORE_B_SCAN     32
3341da177e4SLinus Torvalds #define  SEND_START_ENA    34
3351da177e4SLinus Torvalds #define  DEVICE_ENABLE     36
3361da177e4SLinus Torvalds 
3371da177e4SLinus Torvalds #define  SYNC_RATE_TBL     38
3381da177e4SLinus Torvalds #define  SYNC_RATE_TBL01   38
3391da177e4SLinus Torvalds #define  SYNC_RATE_TBL23   40
3401da177e4SLinus Torvalds #define  SYNC_RATE_TBL45   42
3411da177e4SLinus Torvalds #define  SYNC_RATE_TBL67   44
3421da177e4SLinus Torvalds #define  SYNC_RATE_TBL89   46
3431da177e4SLinus Torvalds #define  SYNC_RATE_TBLab   48
3441da177e4SLinus Torvalds #define  SYNC_RATE_TBLcd   50
3451da177e4SLinus Torvalds #define  SYNC_RATE_TBLef   52
3461da177e4SLinus Torvalds 
3471da177e4SLinus Torvalds #define  EE_SCAMBASE      256
3481da177e4SLinus Torvalds 
3491da177e4SLinus Torvalds #define  SCAM_ENABLED   BIT(2)
3501da177e4SLinus Torvalds #define  SCAM_LEVEL2    BIT(3)
3511da177e4SLinus Torvalds 
3521cafc30fSJiri Slaby #define	RENEGO_ENA		BIT(10)
3531cafc30fSJiri Slaby #define	CONNIO_ENA		BIT(11)
3541cafc30fSJiri Slaby #define  GREEN_PC_ENA   BIT(12)
3551da177e4SLinus Torvalds 
3561da177e4SLinus Torvalds #define  AUTO_RATE_00   00
3571da177e4SLinus Torvalds #define  AUTO_RATE_05   01
3581da177e4SLinus Torvalds #define  AUTO_RATE_10   02
3591da177e4SLinus Torvalds #define  AUTO_RATE_20   03
3601da177e4SLinus Torvalds 
3611da177e4SLinus Torvalds #define  WIDE_NEGO_BIT     BIT(7)
3621da177e4SLinus Torvalds #define  DISC_ENABLE_BIT   BIT(6)
3631da177e4SLinus Torvalds 
3641da177e4SLinus Torvalds #define  hp_vendor_id_0       0x00	/* LSB */
3651da177e4SLinus Torvalds #define  ORION_VEND_0   0x4B
3661da177e4SLinus Torvalds 
3671da177e4SLinus Torvalds #define  hp_vendor_id_1       0x01	/* MSB */
3681da177e4SLinus Torvalds #define  ORION_VEND_1   0x10
3691da177e4SLinus Torvalds 
3701da177e4SLinus Torvalds #define  hp_device_id_0       0x02	/* LSB */
3711da177e4SLinus Torvalds #define  ORION_DEV_0    0x30
3721da177e4SLinus Torvalds 
3731da177e4SLinus Torvalds #define  hp_device_id_1       0x03	/* MSB */
3741da177e4SLinus Torvalds #define  ORION_DEV_1    0x81
3751da177e4SLinus Torvalds 
3761da177e4SLinus Torvalds 	/* Sub Vendor ID and Sub Device ID only available in
3771da177e4SLinus Torvalds 	   Harpoon Version 2 and higher */
3781da177e4SLinus Torvalds 
3791da177e4SLinus Torvalds #define  hp_sub_device_id_0   0x06	/* LSB */
3801da177e4SLinus Torvalds 
3811da177e4SLinus Torvalds #define  hp_semaphore         0x0C
3821da177e4SLinus Torvalds #define SCCB_MGR_ACTIVE    BIT(0)
3831da177e4SLinus Torvalds #define TICKLE_ME          BIT(1)
3841da177e4SLinus Torvalds #define SCCB_MGR_PRESENT   BIT(3)
3851da177e4SLinus Torvalds #define BIOS_IN_USE        BIT(4)
3861da177e4SLinus Torvalds 
3871da177e4SLinus Torvalds #define  hp_sys_ctrl          0x0F
3881da177e4SLinus Torvalds 
3891da177e4SLinus Torvalds #define  STOP_CLK          BIT(0)	/*Turn off BusMaster Clock */
3901da177e4SLinus Torvalds #define  DRVR_RST          BIT(1)	/*Firmware Reset to 80C15 chip */
3911da177e4SLinus Torvalds #define  HALT_MACH         BIT(3)	/*Halt State Machine      */
3921da177e4SLinus Torvalds #define  HARD_ABORT        BIT(4)	/*Hard Abort              */
3931da177e4SLinus Torvalds 
3941da177e4SLinus Torvalds #define  hp_host_blk_cnt      0x13
3951da177e4SLinus Torvalds 
3961da177e4SLinus Torvalds #define  XFER_BLK64        0x06	/*     1 1 0 64 byte per block */
3971da177e4SLinus Torvalds 
3981da177e4SLinus Torvalds #define  BM_THRESHOLD      0x40	/* PCI mode can only xfer 16 bytes */
3991da177e4SLinus Torvalds 
4001da177e4SLinus Torvalds #define  hp_int_mask          0x17
4011da177e4SLinus Torvalds 
4021da177e4SLinus Torvalds #define  INT_CMD_COMPL     BIT(0)	/* DMA command complete   */
4031da177e4SLinus Torvalds #define  INT_EXT_STATUS    BIT(1)	/* Extended Status Set    */
4041da177e4SLinus Torvalds 
4051da177e4SLinus Torvalds #define  hp_xfer_cnt_lo       0x18
4061da177e4SLinus Torvalds #define  hp_xfer_cnt_hi       0x1A
4071da177e4SLinus Torvalds #define  hp_xfer_cmd          0x1B
4081da177e4SLinus Torvalds 
4091da177e4SLinus Torvalds #define  XFER_HOST_DMA     0x00	/*     0 0 0 Transfer Host -> DMA */
4101da177e4SLinus Torvalds #define  XFER_DMA_HOST     0x01	/*     0 0 1 Transfer DMA  -> Host */
4111da177e4SLinus Torvalds 
4121da177e4SLinus Torvalds #define  XFER_HOST_AUTO    0x00	/*     0 0 Auto Transfer Size   */
4131da177e4SLinus Torvalds 
4141da177e4SLinus Torvalds #define  XFER_DMA_8BIT     0x20	/*     0 1 8 BIT  Transfer Size */
4151da177e4SLinus Torvalds 
4161da177e4SLinus Torvalds #define  DISABLE_INT       BIT(7)	/*Do not interrupt at end of cmd. */
4171da177e4SLinus Torvalds 
4181da177e4SLinus Torvalds #define  HOST_WRT_CMD      ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
4191da177e4SLinus Torvalds #define  HOST_RD_CMD       ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
4201da177e4SLinus Torvalds 
4211da177e4SLinus Torvalds #define  hp_host_addr_lo      0x1C
4221da177e4SLinus Torvalds #define  hp_host_addr_hmi     0x1E
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds #define  hp_ee_ctrl           0x22
4251da177e4SLinus Torvalds 
4261da177e4SLinus Torvalds #define  EXT_ARB_ACK       BIT(7)
4271da177e4SLinus Torvalds #define  SCSI_TERM_ENA_H   BIT(6)	/* SCSI high byte terminator */
4281da177e4SLinus Torvalds #define  SEE_MS            BIT(5)
4291da177e4SLinus Torvalds #define  SEE_CS            BIT(3)
4301da177e4SLinus Torvalds #define  SEE_CLK           BIT(2)
4311da177e4SLinus Torvalds #define  SEE_DO            BIT(1)
4321da177e4SLinus Torvalds #define  SEE_DI            BIT(0)
4331da177e4SLinus Torvalds 
4341da177e4SLinus Torvalds #define  EE_READ           0x06
4351da177e4SLinus Torvalds #define  EE_WRITE          0x05
4361da177e4SLinus Torvalds #define  EWEN              0x04
4371da177e4SLinus Torvalds #define  EWEN_ADDR         0x03C0
4381da177e4SLinus Torvalds #define  EWDS              0x04
4391da177e4SLinus Torvalds #define  EWDS_ADDR         0x0000
4401da177e4SLinus Torvalds 
4411da177e4SLinus Torvalds #define  hp_bm_ctrl           0x26
4421da177e4SLinus Torvalds 
4431da177e4SLinus Torvalds #define  SCSI_TERM_ENA_L   BIT(0)	/*Enable/Disable external terminators */
4441da177e4SLinus Torvalds #define  FLUSH_XFER_CNTR   BIT(1)	/*Flush transfer counter */
4451da177e4SLinus Torvalds #define  FORCE1_XFER       BIT(5)	/*Always xfer one byte in byte mode */
4461da177e4SLinus Torvalds #define  FAST_SINGLE       BIT(6)	/*?? */
4471da177e4SLinus Torvalds 
4481da177e4SLinus Torvalds #define  BMCTRL_DEFAULT    (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)
4491da177e4SLinus Torvalds 
4501da177e4SLinus Torvalds #define  hp_sg_addr           0x28
4511da177e4SLinus Torvalds #define  hp_page_ctrl         0x29
4521da177e4SLinus Torvalds 
4531da177e4SLinus Torvalds #define  SCATTER_EN        BIT(0)
4541da177e4SLinus Torvalds #define  SGRAM_ARAM        BIT(1)
4551da177e4SLinus Torvalds #define  G_INT_DISABLE     BIT(3)	/* Enable/Disable all Interrupts */
4561da177e4SLinus Torvalds #define  NARROW_SCSI_CARD  BIT(4)	/* NARROW/WIDE SCSI config pin */
4571da177e4SLinus Torvalds 
4581da177e4SLinus Torvalds #define  hp_pci_stat_cfg      0x2D
4591da177e4SLinus Torvalds 
4601da177e4SLinus Torvalds #define  REC_MASTER_ABORT  BIT(5)	/*received Master abort */
4611da177e4SLinus Torvalds 
4621da177e4SLinus Torvalds #define  hp_rev_num           0x33
4631da177e4SLinus Torvalds 
4641da177e4SLinus Torvalds #define  hp_stack_data        0x34
4651da177e4SLinus Torvalds #define  hp_stack_addr        0x35
4661da177e4SLinus Torvalds 
4671da177e4SLinus Torvalds #define  hp_ext_status        0x36
4681da177e4SLinus Torvalds 
4691da177e4SLinus Torvalds #define  BM_FORCE_OFF      BIT(0)	/*Bus Master is forced to get off */
4701da177e4SLinus Torvalds #define  PCI_TGT_ABORT     BIT(0)	/*PCI bus master transaction aborted */
4711da177e4SLinus Torvalds #define  PCI_DEV_TMOUT     BIT(1)	/*PCI Device Time out */
4721da177e4SLinus Torvalds #define  CMD_ABORTED       BIT(4)	/*Command aborted */
4731da177e4SLinus Torvalds #define  BM_PARITY_ERR     BIT(5)	/*parity error on data received   */
4741da177e4SLinus Torvalds #define  PIO_OVERRUN       BIT(6)	/*Slave data overrun */
4751da177e4SLinus Torvalds #define  BM_CMD_BUSY       BIT(7)	/*Bus master transfer command busy */
4761da177e4SLinus Torvalds #define  BAD_EXT_STATUS    (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
4771da177e4SLinus Torvalds                                   BM_PARITY_ERR | PIO_OVERRUN)
4781da177e4SLinus Torvalds 
4791da177e4SLinus Torvalds #define  hp_int_status        0x37
4801da177e4SLinus Torvalds 
4811da177e4SLinus Torvalds #define  EXT_STATUS_ON     BIT(1)	/*Extended status is valid */
4821da177e4SLinus Torvalds #define  SCSI_INTERRUPT    BIT(2)	/*Global indication of a SCSI int. */
4831da177e4SLinus Torvalds #define  INT_ASSERTED      BIT(5)	/* */
4841da177e4SLinus Torvalds 
4851da177e4SLinus Torvalds #define  hp_fifo_cnt          0x38
4861da177e4SLinus Torvalds 
4871da177e4SLinus Torvalds #define  hp_intena		 0x40
4881da177e4SLinus Torvalds 
4891cafc30fSJiri Slaby #define  RESET		 BIT(7)
4901cafc30fSJiri Slaby #define  PROG_HLT		 BIT(6)
4911cafc30fSJiri Slaby #define  PARITY		 BIT(5)
4921cafc30fSJiri Slaby #define  FIFO		 BIT(4)
4931cafc30fSJiri Slaby #define  SEL		 BIT(3)
4941cafc30fSJiri Slaby #define  SCAM_SEL		 BIT(2)
4951cafc30fSJiri Slaby #define  RSEL		 BIT(1)
4961cafc30fSJiri Slaby #define  TIMEOUT		 BIT(0)
4971cafc30fSJiri Slaby #define  BUS_FREE		 BIT(15)
4981cafc30fSJiri Slaby #define  XFER_CNT_0	 BIT(14)
4991cafc30fSJiri Slaby #define  PHASE		 BIT(13)
5001cafc30fSJiri Slaby #define  IUNKWN		 BIT(12)
5011cafc30fSJiri Slaby #define  ICMD_COMP	 BIT(11)
5021cafc30fSJiri Slaby #define  ITICKLE		 BIT(10)
5031cafc30fSJiri Slaby #define  IDO_STRT		 BIT(9)
5041cafc30fSJiri Slaby #define  ITAR_DISC	 BIT(8)
5051cafc30fSJiri Slaby #define  AUTO_INT		 (BIT(12)+BIT(11)+BIT(10)+BIT(9)+BIT(8))
5061da177e4SLinus Torvalds #define  CLR_ALL_INT	 0xFFFF
5071da177e4SLinus Torvalds #define  CLR_ALL_INT_1	 0xFF00
5081da177e4SLinus Torvalds 
5091da177e4SLinus Torvalds #define  hp_intstat		 0x42
5101da177e4SLinus Torvalds 
5111da177e4SLinus Torvalds #define  hp_scsisig           0x44
5121da177e4SLinus Torvalds 
5131da177e4SLinus Torvalds #define  SCSI_SEL          BIT(7)
5141da177e4SLinus Torvalds #define  SCSI_BSY          BIT(6)
5151da177e4SLinus Torvalds #define  SCSI_REQ          BIT(5)
5161da177e4SLinus Torvalds #define  SCSI_ACK          BIT(4)
5171da177e4SLinus Torvalds #define  SCSI_ATN          BIT(3)
5181da177e4SLinus Torvalds #define  SCSI_CD           BIT(2)
5191da177e4SLinus Torvalds #define  SCSI_MSG          BIT(1)
5201da177e4SLinus Torvalds #define  SCSI_IOBIT        BIT(0)
5211da177e4SLinus Torvalds 
5221da177e4SLinus Torvalds #define  S_SCSI_PHZ        (BIT(2)+BIT(1)+BIT(0))
5231da177e4SLinus Torvalds #define  S_MSGO_PH         (BIT(2)+BIT(1)       )
5241da177e4SLinus Torvalds #define  S_MSGI_PH         (BIT(2)+BIT(1)+BIT(0))
5251da177e4SLinus Torvalds #define  S_DATAI_PH        (              BIT(0))
5261da177e4SLinus Torvalds #define  S_DATAO_PH        0x00
5271da177e4SLinus Torvalds #define  S_ILL_PH          (       BIT(1)       )
5281da177e4SLinus Torvalds 
5291da177e4SLinus Torvalds #define  hp_scsictrl_0        0x45
5301da177e4SLinus Torvalds 
5311da177e4SLinus Torvalds #define  SEL_TAR           BIT(6)
5321da177e4SLinus Torvalds #define  ENA_ATN           BIT(4)
5331da177e4SLinus Torvalds #define  ENA_RESEL         BIT(2)
5341da177e4SLinus Torvalds #define  SCSI_RST          BIT(1)
5351da177e4SLinus Torvalds #define  ENA_SCAM_SEL      BIT(0)
5361da177e4SLinus Torvalds 
5371da177e4SLinus Torvalds #define  hp_portctrl_0        0x46
5381da177e4SLinus Torvalds 
5391da177e4SLinus Torvalds #define  SCSI_PORT         BIT(7)
5401da177e4SLinus Torvalds #define  SCSI_INBIT        BIT(6)
5411da177e4SLinus Torvalds #define  DMA_PORT          BIT(5)
5421da177e4SLinus Torvalds #define  DMA_RD            BIT(4)
5431da177e4SLinus Torvalds #define  HOST_PORT         BIT(3)
5441da177e4SLinus Torvalds #define  HOST_WRT          BIT(2)
5451da177e4SLinus Torvalds #define  SCSI_BUS_EN       BIT(1)
5461da177e4SLinus Torvalds #define  START_TO          BIT(0)
5471da177e4SLinus Torvalds 
5481da177e4SLinus Torvalds #define  hp_scsireset         0x47
5491da177e4SLinus Torvalds 
5501da177e4SLinus Torvalds #define  SCSI_INI          BIT(6)
5511da177e4SLinus Torvalds #define  SCAM_EN           BIT(5)
5521da177e4SLinus Torvalds #define  DMA_RESET         BIT(3)
5531da177e4SLinus Torvalds #define  HPSCSI_RESET      BIT(2)
5541da177e4SLinus Torvalds #define  PROG_RESET        BIT(1)
5551da177e4SLinus Torvalds #define  FIFO_CLR          BIT(0)
5561da177e4SLinus Torvalds 
5571da177e4SLinus Torvalds #define  hp_xfercnt_0         0x48
5581da177e4SLinus Torvalds #define  hp_xfercnt_2         0x4A
5591da177e4SLinus Torvalds 
5601da177e4SLinus Torvalds #define  hp_fifodata_0        0x4C
5611da177e4SLinus Torvalds #define  hp_addstat           0x4E
5621da177e4SLinus Torvalds 
5631da177e4SLinus Torvalds #define  SCAM_TIMER        BIT(7)
5641da177e4SLinus Torvalds #define  SCSI_MODE8        BIT(3)
5651da177e4SLinus Torvalds #define  SCSI_PAR_ERR      BIT(0)
5661da177e4SLinus Torvalds 
5671da177e4SLinus Torvalds #define  hp_prgmcnt_0         0x4F
5681da177e4SLinus Torvalds 
5691da177e4SLinus Torvalds #define  hp_selfid_0          0x50
5701da177e4SLinus Torvalds #define  hp_selfid_1          0x51
5711da177e4SLinus Torvalds #define  hp_arb_id            0x52
5721da177e4SLinus Torvalds 
5731da177e4SLinus Torvalds #define  hp_select_id         0x53
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds #define  hp_synctarg_base     0x54
5761da177e4SLinus Torvalds #define  hp_synctarg_12       0x54
5771da177e4SLinus Torvalds #define  hp_synctarg_13       0x55
5781da177e4SLinus Torvalds #define  hp_synctarg_14       0x56
5791da177e4SLinus Torvalds #define  hp_synctarg_15       0x57
5801da177e4SLinus Torvalds 
5811da177e4SLinus Torvalds #define  hp_synctarg_8        0x58
5821da177e4SLinus Torvalds #define  hp_synctarg_9        0x59
5831da177e4SLinus Torvalds #define  hp_synctarg_10       0x5A
5841da177e4SLinus Torvalds #define  hp_synctarg_11       0x5B
5851da177e4SLinus Torvalds 
5861da177e4SLinus Torvalds #define  hp_synctarg_4        0x5C
5871da177e4SLinus Torvalds #define  hp_synctarg_5        0x5D
5881da177e4SLinus Torvalds #define  hp_synctarg_6        0x5E
5891da177e4SLinus Torvalds #define  hp_synctarg_7        0x5F
5901da177e4SLinus Torvalds 
5911da177e4SLinus Torvalds #define  hp_synctarg_0        0x60
5921da177e4SLinus Torvalds #define  hp_synctarg_1        0x61
5931da177e4SLinus Torvalds #define  hp_synctarg_2        0x62
5941da177e4SLinus Torvalds #define  hp_synctarg_3        0x63
5951da177e4SLinus Torvalds 
5961da177e4SLinus Torvalds #define  NARROW_SCSI       BIT(4)
5971da177e4SLinus Torvalds #define  DEFAULT_OFFSET    0x0F
5981da177e4SLinus Torvalds 
5991da177e4SLinus Torvalds #define  hp_autostart_0       0x64
6001da177e4SLinus Torvalds #define  hp_autostart_1       0x65
6011da177e4SLinus Torvalds #define  hp_autostart_3       0x67
6021da177e4SLinus Torvalds 
6031da177e4SLinus Torvalds #define  AUTO_IMMED    BIT(5)
6041da177e4SLinus Torvalds #define  SELECT   BIT(6)
6051da177e4SLinus Torvalds #define  END_DATA (BIT(7)+BIT(6))
6061da177e4SLinus Torvalds 
6071da177e4SLinus Torvalds #define  hp_gp_reg_0          0x68
6081da177e4SLinus Torvalds #define  hp_gp_reg_1          0x69
6091da177e4SLinus Torvalds #define  hp_gp_reg_3          0x6B
6101da177e4SLinus Torvalds 
6111da177e4SLinus Torvalds #define  hp_seltimeout        0x6C
6121da177e4SLinus Torvalds 
6131da177e4SLinus Torvalds #define  TO_4ms            0x67	/* 3.9959ms */
6141da177e4SLinus Torvalds 
6151da177e4SLinus Torvalds #define  TO_5ms            0x03	/* 4.9152ms */
6161da177e4SLinus Torvalds #define  TO_10ms           0x07	/* 11.xxxms */
6171da177e4SLinus Torvalds #define  TO_250ms          0x99	/* 250.68ms */
6181da177e4SLinus Torvalds #define  TO_290ms          0xB1	/* 289.99ms */
6191da177e4SLinus Torvalds 
6201da177e4SLinus Torvalds #define  hp_clkctrl_0         0x6D
6211da177e4SLinus Torvalds 
6221da177e4SLinus Torvalds #define  PWR_DWN           BIT(6)
6231da177e4SLinus Torvalds #define  ACTdeassert       BIT(4)
6241da177e4SLinus Torvalds #define  CLK_40MHZ         (BIT(1) + BIT(0))
6251da177e4SLinus Torvalds 
6261da177e4SLinus Torvalds #define  CLKCTRL_DEFAULT   (ACTdeassert | CLK_40MHZ)
6271da177e4SLinus Torvalds 
6281da177e4SLinus Torvalds #define  hp_fiforead          0x6E
6291da177e4SLinus Torvalds #define  hp_fifowrite         0x6F
6301da177e4SLinus Torvalds 
6311da177e4SLinus Torvalds #define  hp_offsetctr         0x70
6321da177e4SLinus Torvalds #define  hp_xferstat          0x71
6331da177e4SLinus Torvalds 
6341da177e4SLinus Torvalds #define  FIFO_EMPTY        BIT(6)
6351da177e4SLinus Torvalds 
6361da177e4SLinus Torvalds #define  hp_portctrl_1        0x72
6371da177e4SLinus Torvalds 
6381da177e4SLinus Torvalds #define  CHK_SCSI_P        BIT(3)
6391da177e4SLinus Torvalds #define  HOST_MODE8        BIT(0)
6401da177e4SLinus Torvalds 
6411da177e4SLinus Torvalds #define  hp_xfer_pad          0x73
6421da177e4SLinus Torvalds 
6431da177e4SLinus Torvalds #define  ID_UNLOCK         BIT(3)
6441da177e4SLinus Torvalds 
6451da177e4SLinus Torvalds #define  hp_scsidata_0        0x74
6461da177e4SLinus Torvalds #define  hp_scsidata_1        0x75
6471da177e4SLinus Torvalds 
6481da177e4SLinus Torvalds #define  hp_aramBase          0x80
6491da177e4SLinus Torvalds #define  BIOS_DATA_OFFSET     0x60
6501da177e4SLinus Torvalds #define  BIOS_RELATIVE_CARD   0x64
6511da177e4SLinus Torvalds 
6521cafc30fSJiri Slaby #define  AR3      (BIT(9) + BIT(8))
6531cafc30fSJiri Slaby #define  SDATA    BIT(10)
6541da177e4SLinus Torvalds 
6551cafc30fSJiri Slaby #define  CRD_OP   BIT(11)	/* Cmp Reg. w/ Data */
6561da177e4SLinus Torvalds 
6571cafc30fSJiri Slaby #define  CRR_OP   BIT(12)	/* Cmp Reg. w. Reg. */
6581da177e4SLinus Torvalds 
6591cafc30fSJiri Slaby #define  CPE_OP   (BIT(14)+BIT(11))	/* Cmp SCSI phs & Branch EQ */
6601da177e4SLinus Torvalds 
6611cafc30fSJiri Slaby #define  CPN_OP   (BIT(14)+BIT(12))	/* Cmp SCSI phs & Branch NOT EQ */
6621da177e4SLinus Torvalds 
6631da177e4SLinus Torvalds #define  ADATA_OUT   0x00
6641cafc30fSJiri Slaby #define  ADATA_IN    BIT(8)
6651cafc30fSJiri Slaby #define  ACOMMAND    BIT(10)
6661cafc30fSJiri Slaby #define  ASTATUS     (BIT(10)+BIT(8))
6671cafc30fSJiri Slaby #define  AMSG_OUT    (BIT(10)+BIT(9))
6681cafc30fSJiri Slaby #define  AMSG_IN     (BIT(10)+BIT(9)+BIT(8))
6691da177e4SLinus Torvalds 
6701cafc30fSJiri Slaby #define  BRH_OP   BIT(13)	/* Branch */
6711da177e4SLinus Torvalds 
6721da177e4SLinus Torvalds #define  ALWAYS   0x00
6731cafc30fSJiri Slaby #define  EQUAL    BIT(8)
6741cafc30fSJiri Slaby #define  NOT_EQ   BIT(9)
6751da177e4SLinus Torvalds 
6761cafc30fSJiri Slaby #define  TCB_OP   (BIT(13)+BIT(11))	/* Test condition & branch */
6771da177e4SLinus Torvalds 
6781cafc30fSJiri Slaby #define  FIFO_0      BIT(10)
6791da177e4SLinus Torvalds 
6801cafc30fSJiri Slaby #define  MPM_OP   BIT(15)	/* Match phase and move data */
6811da177e4SLinus Torvalds 
6821cafc30fSJiri Slaby #define  MRR_OP   BIT(14)	/* Move DReg. to Reg. */
6831da177e4SLinus Torvalds 
6841da177e4SLinus Torvalds #define  S_IDREG  (BIT(2)+BIT(1)+BIT(0))
6851da177e4SLinus Torvalds 
6861da177e4SLinus Torvalds #define  D_AR0    0x00
6871da177e4SLinus Torvalds #define  D_AR1    BIT(0)
6881da177e4SLinus Torvalds #define  D_BUCKET (BIT(2) + BIT(1) + BIT(0))
6891da177e4SLinus Torvalds 
6901cafc30fSJiri Slaby #define  RAT_OP      (BIT(14)+BIT(13)+BIT(11))
6911da177e4SLinus Torvalds 
6921cafc30fSJiri Slaby #define  SSI_OP      (BIT(15)+BIT(11))
6931da177e4SLinus Torvalds 
6941da177e4SLinus Torvalds #define  SSI_ITAR_DISC	(ITAR_DISC >> 8)
6951da177e4SLinus Torvalds #define  SSI_IDO_STRT	(IDO_STRT >> 8)
6961da177e4SLinus Torvalds 
6971da177e4SLinus Torvalds #define  SSI_ICMD_COMP	(ICMD_COMP >> 8)
6981da177e4SLinus Torvalds #define  SSI_ITICKLE	(ITICKLE >> 8)
6991da177e4SLinus Torvalds 
7001da177e4SLinus Torvalds #define  SSI_IUNKWN	(IUNKWN >> 8)
7011da177e4SLinus Torvalds #define  SSI_INO_CC	(IUNKWN >> 8)
7021da177e4SLinus Torvalds #define  SSI_IRFAIL	(IUNKWN >> 8)
7031da177e4SLinus Torvalds 
7041da177e4SLinus Torvalds #define  NP    0x10		/*Next Phase */
7051da177e4SLinus Torvalds #define  NTCMD 0x02		/*Non- Tagged Command start */
7061da177e4SLinus Torvalds #define  CMDPZ 0x04		/*Command phase */
7071da177e4SLinus Torvalds #define  DINT  0x12		/*Data Out/In interrupt */
7081da177e4SLinus Torvalds #define  DI    0x13		/*Data Out */
7091da177e4SLinus Torvalds #define  DC    0x19		/*Disconnect Message */
7101da177e4SLinus Torvalds #define  ST    0x1D		/*Status Phase */
7111da177e4SLinus Torvalds #define  UNKNWN 0x24		/*Unknown bus action */
7121da177e4SLinus Torvalds #define  CC    0x25		/*Command Completion failure */
7131da177e4SLinus Torvalds #define  TICK  0x26		/*New target reselected us. */
7141da177e4SLinus Torvalds #define  SELCHK 0x28		/*Select & Check SCSI ID latch reg */
7151da177e4SLinus Torvalds 
7161da177e4SLinus Torvalds #define  ID_MSG_STRT    hp_aramBase + 0x00
7171da177e4SLinus Torvalds #define  NON_TAG_ID_MSG hp_aramBase + 0x06
7181da177e4SLinus Torvalds #define  CMD_STRT       hp_aramBase + 0x08
7191da177e4SLinus Torvalds #define  SYNC_MSGS      hp_aramBase + 0x08
7201da177e4SLinus Torvalds 
7211da177e4SLinus Torvalds #define  TAG_STRT          0x00
7221da177e4SLinus Torvalds #define  DISCONNECT_START  0x10/2
7231da177e4SLinus Torvalds #define  END_DATA_START    0x14/2
7241da177e4SLinus Torvalds #define  CMD_ONLY_STRT     CMDPZ/2
7251da177e4SLinus Torvalds #define  SELCHK_STRT     SELCHK/2
7261da177e4SLinus Torvalds 
7271da177e4SLinus Torvalds #define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
7281da177e4SLinus Torvalds /* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
7291da177e4SLinus Torvalds                                  xfercnt <<= 16,\
730c823feebSAlexey Dobriyan                                  xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0)))
7311da177e4SLinus Torvalds  */
732c823feebSAlexey Dobriyan #define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (unsigned short)(addr & 0x0000FFFFL)),\
7331da177e4SLinus Torvalds          addr >>= 16,\
734c823feebSAlexey Dobriyan          WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\
7351da177e4SLinus Torvalds          WR_HARP32(port,hp_xfercnt_0,count),\
736c823feebSAlexey Dobriyan          WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\
7371da177e4SLinus Torvalds          count >>= 16,\
7381da177e4SLinus Torvalds          WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
7391da177e4SLinus Torvalds 
7401da177e4SLinus Torvalds #define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
7411da177e4SLinus Torvalds                           WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
7421da177e4SLinus Torvalds 
7431da177e4SLinus Torvalds #define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
7441da177e4SLinus Torvalds                           WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}
7451da177e4SLinus Torvalds 
7461da177e4SLinus Torvalds #define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
7471da177e4SLinus Torvalds                         WR_HARPOON(port+hp_scsireset, 0x00))
7481da177e4SLinus Torvalds 
7491da177e4SLinus Torvalds #define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7501da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))
7511da177e4SLinus Torvalds 
7521da177e4SLinus Torvalds #define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7531da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))
7541da177e4SLinus Torvalds 
7551da177e4SLinus Torvalds #define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7561da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))
7571da177e4SLinus Torvalds 
7581da177e4SLinus Torvalds #define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7591da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
7601da177e4SLinus Torvalds 
761391e2f25SKhalid Aziz static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
7625c04a7b8SAlexey Dobriyan 				 unsigned char syncFlag);
763391e2f25SKhalid Aziz static void FPT_ssel(u32 port, unsigned char p_card);
764391e2f25SKhalid Aziz static void FPT_sres(u32 port, unsigned char p_card,
7655c04a7b8SAlexey Dobriyan 		     struct sccb_card *pCurrCard);
766391e2f25SKhalid Aziz static void FPT_shandem(u32 port, unsigned char p_card,
7675c04a7b8SAlexey Dobriyan 			struct sccb *pCurrSCCB);
768391e2f25SKhalid Aziz static void FPT_stsyncn(u32 port, unsigned char p_card);
769391e2f25SKhalid Aziz static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
7705c04a7b8SAlexey Dobriyan 			unsigned char offset);
771391e2f25SKhalid Aziz static void FPT_sssyncv(u32 p_port, unsigned char p_id,
7725c04a7b8SAlexey Dobriyan 			unsigned char p_sync_value,
773f31dc0cdSAlexey Dobriyan 			struct sccb_mgr_tar_info *currTar_Info);
774391e2f25SKhalid Aziz static void FPT_sresb(u32 port, unsigned char p_card);
775391e2f25SKhalid Aziz static void FPT_sxfrp(u32 p_port, unsigned char p_card);
776391e2f25SKhalid Aziz static void FPT_schkdd(u32 port, unsigned char p_card);
777391e2f25SKhalid Aziz static unsigned char FPT_RdStack(u32 port, unsigned char index);
778391e2f25SKhalid Aziz static void FPT_WrStack(u32 portBase, unsigned char index,
7795c04a7b8SAlexey Dobriyan 			unsigned char data);
780391e2f25SKhalid Aziz static unsigned char FPT_ChkIfChipInitialized(u32 ioPort);
7811da177e4SLinus Torvalds 
782391e2f25SKhalid Aziz static void FPT_SendMsg(u32 port, unsigned char message);
783db038cf8SAlexey Dobriyan static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
784db038cf8SAlexey Dobriyan 				   unsigned char error_code);
7851da177e4SLinus Torvalds 
78669eb2ea4SAlexey Dobriyan static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
78768d0c1aeSAlexey Dobriyan static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
7881da177e4SLinus Torvalds 
789391e2f25SKhalid Aziz static unsigned char FPT_siwidn(u32 port, unsigned char p_card);
790391e2f25SKhalid Aziz static void FPT_stwidn(u32 port, unsigned char p_card);
791391e2f25SKhalid Aziz static void FPT_siwidr(u32 port, unsigned char width);
7921da177e4SLinus Torvalds 
7935c04a7b8SAlexey Dobriyan static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
794db038cf8SAlexey Dobriyan 				unsigned char p_card);
7955c04a7b8SAlexey Dobriyan static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card);
7965c04a7b8SAlexey Dobriyan static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
7975c04a7b8SAlexey Dobriyan 				 struct sccb *p_SCCB, unsigned char p_card);
7985c04a7b8SAlexey Dobriyan static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
7995c04a7b8SAlexey Dobriyan 				  unsigned char p_card);
800db038cf8SAlexey Dobriyan static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code);
80169eb2ea4SAlexey Dobriyan static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card);
8025c04a7b8SAlexey Dobriyan static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
8035c04a7b8SAlexey Dobriyan 				       unsigned char p_card);
80469eb2ea4SAlexey Dobriyan static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
805c823feebSAlexey Dobriyan static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
806db038cf8SAlexey Dobriyan static unsigned char FPT_CalcLrc(unsigned char buffer[]);
8071da177e4SLinus Torvalds 
808391e2f25SKhalid Aziz static void FPT_Wait1Second(u32 p_port);
809391e2f25SKhalid Aziz static void FPT_Wait(u32 p_port, unsigned char p_delay);
810391e2f25SKhalid Aziz static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode);
811391e2f25SKhalid Aziz static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
8125c04a7b8SAlexey Dobriyan 			    unsigned short ee_addr);
813391e2f25SKhalid Aziz static unsigned short FPT_utilEERead(u32 p_port,
8145c04a7b8SAlexey Dobriyan 				     unsigned short ee_addr);
815391e2f25SKhalid Aziz static unsigned short FPT_utilEEReadOrg(u32 p_port,
8165c04a7b8SAlexey Dobriyan 					unsigned short ee_addr);
817391e2f25SKhalid Aziz static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
8185c04a7b8SAlexey Dobriyan 				  unsigned short ee_addr);
8191da177e4SLinus Torvalds 
820391e2f25SKhalid Aziz static void FPT_phaseDataOut(u32 port, unsigned char p_card);
821391e2f25SKhalid Aziz static void FPT_phaseDataIn(u32 port, unsigned char p_card);
822391e2f25SKhalid Aziz static void FPT_phaseCommand(u32 port, unsigned char p_card);
823391e2f25SKhalid Aziz static void FPT_phaseStatus(u32 port, unsigned char p_card);
824391e2f25SKhalid Aziz static void FPT_phaseMsgOut(u32 port, unsigned char p_card);
825391e2f25SKhalid Aziz static void FPT_phaseMsgIn(u32 port, unsigned char p_card);
826391e2f25SKhalid Aziz static void FPT_phaseIllegal(u32 port, unsigned char p_card);
8271da177e4SLinus Torvalds 
828391e2f25SKhalid Aziz static void FPT_phaseDecode(u32 port, unsigned char p_card);
829391e2f25SKhalid Aziz static void FPT_phaseChkFifo(u32 port, unsigned char p_card);
830391e2f25SKhalid Aziz static void FPT_phaseBusFree(u32 p_port, unsigned char p_card);
8311da177e4SLinus Torvalds 
832391e2f25SKhalid Aziz static void FPT_XbowInit(u32 port, unsigned char scamFlg);
833391e2f25SKhalid Aziz static void FPT_BusMasterInit(u32 p_port);
834391e2f25SKhalid Aziz static void FPT_DiagEEPROM(u32 p_port);
8351da177e4SLinus Torvalds 
836391e2f25SKhalid Aziz static void FPT_dataXferProcessor(u32 port,
8375c04a7b8SAlexey Dobriyan 				  struct sccb_card *pCurrCard);
838391e2f25SKhalid Aziz static void FPT_busMstrSGDataXferStart(u32 port,
8395c04a7b8SAlexey Dobriyan 				       struct sccb *pCurrSCCB);
840391e2f25SKhalid Aziz static void FPT_busMstrDataXferStart(u32 port,
8415c04a7b8SAlexey Dobriyan 				     struct sccb *pCurrSCCB);
842391e2f25SKhalid Aziz static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
8435c04a7b8SAlexey Dobriyan 				  struct sccb *pCurrSCCB);
84469eb2ea4SAlexey Dobriyan static void FPT_hostDataXferRestart(struct sccb *currSCCB);
8451da177e4SLinus Torvalds 
846391e2f25SKhalid Aziz static unsigned char FPT_SccbMgr_bad_isr(u32 p_port,
8475c04a7b8SAlexey Dobriyan 					 unsigned char p_card,
8485c04a7b8SAlexey Dobriyan 					 struct sccb_card *pCurrCard,
8495c04a7b8SAlexey Dobriyan 					 unsigned short p_int);
8501da177e4SLinus Torvalds 
85147b5d69cSJames Bottomley  static void FPT_SccbMgrTableInitAll(void);
8525c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
8535c04a7b8SAlexey Dobriyan 				     unsigned char p_card);
8545c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
8555c04a7b8SAlexey Dobriyan 				       unsigned char target);
8561da177e4SLinus Torvalds 
8575c04a7b8SAlexey Dobriyan static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
8585c04a7b8SAlexey Dobriyan 		      unsigned char p_power_up);
8591da177e4SLinus Torvalds 
860391e2f25SKhalid Aziz static int FPT_scarb(u32 p_port, unsigned char p_sel_type);
861391e2f25SKhalid Aziz static void FPT_scbusf(u32 p_port);
862391e2f25SKhalid Aziz static void FPT_scsel(u32 p_port);
863391e2f25SKhalid Aziz static void FPT_scasid(unsigned char p_card, u32 p_port);
864391e2f25SKhalid Aziz static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data);
865391e2f25SKhalid Aziz static unsigned char FPT_scsendi(u32 p_port,
8665c04a7b8SAlexey Dobriyan 				 unsigned char p_id_string[]);
867391e2f25SKhalid Aziz static unsigned char FPT_sciso(u32 p_port,
8685c04a7b8SAlexey Dobriyan 			       unsigned char p_id_string[]);
869391e2f25SKhalid Aziz static void FPT_scwirod(u32 p_port, unsigned char p_data_bit);
870391e2f25SKhalid Aziz static void FPT_scwiros(u32 p_port, unsigned char p_data_bit);
871db038cf8SAlexey Dobriyan static unsigned char FPT_scvalq(unsigned char p_quintet);
872391e2f25SKhalid Aziz static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id);
873391e2f25SKhalid Aziz static void FPT_scwtsel(u32 p_port);
874391e2f25SKhalid Aziz static void FPT_inisci(unsigned char p_card, u32 p_port,
8755c04a7b8SAlexey Dobriyan 		       unsigned char p_our_id);
876391e2f25SKhalid Aziz static void FPT_scsavdi(unsigned char p_card, u32 p_port);
8775c04a7b8SAlexey Dobriyan static unsigned char FPT_scmachid(unsigned char p_card,
8785c04a7b8SAlexey Dobriyan 				  unsigned char p_id_string[]);
8791da177e4SLinus Torvalds 
880391e2f25SKhalid Aziz static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card);
881391e2f25SKhalid Aziz static void FPT_autoLoadDefaultMap(u32 p_port);
8821da177e4SLinus Torvalds 
8835c04a7b8SAlexey Dobriyan static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
8845c04a7b8SAlexey Dobriyan     { {{0}} };
88513e6851aSAlexey Dobriyan static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} };
88647b5d69cSJames Bottomley  static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} };
88768d0c1aeSAlexey Dobriyan static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} };
8881da177e4SLinus Torvalds 
889db038cf8SAlexey Dobriyan static unsigned char FPT_mbCards = 0;
8905c04a7b8SAlexey Dobriyan static unsigned char FPT_scamHAString[] =
8915c04a7b8SAlexey Dobriyan     { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C',
8925c04a7b8SAlexey Dobriyan 	' ', 'B', 'T', '-', '9', '3', '0',
8935c04a7b8SAlexey Dobriyan 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
8945c04a7b8SAlexey Dobriyan 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
8955c04a7b8SAlexey Dobriyan };
8961da177e4SLinus Torvalds 
897c823feebSAlexey Dobriyan static unsigned short FPT_default_intena = 0;
8981da177e4SLinus Torvalds 
899391e2f25SKhalid Aziz static void (*FPT_s_PhaseTbl[8]) (u32, unsigned char) = {
9005c04a7b8SAlexey Dobriyan 0};
9011da177e4SLinus Torvalds 
9021da177e4SLinus Torvalds /*---------------------------------------------------------------------
9031da177e4SLinus Torvalds  *
904d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_ProbeHostAdapter
9051da177e4SLinus Torvalds  *
9061da177e4SLinus Torvalds  * Description: Setup and/or Search for cards and return info to caller.
9071da177e4SLinus Torvalds  *
9081da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
9091da177e4SLinus Torvalds 
FlashPoint_ProbeHostAdapter(struct sccb_mgr_info * pCardInfo)9107f101662SAlexey Dobriyan static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
9111da177e4SLinus Torvalds {
912db038cf8SAlexey Dobriyan 	static unsigned char first_time = 1;
9131da177e4SLinus Torvalds 
914db038cf8SAlexey Dobriyan 	unsigned char i, j, id, ScamFlg;
915c823feebSAlexey Dobriyan 	unsigned short temp, temp2, temp3, temp4, temp5, temp6;
916391e2f25SKhalid Aziz 	u32 ioport;
91768d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
9181da177e4SLinus Torvalds 
9191da177e4SLinus Torvalds 	ioport = pCardInfo->si_baseaddr;
9201da177e4SLinus Torvalds 
9211da177e4SLinus Torvalds 	if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0)
9225c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9231da177e4SLinus Torvalds 
9241da177e4SLinus Torvalds 	if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1))
9255c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9261da177e4SLinus Torvalds 
9271da177e4SLinus Torvalds 	if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0))
9285c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9291da177e4SLinus Torvalds 
9301da177e4SLinus Torvalds 	if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1))
9315c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9321da177e4SLinus Torvalds 
9331da177e4SLinus Torvalds 	if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) {
9341da177e4SLinus Torvalds 
9351da177e4SLinus Torvalds /* For new Harpoon then check for sub_device ID LSB
9361da177e4SLinus Torvalds    the bits(0-3) must be all ZERO for compatible with
9371da177e4SLinus Torvalds    current version of SCCBMgr, else skip this Harpoon
9381da177e4SLinus Torvalds 	device. */
9391da177e4SLinus Torvalds 
9401da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f)
9415c1b85e2SAlexey Dobriyan 			return (int)FAILURE;
9421da177e4SLinus Torvalds 	}
9431da177e4SLinus Torvalds 
9445c04a7b8SAlexey Dobriyan 	if (first_time) {
94547b5d69cSJames Bottomley  		FPT_SccbMgrTableInitAll();
9461da177e4SLinus Torvalds 		first_time = 0;
94747b5d69cSJames Bottomley  		FPT_mbCards = 0;
9481da177e4SLinus Torvalds 	}
9491da177e4SLinus Torvalds 
95047b5d69cSJames Bottomley  	if (FPT_RdStack(ioport, 0) != 0x00) {
9515c04a7b8SAlexey Dobriyan 		if (FPT_ChkIfChipInitialized(ioport) == 0) {
9521da177e4SLinus Torvalds 			pCurrNvRam = NULL;
9531da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_semaphore, 0x00);
95447b5d69cSJames Bottomley  			FPT_XbowInit(ioport, 0);	/*Must Init the SCSI before attempting */
95547b5d69cSJames Bottomley  			FPT_DiagEEPROM(ioport);
9565c04a7b8SAlexey Dobriyan 		} else {
95747b5d69cSJames Bottomley  			if (FPT_mbCards < MAX_MB_CARDS) {
95847b5d69cSJames Bottomley  				pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
95947b5d69cSJames Bottomley  				FPT_mbCards++;
9601da177e4SLinus Torvalds 				pCurrNvRam->niBaseAddr = ioport;
96147b5d69cSJames Bottomley  				FPT_RNVRamData(pCurrNvRam);
9621da177e4SLinus Torvalds 			} else
9635c1b85e2SAlexey Dobriyan 				return (int)FAILURE;
9641da177e4SLinus Torvalds 		}
9651da177e4SLinus Torvalds 	} else
9661da177e4SLinus Torvalds 		pCurrNvRam = NULL;
9671da177e4SLinus Torvalds 
9681da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
9691da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
9701da177e4SLinus Torvalds 
9711da177e4SLinus Torvalds 	if (pCurrNvRam)
9721da177e4SLinus Torvalds 		pCardInfo->si_id = pCurrNvRam->niAdapId;
9731da177e4SLinus Torvalds 	else
9745c04a7b8SAlexey Dobriyan 		pCardInfo->si_id =
9755c04a7b8SAlexey Dobriyan 		    (unsigned
9765c04a7b8SAlexey Dobriyan 		     char)(FPT_utilEERead(ioport,
9775c04a7b8SAlexey Dobriyan 					  (ADAPTER_SCSI_ID /
9785c04a7b8SAlexey Dobriyan 					   2)) & (unsigned char)0x0FF);
9791da177e4SLinus Torvalds 
9801da177e4SLinus Torvalds 	pCardInfo->si_lun = 0x00;
9811da177e4SLinus Torvalds 	pCardInfo->si_fw_revision = ORION_FW_REV;
9821da177e4SLinus Torvalds 	temp2 = 0x0000;
9831da177e4SLinus Torvalds 	temp3 = 0x0000;
9841da177e4SLinus Torvalds 	temp4 = 0x0000;
9851da177e4SLinus Torvalds 	temp5 = 0x0000;
9861da177e4SLinus Torvalds 	temp6 = 0x0000;
9871da177e4SLinus Torvalds 
9881da177e4SLinus Torvalds 	for (id = 0; id < (16 / 2); id++) {
9891da177e4SLinus Torvalds 
9901da177e4SLinus Torvalds 		if (pCurrNvRam) {
991c823feebSAlexey Dobriyan 			temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
9921da177e4SLinus Torvalds 			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
9931da177e4SLinus Torvalds 			    (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
9941da177e4SLinus Torvalds 		} else
9955c04a7b8SAlexey Dobriyan 			temp =
9965c04a7b8SAlexey Dobriyan 			    FPT_utilEERead(ioport,
9975c04a7b8SAlexey Dobriyan 					   (unsigned short)((SYNC_RATE_TBL / 2)
9985c04a7b8SAlexey Dobriyan 							    + id));
9991da177e4SLinus Torvalds 
10001da177e4SLinus Torvalds 		for (i = 0; i < 2; temp >>= 8, i++) {
10011da177e4SLinus Torvalds 
10021da177e4SLinus Torvalds 			temp2 >>= 1;
10031da177e4SLinus Torvalds 			temp3 >>= 1;
10041da177e4SLinus Torvalds 			temp4 >>= 1;
10051da177e4SLinus Torvalds 			temp5 >>= 1;
10061da177e4SLinus Torvalds 			temp6 >>= 1;
10075c04a7b8SAlexey Dobriyan 			switch (temp & 0x3) {
10081da177e4SLinus Torvalds 			case AUTO_RATE_20:	/* Synchronous, 20 mega-transfers/second */
1009df561f66SGustavo A. R. Silva 				temp6 |= 0x8000;
1010df561f66SGustavo A. R. Silva 				fallthrough;
10111da177e4SLinus Torvalds 			case AUTO_RATE_10:	/* Synchronous, 10 mega-transfers/second */
1012df561f66SGustavo A. R. Silva 				temp5 |= 0x8000;
1013df561f66SGustavo A. R. Silva 				fallthrough;
10141da177e4SLinus Torvalds 			case AUTO_RATE_05:	/* Synchronous, 5 mega-transfers/second */
1015df561f66SGustavo A. R. Silva 				temp2 |= 0x8000;
1016df561f66SGustavo A. R. Silva 				fallthrough;
10171da177e4SLinus Torvalds 			case AUTO_RATE_00:	/* Asynchronous */
10181da177e4SLinus Torvalds 				break;
10191da177e4SLinus Torvalds 			}
10201da177e4SLinus Torvalds 
10211da177e4SLinus Torvalds 			if (temp & DISC_ENABLE_BIT)
10221da177e4SLinus Torvalds 				temp3 |= 0x8000;
10231da177e4SLinus Torvalds 
10241da177e4SLinus Torvalds 			if (temp & WIDE_NEGO_BIT)
10251da177e4SLinus Torvalds 				temp4 |= 0x8000;
10261da177e4SLinus Torvalds 
10271da177e4SLinus Torvalds 		}
10281da177e4SLinus Torvalds 	}
10291da177e4SLinus Torvalds 
10301da177e4SLinus Torvalds 	pCardInfo->si_per_targ_init_sync = temp2;
10311da177e4SLinus Torvalds 	pCardInfo->si_per_targ_no_disc = temp3;
10321da177e4SLinus Torvalds 	pCardInfo->si_per_targ_wide_nego = temp4;
10331da177e4SLinus Torvalds 	pCardInfo->si_per_targ_fast_nego = temp5;
10341da177e4SLinus Torvalds 	pCardInfo->si_per_targ_ultra_nego = temp6;
10351da177e4SLinus Torvalds 
10361da177e4SLinus Torvalds 	if (pCurrNvRam)
10371da177e4SLinus Torvalds 		i = pCurrNvRam->niSysConf;
10381da177e4SLinus Torvalds 	else
10395c04a7b8SAlexey Dobriyan 		i = (unsigned
10405c04a7b8SAlexey Dobriyan 		     char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
10411da177e4SLinus Torvalds 
10421da177e4SLinus Torvalds 	if (pCurrNvRam)
10431da177e4SLinus Torvalds 		ScamFlg = pCurrNvRam->niScamConf;
10441da177e4SLinus Torvalds 	else
10455c04a7b8SAlexey Dobriyan 		ScamFlg =
10465c04a7b8SAlexey Dobriyan 		    (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
10471da177e4SLinus Torvalds 
10484d431153SRandy Dunlap 	pCardInfo->si_mflags = 0x0000;
10491da177e4SLinus Torvalds 
10501da177e4SLinus Torvalds 	if (i & 0x01)
10514d431153SRandy Dunlap 		pCardInfo->si_mflags |= SCSI_PARITY_ENA;
10521da177e4SLinus Torvalds 
10531da177e4SLinus Torvalds 	if (!(i & 0x02))
10544d431153SRandy Dunlap 		pCardInfo->si_mflags |= SOFT_RESET;
10551da177e4SLinus Torvalds 
10561da177e4SLinus Torvalds 	if (i & 0x10)
10574d431153SRandy Dunlap 		pCardInfo->si_mflags |= EXTENDED_TRANSLATION;
10581da177e4SLinus Torvalds 
10591da177e4SLinus Torvalds 	if (ScamFlg & SCAM_ENABLED)
10604d431153SRandy Dunlap 		pCardInfo->si_mflags |= FLAG_SCAM_ENABLED;
10611da177e4SLinus Torvalds 
10621da177e4SLinus Torvalds 	if (ScamFlg & SCAM_LEVEL2)
10634d431153SRandy Dunlap 		pCardInfo->si_mflags |= FLAG_SCAM_LEVEL2;
10641da177e4SLinus Torvalds 
10651da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
10661da177e4SLinus Torvalds 	if (i & 0x04) {
10671da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_L;
10681da177e4SLinus Torvalds 	}
10691da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_bm_ctrl, j);
10701da177e4SLinus Torvalds 
10711da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
10721da177e4SLinus Torvalds 	if (i & 0x08) {
10731da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_H;
10741da177e4SLinus Torvalds 	}
10751da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_ee_ctrl, j);
10761da177e4SLinus Torvalds 
10771da177e4SLinus Torvalds 	if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
10781da177e4SLinus Torvalds 
10794d431153SRandy Dunlap 		pCardInfo->si_mflags |= SUPPORT_16TAR_32LUN;
10801da177e4SLinus Torvalds 
10811da177e4SLinus Torvalds 	pCardInfo->si_card_family = HARPOON_FAMILY;
10821da177e4SLinus Torvalds 	pCardInfo->si_bustype = BUSTYPE_PCI;
10831da177e4SLinus Torvalds 
10841da177e4SLinus Torvalds 	if (pCurrNvRam) {
10851da177e4SLinus Torvalds 		pCardInfo->si_card_model[0] = '9';
10861da177e4SLinus Torvalds 		switch (pCurrNvRam->niModel & 0x0f) {
10871da177e4SLinus Torvalds 		case MODEL_LT:
10881da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '3';
10891da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '0';
10901da177e4SLinus Torvalds 			break;
10911da177e4SLinus Torvalds 		case MODEL_LW:
10921da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '5';
10931da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '0';
10941da177e4SLinus Torvalds 			break;
10951da177e4SLinus Torvalds 		case MODEL_DL:
10961da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '3';
10971da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '2';
10981da177e4SLinus Torvalds 			break;
10991da177e4SLinus Torvalds 		case MODEL_DW:
11001da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '5';
11011da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '2';
11021da177e4SLinus Torvalds 			break;
11031da177e4SLinus Torvalds 		}
11041da177e4SLinus Torvalds 	} else {
110547b5d69cSJames Bottomley  		temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1106db038cf8SAlexey Dobriyan 		pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
110747b5d69cSJames Bottomley  		temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
11081da177e4SLinus Torvalds 
1109db038cf8SAlexey Dobriyan 		pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1110db038cf8SAlexey Dobriyan 		pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
11111da177e4SLinus Torvalds 	}
11121da177e4SLinus Torvalds 
11135c04a7b8SAlexey Dobriyan 	if (pCardInfo->si_card_model[1] == '3') {
11141da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
11154d431153SRandy Dunlap 			pCardInfo->si_mflags |= LOW_BYTE_TERM;
11165c04a7b8SAlexey Dobriyan 	} else if (pCardInfo->si_card_model[2] == '0') {
11171da177e4SLinus Torvalds 		temp = RD_HARPOON(ioport + hp_xfer_pad);
11181da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
11191da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
11204d431153SRandy Dunlap 			pCardInfo->si_mflags |= LOW_BYTE_TERM;
11211da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
11221da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
11234d431153SRandy Dunlap 			pCardInfo->si_mflags |= HIGH_BYTE_TERM;
11241da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, temp);
11255c04a7b8SAlexey Dobriyan 	} else {
11261da177e4SLinus Torvalds 		temp = RD_HARPOON(ioport + hp_ee_ctrl);
11271da177e4SLinus Torvalds 		temp2 = RD_HARPOON(ioport + hp_xfer_pad);
11281da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
11291da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
11301da177e4SLinus Torvalds 		temp3 = 0;
11315c04a7b8SAlexey Dobriyan 		for (i = 0; i < 8; i++) {
11321da177e4SLinus Torvalds 			temp3 <<= 1;
11331da177e4SLinus Torvalds 			if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
11341da177e4SLinus Torvalds 				temp3 |= 1;
11351da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
11361da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
11371da177e4SLinus Torvalds 		}
11381da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_ee_ctrl, temp);
11391da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, temp2);
11401da177e4SLinus Torvalds 		if (!(temp3 & BIT(7)))
11414d431153SRandy Dunlap 			pCardInfo->si_mflags |= LOW_BYTE_TERM;
11421da177e4SLinus Torvalds 		if (!(temp3 & BIT(6)))
11434d431153SRandy Dunlap 			pCardInfo->si_mflags |= HIGH_BYTE_TERM;
11441da177e4SLinus Torvalds 	}
11451da177e4SLinus Torvalds 
11461da177e4SLinus Torvalds 	ARAM_ACCESS(ioport);
11471da177e4SLinus Torvalds 
11481da177e4SLinus Torvalds 	for (i = 0; i < 4; i++) {
11491da177e4SLinus Torvalds 
11501da177e4SLinus Torvalds 		pCardInfo->si_XlatInfo[i] =
11511da177e4SLinus Torvalds 		    RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
11521da177e4SLinus Torvalds 	}
11531da177e4SLinus Torvalds 
11541da177e4SLinus Torvalds 	/* return with -1 if no sort, else return with
11551da177e4SLinus Torvalds 	   logical card number sorted by BIOS (zero-based) */
11561da177e4SLinus Torvalds 
11571da177e4SLinus Torvalds 	pCardInfo->si_relative_cardnum =
11585c04a7b8SAlexey Dobriyan 	    (unsigned
11595c04a7b8SAlexey Dobriyan 	     char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
11601da177e4SLinus Torvalds 
11611da177e4SLinus Torvalds 	SGRAM_ACCESS(ioport);
11621da177e4SLinus Torvalds 
116347b5d69cSJames Bottomley  	FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
116447b5d69cSJames Bottomley  	FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
116547b5d69cSJames Bottomley  	FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
116647b5d69cSJames Bottomley  	FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
116747b5d69cSJames Bottomley  	FPT_s_PhaseTbl[4] = FPT_phaseCommand;
116847b5d69cSJames Bottomley  	FPT_s_PhaseTbl[5] = FPT_phaseStatus;
116947b5d69cSJames Bottomley  	FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
117047b5d69cSJames Bottomley  	FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
11711da177e4SLinus Torvalds 
11721da177e4SLinus Torvalds 	pCardInfo->si_present = 0x01;
11731da177e4SLinus Torvalds 
11745c1b85e2SAlexey Dobriyan 	return 0;
11751da177e4SLinus Torvalds }
11761da177e4SLinus Torvalds 
11771da177e4SLinus Torvalds /*---------------------------------------------------------------------
11781da177e4SLinus Torvalds  *
1179d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_HardwareResetHostAdapter
11801da177e4SLinus Torvalds  *
11811da177e4SLinus Torvalds  * Description: Setup adapter for normal operation (hard reset).
11821da177e4SLinus Torvalds  *
11831da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
11841da177e4SLinus Torvalds 
FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info * pCardInfo)1185391e2f25SKhalid Aziz static void *FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
11865c04a7b8SAlexey Dobriyan 							 *pCardInfo)
11871da177e4SLinus Torvalds {
118813e6851aSAlexey Dobriyan 	struct sccb_card *CurrCard = NULL;
118968d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
1190db038cf8SAlexey Dobriyan 	unsigned char i, j, thisCard, ScamFlg;
1191c823feebSAlexey Dobriyan 	unsigned short temp, sync_bit_map, id;
1192391e2f25SKhalid Aziz 	u32 ioport;
11931da177e4SLinus Torvalds 
11941da177e4SLinus Torvalds 	ioport = pCardInfo->si_baseaddr;
11951da177e4SLinus Torvalds 
11961da177e4SLinus Torvalds 	for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
11971da177e4SLinus Torvalds 
1198391e2f25SKhalid Aziz 		if (thisCard == MAX_CARDS)
1199391e2f25SKhalid Aziz 			return (void *)FAILURE;
12001da177e4SLinus Torvalds 
120147b5d69cSJames Bottomley  		if (FPT_BL_Card[thisCard].ioPort == ioport) {
12021da177e4SLinus Torvalds 
120347b5d69cSJames Bottomley  			CurrCard = &FPT_BL_Card[thisCard];
120447b5d69cSJames Bottomley  			FPT_SccbMgrTableInitCard(CurrCard, thisCard);
12051da177e4SLinus Torvalds 			break;
12061da177e4SLinus Torvalds 		}
12071da177e4SLinus Torvalds 
120847b5d69cSJames Bottomley  		else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
12091da177e4SLinus Torvalds 
121047b5d69cSJames Bottomley  			FPT_BL_Card[thisCard].ioPort = ioport;
121147b5d69cSJames Bottomley  			CurrCard = &FPT_BL_Card[thisCard];
12121da177e4SLinus Torvalds 
121347b5d69cSJames Bottomley  			if (FPT_mbCards)
121447b5d69cSJames Bottomley  				for (i = 0; i < FPT_mbCards; i++) {
12155c04a7b8SAlexey Dobriyan 					if (CurrCard->ioPort ==
12165c04a7b8SAlexey Dobriyan 					    FPT_nvRamInfo[i].niBaseAddr)
12175c04a7b8SAlexey Dobriyan 						CurrCard->pNvRamInfo =
12185c04a7b8SAlexey Dobriyan 						    &FPT_nvRamInfo[i];
12191da177e4SLinus Torvalds 				}
122047b5d69cSJames Bottomley  			FPT_SccbMgrTableInitCard(CurrCard, thisCard);
12211da177e4SLinus Torvalds 			CurrCard->cardIndex = thisCard;
12221da177e4SLinus Torvalds 			CurrCard->cardInfo = pCardInfo;
12231da177e4SLinus Torvalds 
12241da177e4SLinus Torvalds 			break;
12251da177e4SLinus Torvalds 		}
12261da177e4SLinus Torvalds 	}
12271da177e4SLinus Torvalds 
12281da177e4SLinus Torvalds 	pCurrNvRam = CurrCard->pNvRamInfo;
12291da177e4SLinus Torvalds 
12301da177e4SLinus Torvalds 	if (pCurrNvRam) {
12311da177e4SLinus Torvalds 		ScamFlg = pCurrNvRam->niScamConf;
12325c04a7b8SAlexey Dobriyan 	} else {
12335c04a7b8SAlexey Dobriyan 		ScamFlg =
12345c04a7b8SAlexey Dobriyan 		    (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
12351da177e4SLinus Torvalds 	}
12361da177e4SLinus Torvalds 
123747b5d69cSJames Bottomley  	FPT_BusMasterInit(ioport);
123847b5d69cSJames Bottomley  	FPT_XbowInit(ioport, ScamFlg);
12391da177e4SLinus Torvalds 
124047b5d69cSJames Bottomley  	FPT_autoLoadDefaultMap(ioport);
12411da177e4SLinus Torvalds 
12425c04a7b8SAlexey Dobriyan 	for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
12435c04a7b8SAlexey Dobriyan 	}
12441da177e4SLinus Torvalds 
12451da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_selfid_0, id);
12461da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_selfid_1, 0x00);
12471da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
12481da177e4SLinus Torvalds 	CurrCard->ourId = pCardInfo->si_id;
12491da177e4SLinus Torvalds 
12504d431153SRandy Dunlap 	i = (unsigned char)pCardInfo->si_mflags;
12511da177e4SLinus Torvalds 	if (i & SCSI_PARITY_ENA)
12521da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
12531da177e4SLinus Torvalds 
12541da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
12551da177e4SLinus Torvalds 	if (i & LOW_BYTE_TERM)
12561da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_L;
12571da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_bm_ctrl, j);
12581da177e4SLinus Torvalds 
12591da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
12601da177e4SLinus Torvalds 	if (i & HIGH_BYTE_TERM)
12611da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_H;
12621da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_ee_ctrl, j);
12631da177e4SLinus Torvalds 
12644d431153SRandy Dunlap 	if (!(pCardInfo->si_mflags & SOFT_RESET)) {
12651da177e4SLinus Torvalds 
126647b5d69cSJames Bottomley  		FPT_sresb(ioport, thisCard);
12671da177e4SLinus Torvalds 
126847b5d69cSJames Bottomley  		FPT_scini(thisCard, pCardInfo->si_id, 0);
12691da177e4SLinus Torvalds 	}
12701da177e4SLinus Torvalds 
12714d431153SRandy Dunlap 	if (pCardInfo->si_mflags & POST_ALL_UNDERRRUNS)
12721da177e4SLinus Torvalds 		CurrCard->globalFlags |= F_NO_FILTER;
12731da177e4SLinus Torvalds 
12741da177e4SLinus Torvalds 	if (pCurrNvRam) {
12751da177e4SLinus Torvalds 		if (pCurrNvRam->niSysConf & 0x10)
12761da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_GREEN_PC;
12775c04a7b8SAlexey Dobriyan 	} else {
127847b5d69cSJames Bottomley  		if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
12791da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_GREEN_PC;
12801da177e4SLinus Torvalds 	}
12811da177e4SLinus Torvalds 
12821da177e4SLinus Torvalds 	/* Set global flag to indicate Re-Negotiation to be done on all
12831da177e4SLinus Torvalds 	   ckeck condition */
12841da177e4SLinus Torvalds 	if (pCurrNvRam) {
12851da177e4SLinus Torvalds 		if (pCurrNvRam->niScsiConf & 0x04)
12861da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_DO_RENEGO;
12875c04a7b8SAlexey Dobriyan 	} else {
128847b5d69cSJames Bottomley  		if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
12891da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_DO_RENEGO;
12901da177e4SLinus Torvalds 	}
12911da177e4SLinus Torvalds 
12921da177e4SLinus Torvalds 	if (pCurrNvRam) {
12931da177e4SLinus Torvalds 		if (pCurrNvRam->niScsiConf & 0x08)
12941da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_CONLUN_IO;
12955c04a7b8SAlexey Dobriyan 	} else {
129647b5d69cSJames Bottomley  		if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
12971da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_CONLUN_IO;
12981da177e4SLinus Torvalds 	}
12991da177e4SLinus Torvalds 
13001da177e4SLinus Torvalds 	temp = pCardInfo->si_per_targ_no_disc;
13011da177e4SLinus Torvalds 
13021da177e4SLinus Torvalds 	for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
13031da177e4SLinus Torvalds 
13041da177e4SLinus Torvalds 		if (temp & id)
130547b5d69cSJames Bottomley  			FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
13061da177e4SLinus Torvalds 	}
13071da177e4SLinus Torvalds 
13081da177e4SLinus Torvalds 	sync_bit_map = 0x0001;
13091da177e4SLinus Torvalds 
13101da177e4SLinus Torvalds 	for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
13111da177e4SLinus Torvalds 
13121da177e4SLinus Torvalds 		if (pCurrNvRam) {
1313c823feebSAlexey Dobriyan 			temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
13141da177e4SLinus Torvalds 			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
13151da177e4SLinus Torvalds 			    (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
13161da177e4SLinus Torvalds 		} else
13175c04a7b8SAlexey Dobriyan 			temp =
13185c04a7b8SAlexey Dobriyan 			    FPT_utilEERead(ioport,
13195c04a7b8SAlexey Dobriyan 					   (unsigned short)((SYNC_RATE_TBL / 2)
13205c04a7b8SAlexey Dobriyan 							    + id));
13211da177e4SLinus Torvalds 
13221da177e4SLinus Torvalds 		for (i = 0; i < 2; temp >>= 8, i++) {
13231da177e4SLinus Torvalds 
13241da177e4SLinus Torvalds 			if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
13251da177e4SLinus Torvalds 
13265c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13275c04a7b8SAlexey Dobriyan 							 i].TarEEValue =
13285c04a7b8SAlexey Dobriyan 				    (unsigned char)temp;
13291da177e4SLinus Torvalds 			}
13301da177e4SLinus Torvalds 
13311da177e4SLinus Torvalds 			else {
13325c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13335c04a7b8SAlexey Dobriyan 							 i].TarStatus |=
13345c04a7b8SAlexey Dobriyan 				    SYNC_SUPPORTED;
13355c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13365c04a7b8SAlexey Dobriyan 							 i].TarEEValue =
1337db038cf8SAlexey Dobriyan 				    (unsigned char)(temp & ~EE_SYNC_MASK);
13381da177e4SLinus Torvalds 			}
13391da177e4SLinus Torvalds 
13401da177e4SLinus Torvalds /*         if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
13411da177e4SLinus Torvalds             (id*2+i >= 8)){
13421da177e4SLinus Torvalds */
13431da177e4SLinus Torvalds 			if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
13441da177e4SLinus Torvalds 
13455c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13465c04a7b8SAlexey Dobriyan 							 i].TarEEValue |=
13475c04a7b8SAlexey Dobriyan 				    EE_WIDE_SCSI;
13481da177e4SLinus Torvalds 
13491da177e4SLinus Torvalds 			}
13501da177e4SLinus Torvalds 
13511da177e4SLinus Torvalds 			else {	/* NARROW SCSI */
13525c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13535c04a7b8SAlexey Dobriyan 							 i].TarStatus |=
13545c04a7b8SAlexey Dobriyan 				    WIDE_NEGOCIATED;
13551da177e4SLinus Torvalds 			}
13561da177e4SLinus Torvalds 
13571da177e4SLinus Torvalds 			sync_bit_map <<= 1;
13581da177e4SLinus Torvalds 
13591da177e4SLinus Torvalds 		}
13601da177e4SLinus Torvalds 	}
13611da177e4SLinus Torvalds 
13621da177e4SLinus Torvalds 	WR_HARPOON((ioport + hp_semaphore),
13635c04a7b8SAlexey Dobriyan 		   (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
13645c04a7b8SAlexey Dobriyan 				   SCCB_MGR_PRESENT));
13651da177e4SLinus Torvalds 
1366391e2f25SKhalid Aziz 	return (void *)CurrCard;
13671da177e4SLinus Torvalds }
13681da177e4SLinus Torvalds 
FlashPoint_ReleaseHostAdapter(void * pCurrCard)1369391e2f25SKhalid Aziz static void FlashPoint_ReleaseHostAdapter(void *pCurrCard)
13701da177e4SLinus Torvalds {
1371db038cf8SAlexey Dobriyan 	unsigned char i;
1372391e2f25SKhalid Aziz 	u32 portBase;
1373391e2f25SKhalid Aziz 	u32 regOffset;
1374391e2f25SKhalid Aziz 	u32 scamData;
1375391e2f25SKhalid Aziz 	u32 *pScamTbl;
137668d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
13771da177e4SLinus Torvalds 
137813e6851aSAlexey Dobriyan 	pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
13791da177e4SLinus Torvalds 
13801da177e4SLinus Torvalds 	if (pCurrNvRam) {
138147b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
138247b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
138347b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
138447b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
138547b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
13861da177e4SLinus Torvalds 
13871da177e4SLinus Torvalds 		for (i = 0; i < MAX_SCSI_TAR / 2; i++)
13885c04a7b8SAlexey Dobriyan 			FPT_WrStack(pCurrNvRam->niBaseAddr,
13895c04a7b8SAlexey Dobriyan 				    (unsigned char)(i + 5),
13905c04a7b8SAlexey Dobriyan 				    pCurrNvRam->niSyncTbl[i]);
13911da177e4SLinus Torvalds 
13921da177e4SLinus Torvalds 		portBase = pCurrNvRam->niBaseAddr;
13931da177e4SLinus Torvalds 
13941da177e4SLinus Torvalds 		for (i = 0; i < MAX_SCSI_TAR; i++) {
13951da177e4SLinus Torvalds 			regOffset = hp_aramBase + 64 + i * 4;
1396391e2f25SKhalid Aziz 			pScamTbl = (u32 *)&pCurrNvRam->niScamTbl[i];
13971da177e4SLinus Torvalds 			scamData = *pScamTbl;
13981da177e4SLinus Torvalds 			WR_HARP32(portBase, regOffset, scamData);
13991da177e4SLinus Torvalds 		}
14001da177e4SLinus Torvalds 
14011da177e4SLinus Torvalds 	} else {
140213e6851aSAlexey Dobriyan 		FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
14031da177e4SLinus Torvalds 	}
14041da177e4SLinus Torvalds }
14051da177e4SLinus Torvalds 
FPT_RNVRamData(struct nvram_info * pNvRamInfo)140668d0c1aeSAlexey Dobriyan static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
14071da177e4SLinus Torvalds {
1408db038cf8SAlexey Dobriyan 	unsigned char i;
1409391e2f25SKhalid Aziz 	u32 portBase;
1410391e2f25SKhalid Aziz 	u32 regOffset;
1411391e2f25SKhalid Aziz 	u32 scamData;
1412391e2f25SKhalid Aziz 	u32 *pScamTbl;
14131da177e4SLinus Torvalds 
141447b5d69cSJames Bottomley  	pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
141547b5d69cSJames Bottomley  	pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
141647b5d69cSJames Bottomley  	pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
141747b5d69cSJames Bottomley  	pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
141847b5d69cSJames Bottomley  	pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
14191da177e4SLinus Torvalds 
14201da177e4SLinus Torvalds 	for (i = 0; i < MAX_SCSI_TAR / 2; i++)
14215c04a7b8SAlexey Dobriyan 		pNvRamInfo->niSyncTbl[i] =
14225c04a7b8SAlexey Dobriyan 		    FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
14231da177e4SLinus Torvalds 
14241da177e4SLinus Torvalds 	portBase = pNvRamInfo->niBaseAddr;
14251da177e4SLinus Torvalds 
14261da177e4SLinus Torvalds 	for (i = 0; i < MAX_SCSI_TAR; i++) {
14271da177e4SLinus Torvalds 		regOffset = hp_aramBase + 64 + i * 4;
14281da177e4SLinus Torvalds 		RD_HARP32(portBase, regOffset, scamData);
1429391e2f25SKhalid Aziz 		pScamTbl = (u32 *)&pNvRamInfo->niScamTbl[i];
14301da177e4SLinus Torvalds 		*pScamTbl = scamData;
14311da177e4SLinus Torvalds 	}
14321da177e4SLinus Torvalds 
14331da177e4SLinus Torvalds }
14341da177e4SLinus Torvalds 
FPT_RdStack(u32 portBase,unsigned char index)1435391e2f25SKhalid Aziz static unsigned char FPT_RdStack(u32 portBase, unsigned char index)
14361da177e4SLinus Torvalds {
14371da177e4SLinus Torvalds 	WR_HARPOON(portBase + hp_stack_addr, index);
14385c1b85e2SAlexey Dobriyan 	return RD_HARPOON(portBase + hp_stack_data);
14391da177e4SLinus Torvalds }
14401da177e4SLinus Torvalds 
FPT_WrStack(u32 portBase,unsigned char index,unsigned char data)1441391e2f25SKhalid Aziz static void FPT_WrStack(u32 portBase, unsigned char index, unsigned char data)
14421da177e4SLinus Torvalds {
14431da177e4SLinus Torvalds 	WR_HARPOON(portBase + hp_stack_addr, index);
14441da177e4SLinus Torvalds 	WR_HARPOON(portBase + hp_stack_data, data);
14451da177e4SLinus Torvalds }
14461da177e4SLinus Torvalds 
FPT_ChkIfChipInitialized(u32 ioPort)1447391e2f25SKhalid Aziz static unsigned char FPT_ChkIfChipInitialized(u32 ioPort)
14481da177e4SLinus Torvalds {
144947b5d69cSJames Bottomley  	if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
14505c1b85e2SAlexey Dobriyan 		return 0;
14511da177e4SLinus Torvalds 	if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
14521da177e4SLinus Torvalds 	    != CLKCTRL_DEFAULT)
14535c1b85e2SAlexey Dobriyan 		return 0;
14541da177e4SLinus Torvalds 	if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
14551da177e4SLinus Torvalds 	    (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
14565c1b85e2SAlexey Dobriyan 		return 1;
14575c1b85e2SAlexey Dobriyan 	return 0;
14581da177e4SLinus Torvalds 
14591da177e4SLinus Torvalds }
14605c04a7b8SAlexey Dobriyan 
14611da177e4SLinus Torvalds /*---------------------------------------------------------------------
14621da177e4SLinus Torvalds  *
1463d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_StartCCB
14641da177e4SLinus Torvalds  *
14651da177e4SLinus Torvalds  * Description: Start a command pointed to by p_Sccb. When the
14661da177e4SLinus Torvalds  *              command is completed it will be returned via the
14671da177e4SLinus Torvalds  *              callback function.
14681da177e4SLinus Torvalds  *
14691da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FlashPoint_StartCCB(void * curr_card,struct sccb * p_Sccb)1470391e2f25SKhalid Aziz static void FlashPoint_StartCCB(void *curr_card, struct sccb *p_Sccb)
14711da177e4SLinus Torvalds {
1472391e2f25SKhalid Aziz 	u32 ioport;
1473db038cf8SAlexey Dobriyan 	unsigned char thisCard, lun;
147469eb2ea4SAlexey Dobriyan 	struct sccb *pSaveSccb;
14751da177e4SLinus Torvalds 	CALL_BK_FN callback;
1476391e2f25SKhalid Aziz 	struct sccb_card *pCurrCard = curr_card;
14771da177e4SLinus Torvalds 
1478391e2f25SKhalid Aziz 	thisCard = pCurrCard->cardIndex;
1479391e2f25SKhalid Aziz 	ioport = pCurrCard->ioPort;
14801da177e4SLinus Torvalds 
14811377d8ddSAdrian Bunk 	if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
14821da177e4SLinus Torvalds 
14831da177e4SLinus Torvalds 		p_Sccb->HostStatus = SCCB_COMPLETE;
14841da177e4SLinus Torvalds 		p_Sccb->SccbStatus = SCCB_ERROR;
14851da177e4SLinus Torvalds 		callback = (CALL_BK_FN) p_Sccb->SccbCallback;
14861da177e4SLinus Torvalds 		if (callback)
14871da177e4SLinus Torvalds 			callback(p_Sccb);
14881da177e4SLinus Torvalds 
14891da177e4SLinus Torvalds 		return;
14901da177e4SLinus Torvalds 	}
14911da177e4SLinus Torvalds 
149247b5d69cSJames Bottomley  	FPT_sinits(p_Sccb, thisCard);
14931da177e4SLinus Torvalds 
1494391e2f25SKhalid Aziz 	if (!pCurrCard->cmdCounter) {
14955c04a7b8SAlexey Dobriyan 		WR_HARPOON(ioport + hp_semaphore,
14965c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(ioport + hp_semaphore)
14971da177e4SLinus Torvalds 			    | SCCB_MGR_ACTIVE));
14981da177e4SLinus Torvalds 
1499391e2f25SKhalid Aziz 		if (pCurrCard->globalFlags & F_GREEN_PC) {
15001da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
15011da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
15021da177e4SLinus Torvalds 		}
15031da177e4SLinus Torvalds 	}
15041da177e4SLinus Torvalds 
1505391e2f25SKhalid Aziz 	pCurrCard->cmdCounter++;
15061da177e4SLinus Torvalds 
15071da177e4SLinus Torvalds 	if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
15081da177e4SLinus Torvalds 
15095c04a7b8SAlexey Dobriyan 		WR_HARPOON(ioport + hp_semaphore,
15105c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(ioport + hp_semaphore)
15111da177e4SLinus Torvalds 			    | TICKLE_ME));
15125c04a7b8SAlexey Dobriyan 		if (p_Sccb->OperationCode == RESET_COMMAND) {
15135c04a7b8SAlexey Dobriyan 			pSaveSccb =
1514391e2f25SKhalid Aziz 			    pCurrCard->currentSCCB;
1515391e2f25SKhalid Aziz 			pCurrCard->currentSCCB = p_Sccb;
151647b5d69cSJames Bottomley  			FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1517391e2f25SKhalid Aziz 			pCurrCard->currentSCCB =
15185c04a7b8SAlexey Dobriyan 			    pSaveSccb;
15195c04a7b8SAlexey Dobriyan 		} else {
152047b5d69cSJames Bottomley  			FPT_queueAddSccb(p_Sccb, thisCard);
15211da177e4SLinus Torvalds 		}
15221da177e4SLinus Torvalds 	}
15231da177e4SLinus Torvalds 
15241da177e4SLinus Torvalds 	else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
15251da177e4SLinus Torvalds 
15265c04a7b8SAlexey Dobriyan 		if (p_Sccb->OperationCode == RESET_COMMAND) {
15275c04a7b8SAlexey Dobriyan 			pSaveSccb =
1528391e2f25SKhalid Aziz 			    pCurrCard->currentSCCB;
1529391e2f25SKhalid Aziz 			pCurrCard->currentSCCB = p_Sccb;
153047b5d69cSJames Bottomley  			FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1531391e2f25SKhalid Aziz 			pCurrCard->currentSCCB =
15325c04a7b8SAlexey Dobriyan 			    pSaveSccb;
15335c04a7b8SAlexey Dobriyan 		} else {
153447b5d69cSJames Bottomley  			FPT_queueAddSccb(p_Sccb, thisCard);
15351da177e4SLinus Torvalds 		}
15361da177e4SLinus Torvalds 	}
15371da177e4SLinus Torvalds 
15381da177e4SLinus Torvalds 	else {
15391da177e4SLinus Torvalds 
15401da177e4SLinus Torvalds 		MDISABLE_INT(ioport);
15411da177e4SLinus Torvalds 
1542391e2f25SKhalid Aziz 		if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
15435c04a7b8SAlexey Dobriyan 		    ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
15445c04a7b8SAlexey Dobriyan 		      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
15451da177e4SLinus Torvalds 			lun = p_Sccb->Lun;
15461da177e4SLinus Torvalds 		else
15471da177e4SLinus Torvalds 			lun = 0;
1548391e2f25SKhalid Aziz 		if ((pCurrCard->currentSCCB == NULL) &&
15495c04a7b8SAlexey Dobriyan 		    (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
15505c04a7b8SAlexey Dobriyan 		    && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
155147b5d69cSJames Bottomley  			== 0)) {
15521da177e4SLinus Torvalds 
1553391e2f25SKhalid Aziz 			pCurrCard->currentSCCB = p_Sccb;
155447b5d69cSJames Bottomley  			FPT_ssel(p_Sccb->SccbIOPort, thisCard);
15551da177e4SLinus Torvalds 		}
15561da177e4SLinus Torvalds 
15571da177e4SLinus Torvalds 		else {
15581da177e4SLinus Torvalds 
15595c04a7b8SAlexey Dobriyan 			if (p_Sccb->OperationCode == RESET_COMMAND) {
1560391e2f25SKhalid Aziz 				pSaveSccb = pCurrCard->currentSCCB;
1561391e2f25SKhalid Aziz 				pCurrCard->currentSCCB = p_Sccb;
15625c04a7b8SAlexey Dobriyan 				FPT_queueSelectFail(&FPT_BL_Card[thisCard],
15635c04a7b8SAlexey Dobriyan 						    thisCard);
1564391e2f25SKhalid Aziz 				pCurrCard->currentSCCB = pSaveSccb;
15655c04a7b8SAlexey Dobriyan 			} else {
156647b5d69cSJames Bottomley  				FPT_queueAddSccb(p_Sccb, thisCard);
15671da177e4SLinus Torvalds 			}
15681da177e4SLinus Torvalds 		}
15691da177e4SLinus Torvalds 
15701da177e4SLinus Torvalds 		MENABLE_INT(ioport);
15711da177e4SLinus Torvalds 	}
15721da177e4SLinus Torvalds 
15731da177e4SLinus Torvalds }
15741da177e4SLinus Torvalds 
15751da177e4SLinus Torvalds /*---------------------------------------------------------------------
15761da177e4SLinus Torvalds  *
1577d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_AbortCCB
15781da177e4SLinus Torvalds  *
15791da177e4SLinus Torvalds  * Description: Abort the command pointed to by p_Sccb.  When the
15801da177e4SLinus Torvalds  *              command is completed it will be returned via the
15811da177e4SLinus Torvalds  *              callback function.
15821da177e4SLinus Torvalds  *
15831da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FlashPoint_AbortCCB(void * pCurrCard,struct sccb * p_Sccb)1584391e2f25SKhalid Aziz static int FlashPoint_AbortCCB(void *pCurrCard, struct sccb *p_Sccb)
15851da177e4SLinus Torvalds {
1586391e2f25SKhalid Aziz 	u32 ioport;
15871da177e4SLinus Torvalds 
1588db038cf8SAlexey Dobriyan 	unsigned char thisCard;
15891da177e4SLinus Torvalds 	CALL_BK_FN callback;
159069eb2ea4SAlexey Dobriyan 	struct sccb *pSaveSCCB;
1591f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
15921da177e4SLinus Torvalds 
159313e6851aSAlexey Dobriyan 	ioport = ((struct sccb_card *)pCurrCard)->ioPort;
15941da177e4SLinus Torvalds 
159513e6851aSAlexey Dobriyan 	thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
15961da177e4SLinus Torvalds 
15975c04a7b8SAlexey Dobriyan 	if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
15981da177e4SLinus Torvalds 
15995c04a7b8SAlexey Dobriyan 		if (FPT_queueFindSccb(p_Sccb, thisCard)) {
16001da177e4SLinus Torvalds 
160113e6851aSAlexey Dobriyan 			((struct sccb_card *)pCurrCard)->cmdCounter--;
16021da177e4SLinus Torvalds 
160313e6851aSAlexey Dobriyan 			if (!((struct sccb_card *)pCurrCard)->cmdCounter)
16045c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_semaphore,
16055c04a7b8SAlexey Dobriyan 					   (RD_HARPOON(ioport + hp_semaphore)
16065c04a7b8SAlexey Dobriyan 					    & (unsigned
16075c04a7b8SAlexey Dobriyan 					       char)(~(SCCB_MGR_ACTIVE |
16085c04a7b8SAlexey Dobriyan 						       TICKLE_ME))));
16091da177e4SLinus Torvalds 
16101da177e4SLinus Torvalds 			p_Sccb->SccbStatus = SCCB_ABORT;
16111da177e4SLinus Torvalds 			callback = p_Sccb->SccbCallback;
16121da177e4SLinus Torvalds 			callback(p_Sccb);
16131da177e4SLinus Torvalds 
16145c1b85e2SAlexey Dobriyan 			return 0;
16151da177e4SLinus Torvalds 		}
16161da177e4SLinus Torvalds 
16175c04a7b8SAlexey Dobriyan 		else {
16185c04a7b8SAlexey Dobriyan 			if (((struct sccb_card *)pCurrCard)->currentSCCB ==
16195c04a7b8SAlexey Dobriyan 			    p_Sccb) {
16201da177e4SLinus Torvalds 				p_Sccb->SccbStatus = SCCB_ABORT;
16215c1b85e2SAlexey Dobriyan 				return 0;
16221da177e4SLinus Torvalds 
16231da177e4SLinus Torvalds 			}
16241da177e4SLinus Torvalds 
16255c04a7b8SAlexey Dobriyan 			else {
16265c04a7b8SAlexey Dobriyan 				if (p_Sccb->Sccb_tag) {
16271da177e4SLinus Torvalds 					MDISABLE_INT(ioport);
16285c04a7b8SAlexey Dobriyan 					if (((struct sccb_card *)pCurrCard)->
16295c04a7b8SAlexey Dobriyan 					    discQ_Tbl[p_Sccb->Sccb_tag] ==
16305c04a7b8SAlexey Dobriyan 					    p_Sccb) {
16311da177e4SLinus Torvalds 						p_Sccb->SccbStatus = SCCB_ABORT;
16325c04a7b8SAlexey Dobriyan 						p_Sccb->Sccb_scsistat =
16335c04a7b8SAlexey Dobriyan 						    ABORT_ST;
16345c04a7b8SAlexey Dobriyan 						p_Sccb->Sccb_scsimsg =
1635a87afe28SHannes Reinecke 						    ABORT_TASK;
16361da177e4SLinus Torvalds 
16375c04a7b8SAlexey Dobriyan 						if (((struct sccb_card *)
16385c04a7b8SAlexey Dobriyan 						     pCurrCard)->currentSCCB ==
16395c04a7b8SAlexey Dobriyan 						    NULL) {
16405c04a7b8SAlexey Dobriyan 							((struct sccb_card *)
16415c04a7b8SAlexey Dobriyan 							 pCurrCard)->
16425c04a7b8SAlexey Dobriyan 					currentSCCB = p_Sccb;
16435c04a7b8SAlexey Dobriyan 							FPT_ssel(ioport,
16445c04a7b8SAlexey Dobriyan 								 thisCard);
16455c04a7b8SAlexey Dobriyan 						} else {
16465c04a7b8SAlexey Dobriyan 							pSaveSCCB =
16475c04a7b8SAlexey Dobriyan 							    ((struct sccb_card
16485c04a7b8SAlexey Dobriyan 							      *)pCurrCard)->
16495c04a7b8SAlexey Dobriyan 							    currentSCCB;
16505c04a7b8SAlexey Dobriyan 							((struct sccb_card *)
16515c04a7b8SAlexey Dobriyan 							 pCurrCard)->
16525c04a7b8SAlexey Dobriyan 					currentSCCB = p_Sccb;
165313e6851aSAlexey Dobriyan 							FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
16545c04a7b8SAlexey Dobriyan 							((struct sccb_card *)
16555c04a7b8SAlexey Dobriyan 							 pCurrCard)->
16565c04a7b8SAlexey Dobriyan 					currentSCCB = pSaveSCCB;
16571da177e4SLinus Torvalds 						}
16581da177e4SLinus Torvalds 					}
16591da177e4SLinus Torvalds 					MENABLE_INT(ioport);
16605c1b85e2SAlexey Dobriyan 					return 0;
16615c04a7b8SAlexey Dobriyan 				} else {
16625c04a7b8SAlexey Dobriyan 					currTar_Info =
16635c04a7b8SAlexey Dobriyan 					    &FPT_sccbMgrTbl[thisCard][p_Sccb->
16645c04a7b8SAlexey Dobriyan 								      TargID];
16651da177e4SLinus Torvalds 
16665c04a7b8SAlexey Dobriyan 					if (FPT_BL_Card[thisCard].
16675c04a7b8SAlexey Dobriyan 					    discQ_Tbl[currTar_Info->
16685c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[p_Sccb->Lun]]
16695c04a7b8SAlexey Dobriyan 					    == p_Sccb) {
16701da177e4SLinus Torvalds 						p_Sccb->SccbStatus = SCCB_ABORT;
16715c1b85e2SAlexey Dobriyan 						return 0;
16721da177e4SLinus Torvalds 					}
16731da177e4SLinus Torvalds 				}
16741da177e4SLinus Torvalds 			}
16751da177e4SLinus Torvalds 		}
16761da177e4SLinus Torvalds 	}
16775c1b85e2SAlexey Dobriyan 	return -1;
16781da177e4SLinus Torvalds }
16791da177e4SLinus Torvalds 
16801da177e4SLinus Torvalds /*---------------------------------------------------------------------
16811da177e4SLinus Torvalds  *
1682d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_InterruptPending
16831da177e4SLinus Torvalds  *
16841da177e4SLinus Torvalds  * Description: Do a quick check to determine if there is a pending
16851da177e4SLinus Torvalds  *              interrupt for this card and disable the IRQ Pin if so.
16861da177e4SLinus Torvalds  *
16871da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FlashPoint_InterruptPending(void * pCurrCard)1688391e2f25SKhalid Aziz static unsigned char FlashPoint_InterruptPending(void *pCurrCard)
16891da177e4SLinus Torvalds {
1690391e2f25SKhalid Aziz 	u32 ioport;
16911da177e4SLinus Torvalds 
169213e6851aSAlexey Dobriyan 	ioport = ((struct sccb_card *)pCurrCard)->ioPort;
16931da177e4SLinus Torvalds 
16945c04a7b8SAlexey Dobriyan 	if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
16955c1b85e2SAlexey Dobriyan 		return 1;
16961da177e4SLinus Torvalds 	}
16971da177e4SLinus Torvalds 
16981da177e4SLinus Torvalds 	else
16991da177e4SLinus Torvalds 
17005c1b85e2SAlexey Dobriyan 		return 0;
17011da177e4SLinus Torvalds }
17021da177e4SLinus Torvalds 
17031da177e4SLinus Torvalds /*---------------------------------------------------------------------
17041da177e4SLinus Torvalds  *
1705d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_HandleInterrupt
17061da177e4SLinus Torvalds  *
17071da177e4SLinus Torvalds  * Description: This is our entry point when an interrupt is generated
17081da177e4SLinus Torvalds  *              by the card and the upper level driver passes it on to
17091da177e4SLinus Torvalds  *              us.
17101da177e4SLinus Torvalds  *
17111da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FlashPoint_HandleInterrupt(void * pcard)1712391e2f25SKhalid Aziz static int FlashPoint_HandleInterrupt(void *pcard)
17131da177e4SLinus Torvalds {
171469eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
1715*554b117eSColin Ian King 	unsigned char thisCard, result, bm_status;
1716c823feebSAlexey Dobriyan 	unsigned short hp_int;
1717db038cf8SAlexey Dobriyan 	unsigned char i, target;
1718391e2f25SKhalid Aziz 	struct sccb_card *pCurrCard = pcard;
1719391e2f25SKhalid Aziz 	u32 ioport;
17201da177e4SLinus Torvalds 
1721391e2f25SKhalid Aziz 	thisCard = pCurrCard->cardIndex;
1722391e2f25SKhalid Aziz 	ioport = pCurrCard->ioPort;
17231da177e4SLinus Torvalds 
17241da177e4SLinus Torvalds 	MDISABLE_INT(ioport);
17251da177e4SLinus Torvalds 
1726*554b117eSColin Ian King 	if (RD_HARPOON(ioport + hp_int_status) & EXT_STATUS_ON)
1727391e2f25SKhalid Aziz 		bm_status = RD_HARPOON(ioport + hp_ext_status) &
1728391e2f25SKhalid Aziz 					(unsigned char)BAD_EXT_STATUS;
17291da177e4SLinus Torvalds 	else
17301da177e4SLinus Torvalds 		bm_status = 0;
17311da177e4SLinus Torvalds 
17321da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
17331da177e4SLinus Torvalds 
1734391e2f25SKhalid Aziz 	while ((hp_int = RDW_HARPOON((ioport + hp_intstat)) &
1735391e2f25SKhalid Aziz 				FPT_default_intena) | bm_status) {
17361da177e4SLinus Torvalds 
1737391e2f25SKhalid Aziz 		currSCCB = pCurrCard->currentSCCB;
17381da177e4SLinus Torvalds 
17391da177e4SLinus Torvalds 		if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
17405c04a7b8SAlexey Dobriyan 			result =
1741391e2f25SKhalid Aziz 			    FPT_SccbMgr_bad_isr(ioport, thisCard, pCurrCard,
17425c04a7b8SAlexey Dobriyan 						hp_int);
17435c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
17445c04a7b8SAlexey Dobriyan 				    (FIFO | TIMEOUT | RESET | SCAM_SEL));
17451da177e4SLinus Torvalds 			bm_status = 0;
17461da177e4SLinus Torvalds 
17471da177e4SLinus Torvalds 			if (result) {
17481da177e4SLinus Torvalds 
17491da177e4SLinus Torvalds 				MENABLE_INT(ioport);
17505c1b85e2SAlexey Dobriyan 				return result;
17511da177e4SLinus Torvalds 			}
17521da177e4SLinus Torvalds 		}
17531da177e4SLinus Torvalds 
17541da177e4SLinus Torvalds 		else if (hp_int & ICMD_COMP) {
17551da177e4SLinus Torvalds 
17561da177e4SLinus Torvalds 			if (!(hp_int & BUS_FREE)) {
17571da177e4SLinus Torvalds 				/* Wait for the BusFree before starting a new command.  We
17581da177e4SLinus Torvalds 				   must also check for being reselected since the BusFree
17591da177e4SLinus Torvalds 				   may not show up if another device reselects us in 1.5us or
17601da177e4SLinus Torvalds 				   less.  SRR Wednesday, 3/8/1995.
17611da177e4SLinus Torvalds 				 */
17625c04a7b8SAlexey Dobriyan 				while (!
17635c04a7b8SAlexey Dobriyan 				       (RDW_HARPOON((ioport + hp_intstat)) &
17645c04a7b8SAlexey Dobriyan 					(BUS_FREE | RSEL))) ;
17651da177e4SLinus Torvalds 			}
17661da177e4SLinus Torvalds 
1767391e2f25SKhalid Aziz 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
17681da177e4SLinus Torvalds 
176947b5d69cSJames Bottomley  				FPT_phaseChkFifo(ioport, thisCard);
17701da177e4SLinus Torvalds 
17711da177e4SLinus Torvalds /*         WRW_HARPOON((ioport+hp_intstat),
17721da177e4SLinus Torvalds             (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
17731da177e4SLinus Torvalds          */
17741da177e4SLinus Torvalds 
17751da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
17761da177e4SLinus Torvalds 
177747b5d69cSJames Bottomley  			FPT_autoCmdCmplt(ioport, thisCard);
17781da177e4SLinus Torvalds 
17791da177e4SLinus Torvalds 		}
17801da177e4SLinus Torvalds 
17815c04a7b8SAlexey Dobriyan 		else if (hp_int & ITAR_DISC) {
17821da177e4SLinus Torvalds 
1783391e2f25SKhalid Aziz 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
178447b5d69cSJames Bottomley  				FPT_phaseChkFifo(ioport, thisCard);
17851da177e4SLinus Torvalds 
1786391e2f25SKhalid Aziz 			if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1787a87afe28SHannes Reinecke 					SAVE_POINTERS) {
17881da177e4SLinus Torvalds 
17891da177e4SLinus Torvalds 				WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
17901da177e4SLinus Torvalds 				currSCCB->Sccb_XferState |= F_NO_DATA_YET;
17911da177e4SLinus Torvalds 
17921da177e4SLinus Torvalds 				currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
17931da177e4SLinus Torvalds 			}
17941da177e4SLinus Torvalds 
17951da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = DISCONNECT_ST;
179647b5d69cSJames Bottomley  			FPT_queueDisconnect(currSCCB, thisCard);
17971da177e4SLinus Torvalds 
17981da177e4SLinus Torvalds 			/* Wait for the BusFree before starting a new command.  We
17991da177e4SLinus Torvalds 			   must also check for being reselected since the BusFree
18001da177e4SLinus Torvalds 			   may not show up if another device reselects us in 1.5us or
18011da177e4SLinus Torvalds 			   less.  SRR Wednesday, 3/8/1995.
18021da177e4SLinus Torvalds 			 */
18035c04a7b8SAlexey Dobriyan 			while (!
18045c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((ioport + hp_intstat)) &
18055c04a7b8SAlexey Dobriyan 				(BUS_FREE | RSEL))
18065c04a7b8SAlexey Dobriyan 			       && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
18075c04a7b8SAlexey Dobriyan 				    && RD_HARPOON((ioport + hp_scsisig)) ==
18085c04a7b8SAlexey Dobriyan 				    (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
18095c04a7b8SAlexey Dobriyan 				     SCSI_IOBIT))) ;
18101da177e4SLinus Torvalds 
18111da177e4SLinus Torvalds 			/*
18121da177e4SLinus Torvalds 			   The additional loop exit condition above detects a timing problem
18131da177e4SLinus Torvalds 			   with the revision D/E harpoon chips.  The caller should reset the
18141da177e4SLinus Torvalds 			   host adapter to recover when 0xFE is returned.
18151da177e4SLinus Torvalds 			 */
18165c04a7b8SAlexey Dobriyan 			if (!
18175c04a7b8SAlexey Dobriyan 			    (RDW_HARPOON((ioport + hp_intstat)) &
18185c04a7b8SAlexey Dobriyan 			     (BUS_FREE | RSEL))) {
18191da177e4SLinus Torvalds 				MENABLE_INT(ioport);
18201da177e4SLinus Torvalds 				return 0xFE;
18211da177e4SLinus Torvalds 			}
18221da177e4SLinus Torvalds 
18235c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
18245c04a7b8SAlexey Dobriyan 				    (BUS_FREE | ITAR_DISC));
18251da177e4SLinus Torvalds 
1826391e2f25SKhalid Aziz 			pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
18271da177e4SLinus Torvalds 
18281da177e4SLinus Torvalds 		}
18291da177e4SLinus Torvalds 
18301da177e4SLinus Torvalds 		else if (hp_int & RSEL) {
18311da177e4SLinus Torvalds 
18325c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
18335c04a7b8SAlexey Dobriyan 				    (PROG_HLT | RSEL | PHASE | BUS_FREE));
18341da177e4SLinus Torvalds 
18355c04a7b8SAlexey Dobriyan 			if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
1836391e2f25SKhalid Aziz 				if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
183747b5d69cSJames Bottomley  					FPT_phaseChkFifo(ioport, thisCard);
18381da177e4SLinus Torvalds 
18395c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1840a87afe28SHannes Reinecke 				    SAVE_POINTERS) {
18411da177e4SLinus Torvalds 					WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
18425c04a7b8SAlexey Dobriyan 					currSCCB->Sccb_XferState |=
18435c04a7b8SAlexey Dobriyan 					    F_NO_DATA_YET;
18445c04a7b8SAlexey Dobriyan 					currSCCB->Sccb_savedATC =
18455c04a7b8SAlexey Dobriyan 					    currSCCB->Sccb_ATC;
18461da177e4SLinus Torvalds 				}
18471da177e4SLinus Torvalds 
18485c04a7b8SAlexey Dobriyan 				WRW_HARPOON((ioport + hp_intstat),
18495c04a7b8SAlexey Dobriyan 					    (BUS_FREE | ITAR_DISC));
18501da177e4SLinus Torvalds 				currSCCB->Sccb_scsistat = DISCONNECT_ST;
185147b5d69cSJames Bottomley  				FPT_queueDisconnect(currSCCB, thisCard);
18521da177e4SLinus Torvalds 			}
18531da177e4SLinus Torvalds 
1854391e2f25SKhalid Aziz 			FPT_sres(ioport, thisCard, pCurrCard);
185547b5d69cSJames Bottomley  			FPT_phaseDecode(ioport, thisCard);
18561da177e4SLinus Torvalds 
18571da177e4SLinus Torvalds 		}
18581da177e4SLinus Torvalds 
18595c04a7b8SAlexey Dobriyan 		else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
18601da177e4SLinus Torvalds 
18615c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
18625c04a7b8SAlexey Dobriyan 				    (IDO_STRT | XFER_CNT_0));
186347b5d69cSJames Bottomley  			FPT_phaseDecode(ioport, thisCard);
18641da177e4SLinus Torvalds 
18651da177e4SLinus Torvalds 		}
18661da177e4SLinus Torvalds 
18675c04a7b8SAlexey Dobriyan 		else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
18685c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
18695c04a7b8SAlexey Dobriyan 				    (PHASE | IUNKWN | PROG_HLT));
18705c04a7b8SAlexey Dobriyan 			if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
18715c04a7b8SAlexey Dobriyan 			     0x3f) < (unsigned char)SELCHK) {
187247b5d69cSJames Bottomley  				FPT_phaseDecode(ioport, thisCard);
18735c04a7b8SAlexey Dobriyan 			} else {
18741da177e4SLinus Torvalds 				/* Harpoon problem some SCSI target device respond to selection
18751da177e4SLinus Torvalds 				   with short BUSY pulse (<400ns) this will make the Harpoon is not able
18761da177e4SLinus Torvalds 				   to latch the correct Target ID into reg. x53.
18771da177e4SLinus Torvalds 				   The work around require to correct this reg. But when write to this
18781da177e4SLinus Torvalds 				   reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
18791da177e4SLinus Torvalds 				   need to read this reg first then restore it later. After update to 0x53 */
18801da177e4SLinus Torvalds 
18815c04a7b8SAlexey Dobriyan 				i = (unsigned
18825c04a7b8SAlexey Dobriyan 				     char)(RD_HARPOON(ioport + hp_fifowrite));
18835c04a7b8SAlexey Dobriyan 				target =
18845c04a7b8SAlexey Dobriyan 				    (unsigned
18855c04a7b8SAlexey Dobriyan 				     char)(RD_HARPOON(ioport + hp_gp_reg_3));
18865c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_xfer_pad,
18875c04a7b8SAlexey Dobriyan 					   (unsigned char)ID_UNLOCK);
18885c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_select_id,
18895c04a7b8SAlexey Dobriyan 					   (unsigned char)(target | target <<
18905c04a7b8SAlexey Dobriyan 							   4));
18915c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_xfer_pad,
18925c04a7b8SAlexey Dobriyan 					   (unsigned char)0x00);
18931da177e4SLinus Torvalds 				WR_HARPOON(ioport + hp_fifowrite, i);
18945c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_autostart_3,
18955c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + TAG_STRT));
18961da177e4SLinus Torvalds 			}
18971da177e4SLinus Torvalds 		}
18981da177e4SLinus Torvalds 
18991da177e4SLinus Torvalds 		else if (hp_int & XFER_CNT_0) {
19001da177e4SLinus Torvalds 
19011da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
19021da177e4SLinus Torvalds 
190347b5d69cSJames Bottomley  			FPT_schkdd(ioport, thisCard);
19041da177e4SLinus Torvalds 
19051da177e4SLinus Torvalds 		}
19061da177e4SLinus Torvalds 
19071da177e4SLinus Torvalds 		else if (hp_int & BUS_FREE) {
19081da177e4SLinus Torvalds 
19091da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
19101da177e4SLinus Torvalds 
1911391e2f25SKhalid Aziz 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
19121da177e4SLinus Torvalds 
19135c04a7b8SAlexey Dobriyan 				FPT_hostDataXferAbort(ioport, thisCard,
19145c04a7b8SAlexey Dobriyan 						      currSCCB);
19151da177e4SLinus Torvalds 			}
19161da177e4SLinus Torvalds 
191747b5d69cSJames Bottomley  			FPT_phaseBusFree(ioport, thisCard);
19181da177e4SLinus Torvalds 		}
19191da177e4SLinus Torvalds 
19201da177e4SLinus Torvalds 		else if (hp_int & ITICKLE) {
19211da177e4SLinus Torvalds 
19221da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), ITICKLE);
1923391e2f25SKhalid Aziz 			pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
19241da177e4SLinus Torvalds 		}
19251da177e4SLinus Torvalds 
19265c04a7b8SAlexey Dobriyan 		if (((struct sccb_card *)pCurrCard)->
19275c04a7b8SAlexey Dobriyan 		    globalFlags & F_NEW_SCCB_CMD) {
19281da177e4SLinus Torvalds 
1929391e2f25SKhalid Aziz 			pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
19301da177e4SLinus Torvalds 
1931391e2f25SKhalid Aziz 			if (pCurrCard->currentSCCB == NULL)
1932391e2f25SKhalid Aziz 				FPT_queueSearchSelect(pCurrCard, thisCard);
19331da177e4SLinus Torvalds 
1934391e2f25SKhalid Aziz 			if (pCurrCard->currentSCCB != NULL) {
1935391e2f25SKhalid Aziz 				pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
193647b5d69cSJames Bottomley  				FPT_ssel(ioport, thisCard);
19371da177e4SLinus Torvalds 			}
19381da177e4SLinus Torvalds 
19391da177e4SLinus Torvalds 			break;
19401da177e4SLinus Torvalds 
19411da177e4SLinus Torvalds 		}
19421da177e4SLinus Torvalds 
19431da177e4SLinus Torvalds 	}			/*end while */
19441da177e4SLinus Torvalds 
19451da177e4SLinus Torvalds 	MENABLE_INT(ioport);
19461da177e4SLinus Torvalds 
19475c1b85e2SAlexey Dobriyan 	return 0;
19481da177e4SLinus Torvalds }
19491da177e4SLinus Torvalds 
19501da177e4SLinus Torvalds /*---------------------------------------------------------------------
19511da177e4SLinus Torvalds  *
19521da177e4SLinus Torvalds  * Function: Sccb_bad_isr
19531da177e4SLinus Torvalds  *
19541da177e4SLinus Torvalds  * Description: Some type of interrupt has occurred which is slightly
19551da177e4SLinus Torvalds  *              out of the ordinary.  We will now decode it fully, in
19561da177e4SLinus Torvalds  *              this routine.  This is broken up in an attempt to save
19571da177e4SLinus Torvalds  *              processing time.
19581da177e4SLinus Torvalds  *
19591da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_SccbMgr_bad_isr(u32 p_port,unsigned char p_card,struct sccb_card * pCurrCard,unsigned short p_int)1960391e2f25SKhalid Aziz static unsigned char FPT_SccbMgr_bad_isr(u32 p_port, unsigned char p_card,
19615c04a7b8SAlexey Dobriyan 					 struct sccb_card *pCurrCard,
19625c04a7b8SAlexey Dobriyan 					 unsigned short p_int)
19631da177e4SLinus Torvalds {
1964db038cf8SAlexey Dobriyan 	unsigned char temp, ScamFlg;
1965f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
196668d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
19671da177e4SLinus Torvalds 
19681da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_ext_status) &
19695c04a7b8SAlexey Dobriyan 	    (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
19701da177e4SLinus Torvalds 
19715c04a7b8SAlexey Dobriyan 		if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
19721da177e4SLinus Torvalds 
19735c04a7b8SAlexey Dobriyan 			FPT_hostDataXferAbort(p_port, p_card,
19745c04a7b8SAlexey Dobriyan 					      pCurrCard->currentSCCB);
19751da177e4SLinus Torvalds 		}
19761da177e4SLinus Torvalds 
19771da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
19781da177e4SLinus Torvalds 		{
19791da177e4SLinus Torvalds 			WR_HARPOON(p_port + hp_pci_stat_cfg,
19805c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(p_port + hp_pci_stat_cfg) &
19815c04a7b8SAlexey Dobriyan 				    ~REC_MASTER_ABORT));
19821da177e4SLinus Torvalds 
19831da177e4SLinus Torvalds 			WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
19841da177e4SLinus Torvalds 
19851da177e4SLinus Torvalds 		}
19861da177e4SLinus Torvalds 
19875c04a7b8SAlexey Dobriyan 		if (pCurrCard->currentSCCB != NULL) {
19881da177e4SLinus Torvalds 
19891da177e4SLinus Torvalds 			if (!pCurrCard->currentSCCB->HostStatus)
19905c04a7b8SAlexey Dobriyan 				pCurrCard->currentSCCB->HostStatus =
19915c04a7b8SAlexey Dobriyan 				    SCCB_BM_ERR;
19921da177e4SLinus Torvalds 
199347b5d69cSJames Bottomley  			FPT_sxfrp(p_port, p_card);
19941da177e4SLinus Torvalds 
1995db038cf8SAlexey Dobriyan 			temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
19961da177e4SLinus Torvalds 					       (EXT_ARB_ACK | SCSI_TERM_ENA_H));
19975c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_ee_ctrl,
19985c04a7b8SAlexey Dobriyan 				   ((unsigned char)temp | SEE_MS | SEE_CS));
19991da177e4SLinus Torvalds 			WR_HARPOON(p_port + hp_ee_ctrl, temp);
20001da177e4SLinus Torvalds 
20015c04a7b8SAlexey Dobriyan 			if (!
20025c04a7b8SAlexey Dobriyan 			    (RDW_HARPOON((p_port + hp_intstat)) &
20035c04a7b8SAlexey Dobriyan 			     (BUS_FREE | RESET))) {
200447b5d69cSJames Bottomley  				FPT_phaseDecode(p_port, p_card);
20051da177e4SLinus Torvalds 			}
20061da177e4SLinus Torvalds 		}
20071da177e4SLinus Torvalds 	}
20081da177e4SLinus Torvalds 
20095c04a7b8SAlexey Dobriyan 	else if (p_int & RESET) {
20101da177e4SLinus Torvalds 
20111da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
20121da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
20131da177e4SLinus Torvalds 		if (pCurrCard->currentSCCB != NULL) {
20141da177e4SLinus Torvalds 
20151da177e4SLinus Torvalds 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
20161da177e4SLinus Torvalds 
20175c04a7b8SAlexey Dobriyan 				FPT_hostDataXferAbort(p_port, p_card,
20185c04a7b8SAlexey Dobriyan 						      pCurrCard->currentSCCB);
20191da177e4SLinus Torvalds 		}
20201da177e4SLinus Torvalds 
20211da177e4SLinus Torvalds 		DISABLE_AUTO(p_port);
20221da177e4SLinus Torvalds 
202347b5d69cSJames Bottomley  		FPT_sresb(p_port, p_card);
20241da177e4SLinus Torvalds 
20255c04a7b8SAlexey Dobriyan 		while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
20265c04a7b8SAlexey Dobriyan 		}
20271da177e4SLinus Torvalds 
20281da177e4SLinus Torvalds 		pCurrNvRam = pCurrCard->pNvRamInfo;
20291da177e4SLinus Torvalds 		if (pCurrNvRam) {
20301da177e4SLinus Torvalds 			ScamFlg = pCurrNvRam->niScamConf;
20315c04a7b8SAlexey Dobriyan 		} else {
20325c04a7b8SAlexey Dobriyan 			ScamFlg =
20335c04a7b8SAlexey Dobriyan 			    (unsigned char)FPT_utilEERead(p_port,
20345c04a7b8SAlexey Dobriyan 							  SCAM_CONFIG / 2);
20351da177e4SLinus Torvalds 		}
20361da177e4SLinus Torvalds 
203747b5d69cSJames Bottomley  		FPT_XbowInit(p_port, ScamFlg);
20381da177e4SLinus Torvalds 
203947b5d69cSJames Bottomley  		FPT_scini(p_card, pCurrCard->ourId, 0);
20401da177e4SLinus Torvalds 
20415c1b85e2SAlexey Dobriyan 		return 0xFF;
20421da177e4SLinus Torvalds 	}
20431da177e4SLinus Torvalds 
20441da177e4SLinus Torvalds 	else if (p_int & FIFO) {
20451da177e4SLinus Torvalds 
20461da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat), FIFO);
20471da177e4SLinus Torvalds 
20481da177e4SLinus Torvalds 		if (pCurrCard->currentSCCB != NULL)
204947b5d69cSJames Bottomley  			FPT_sxfrp(p_port, p_card);
20501da177e4SLinus Torvalds 	}
20511da177e4SLinus Torvalds 
20525c04a7b8SAlexey Dobriyan 	else if (p_int & TIMEOUT) {
20531da177e4SLinus Torvalds 
20541da177e4SLinus Torvalds 		DISABLE_AUTO(p_port);
20551da177e4SLinus Torvalds 
20561da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat),
20575c04a7b8SAlexey Dobriyan 			    (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
20585c04a7b8SAlexey Dobriyan 			     IUNKWN));
20591da177e4SLinus Torvalds 
20601da177e4SLinus Torvalds 		pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
20611da177e4SLinus Torvalds 
20625c04a7b8SAlexey Dobriyan 		currTar_Info =
20635c04a7b8SAlexey Dobriyan 		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
20645c04a7b8SAlexey Dobriyan 		if ((pCurrCard->globalFlags & F_CONLUN_IO)
20655c04a7b8SAlexey Dobriyan 		    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
20665c04a7b8SAlexey Dobriyan 			TAG_Q_TRYING))
20675c04a7b8SAlexey Dobriyan 			currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
20685c04a7b8SAlexey Dobriyan 			    0;
20691da177e4SLinus Torvalds 		else
207047b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[0] = 0;
20711da177e4SLinus Torvalds 
20725c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
20731da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
20741da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
20751da177e4SLinus Torvalds 		}
20761da177e4SLinus Torvalds 
20775c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
20781da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
20791da177e4SLinus Torvalds 		}
20801da177e4SLinus Torvalds 
20815c04a7b8SAlexey Dobriyan 		FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
20825c04a7b8SAlexey Dobriyan 			    currTar_Info);
20831da177e4SLinus Torvalds 
208447b5d69cSJames Bottomley  		FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
20851da177e4SLinus Torvalds 
20861da177e4SLinus Torvalds 	}
20871da177e4SLinus Torvalds 
20885c04a7b8SAlexey Dobriyan 	else if (p_int & SCAM_SEL) {
20891da177e4SLinus Torvalds 
209047b5d69cSJames Bottomley  		FPT_scarb(p_port, LEVEL2_TAR);
209147b5d69cSJames Bottomley  		FPT_scsel(p_port);
209247b5d69cSJames Bottomley  		FPT_scasid(p_card, p_port);
20931da177e4SLinus Torvalds 
209447b5d69cSJames Bottomley  		FPT_scbusf(p_port);
20951da177e4SLinus Torvalds 
20961da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
20971da177e4SLinus Torvalds 	}
20981da177e4SLinus Torvalds 
20995c1b85e2SAlexey Dobriyan 	return 0x00;
21001da177e4SLinus Torvalds }
21011da177e4SLinus Torvalds 
21021da177e4SLinus Torvalds /*---------------------------------------------------------------------
21031da177e4SLinus Torvalds  *
21041da177e4SLinus Torvalds  * Function: SccbMgrTableInit
21051da177e4SLinus Torvalds  *
21061da177e4SLinus Torvalds  * Description: Initialize all Sccb manager data structures.
21071da177e4SLinus Torvalds  *
21081da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
21091da177e4SLinus Torvalds 
FPT_SccbMgrTableInitAll(void)2110cd9d715cSSudip Mukherjee static void FPT_SccbMgrTableInitAll(void)
21111da177e4SLinus Torvalds {
2112db038cf8SAlexey Dobriyan 	unsigned char thisCard;
21131da177e4SLinus Torvalds 
21145c04a7b8SAlexey Dobriyan 	for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
211547b5d69cSJames Bottomley  		FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
21161da177e4SLinus Torvalds 
211747b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].ioPort = 0x00;
211847b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].cardInfo = NULL;
211947b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].cardIndex = 0xFF;
212047b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].ourId = 0x00;
212147b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].pNvRamInfo = NULL;
21221da177e4SLinus Torvalds 	}
21231da177e4SLinus Torvalds }
21241da177e4SLinus Torvalds 
21251da177e4SLinus Torvalds /*---------------------------------------------------------------------
21261da177e4SLinus Torvalds  *
21271da177e4SLinus Torvalds  * Function: SccbMgrTableInit
21281da177e4SLinus Torvalds  *
21291da177e4SLinus Torvalds  * Description: Initialize all Sccb manager data structures.
21301da177e4SLinus Torvalds  *
21311da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
21321da177e4SLinus Torvalds 
FPT_SccbMgrTableInitCard(struct sccb_card * pCurrCard,unsigned char p_card)21335c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
21345c04a7b8SAlexey Dobriyan 				     unsigned char p_card)
21351da177e4SLinus Torvalds {
2136db038cf8SAlexey Dobriyan 	unsigned char scsiID, qtag;
21371da177e4SLinus Torvalds 
21385c04a7b8SAlexey Dobriyan 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
213947b5d69cSJames Bottomley  		FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
21401da177e4SLinus Torvalds 	}
21411da177e4SLinus Torvalds 
21425c04a7b8SAlexey Dobriyan 	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
214347b5d69cSJames Bottomley  		FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
214447b5d69cSJames Bottomley  		FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
214547b5d69cSJames Bottomley  		FPT_SccbMgrTableInitTarget(p_card, scsiID);
21461da177e4SLinus Torvalds 	}
21471da177e4SLinus Torvalds 
21481da177e4SLinus Torvalds 	pCurrCard->scanIndex = 0x00;
21491da177e4SLinus Torvalds 	pCurrCard->currentSCCB = NULL;
21501da177e4SLinus Torvalds 	pCurrCard->globalFlags = 0x00;
21511da177e4SLinus Torvalds 	pCurrCard->cmdCounter = 0x00;
21521da177e4SLinus Torvalds 	pCurrCard->tagQ_Lst = 0x01;
21531da177e4SLinus Torvalds 	pCurrCard->discQCount = 0;
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 
FPT_SccbMgrTableInitTarget(unsigned char p_card,unsigned char target)21655c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
21665c04a7b8SAlexey Dobriyan 				       unsigned char target)
21671da177e4SLinus Torvalds {
21681da177e4SLinus Torvalds 
2169db038cf8SAlexey Dobriyan 	unsigned char lun, qtag;
2170f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
21711da177e4SLinus Torvalds 
217247b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
21731da177e4SLinus Torvalds 
21741da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Cnt = 0;
21751da177e4SLinus Torvalds 	currTar_Info->TarSyncCtrl = 0;
21761da177e4SLinus Torvalds 
21771da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Head = NULL;
21781da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Tail = NULL;
21791da177e4SLinus Torvalds 	currTar_Info->TarTagQ_Cnt = 0;
218047b5d69cSJames Bottomley  	currTar_Info->TarLUN_CA = 0;
21811da177e4SLinus Torvalds 
21825c04a7b8SAlexey Dobriyan 	for (lun = 0; lun < MAX_LUN; lun++) {
218347b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[lun] = 0;
21841da177e4SLinus Torvalds 		currTar_Info->LunDiscQ_Idx[lun] = 0;
21851da177e4SLinus Torvalds 	}
21861da177e4SLinus Torvalds 
21875c04a7b8SAlexey Dobriyan 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
21885c04a7b8SAlexey Dobriyan 		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
21895c04a7b8SAlexey Dobriyan 			if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
21905c04a7b8SAlexey Dobriyan 			    target) {
219147b5d69cSJames Bottomley  				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
219247b5d69cSJames Bottomley  				FPT_BL_Card[p_card].discQCount--;
21931da177e4SLinus Torvalds 			}
21941da177e4SLinus Torvalds 		}
21951da177e4SLinus Torvalds 	}
21961da177e4SLinus Torvalds }
21971da177e4SLinus Torvalds 
21981da177e4SLinus Torvalds /*---------------------------------------------------------------------
21991da177e4SLinus Torvalds  *
22001da177e4SLinus Torvalds  * Function: sfetm
22011da177e4SLinus Torvalds  *
22021da177e4SLinus Torvalds  * Description: Read in a message byte from the SCSI bus, and check
22031da177e4SLinus Torvalds  *              for a parity error.
22041da177e4SLinus Torvalds  *
22051da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
22061da177e4SLinus Torvalds 
FPT_sfm(u32 port,struct sccb * pCurrSCCB)2207391e2f25SKhalid Aziz static unsigned char FPT_sfm(u32 port, struct sccb *pCurrSCCB)
22081da177e4SLinus Torvalds {
2209db038cf8SAlexey Dobriyan 	unsigned char message;
2210c823feebSAlexey Dobriyan 	unsigned short TimeOutLoop;
22111da177e4SLinus Torvalds 
22121da177e4SLinus Torvalds 	TimeOutLoop = 0;
22131da177e4SLinus Torvalds 	while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
22145c04a7b8SAlexey Dobriyan 	       (TimeOutLoop++ < 20000)) {
22155c04a7b8SAlexey Dobriyan 	}
22161da177e4SLinus Torvalds 
22171da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
22181da177e4SLinus Torvalds 
22191da177e4SLinus Torvalds 	message = RD_HARPOON(port + hp_scsidata_0);
22201da177e4SLinus Torvalds 
22211da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
22221da177e4SLinus Torvalds 
22231da177e4SLinus Torvalds 	if (TimeOutLoop > 20000)
22241da177e4SLinus Torvalds 		message = 0x00;	/* force message byte = 0 if Time Out on Req */
22251da177e4SLinus Torvalds 
22261da177e4SLinus Torvalds 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
22275c04a7b8SAlexey Dobriyan 	    (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
22281da177e4SLinus Torvalds 		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
22291da177e4SLinus Torvalds 		WR_HARPOON(port + hp_xferstat, 0);
22301da177e4SLinus Torvalds 		WR_HARPOON(port + hp_fiforead, 0);
22311da177e4SLinus Torvalds 		WR_HARPOON(port + hp_fifowrite, 0);
22325c04a7b8SAlexey Dobriyan 		if (pCurrSCCB != NULL) {
2233a87afe28SHannes Reinecke 			pCurrSCCB->Sccb_scsimsg = MSG_PARITY_ERROR;
22341da177e4SLinus Torvalds 		}
22351da177e4SLinus Torvalds 		message = 0x00;
22365c04a7b8SAlexey Dobriyan 		do {
22371da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
22381da177e4SLinus Torvalds 			TimeOutLoop = 0;
22391da177e4SLinus Torvalds 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
22405c04a7b8SAlexey Dobriyan 			       (TimeOutLoop++ < 20000)) {
22415c04a7b8SAlexey Dobriyan 			}
22425c04a7b8SAlexey Dobriyan 			if (TimeOutLoop > 20000) {
22431da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PARITY);
22445c1b85e2SAlexey Dobriyan 				return message;
22451da177e4SLinus Torvalds 			}
22465c04a7b8SAlexey Dobriyan 			if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
22475c04a7b8SAlexey Dobriyan 			    S_MSGI_PH) {
22481da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PARITY);
22495c1b85e2SAlexey Dobriyan 				return message;
22501da177e4SLinus Torvalds 			}
22511da177e4SLinus Torvalds 			WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
22521da177e4SLinus Torvalds 
22531da177e4SLinus Torvalds 			RD_HARPOON(port + hp_scsidata_0);
22541da177e4SLinus Torvalds 
22551da177e4SLinus Torvalds 			WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
22561da177e4SLinus Torvalds 
22571da177e4SLinus Torvalds 		} while (1);
22581da177e4SLinus Torvalds 
22591da177e4SLinus Torvalds 	}
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);
22645c1b85e2SAlexey Dobriyan 	return message;
22651da177e4SLinus Torvalds }
22661da177e4SLinus Torvalds 
22671da177e4SLinus Torvalds /*---------------------------------------------------------------------
22681da177e4SLinus Torvalds  *
226947b5d69cSJames Bottomley   * Function: FPT_ssel
22701da177e4SLinus Torvalds  *
22711da177e4SLinus Torvalds  * Description: Load up automation and select target device.
22721da177e4SLinus Torvalds  *
22731da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
22741da177e4SLinus Torvalds 
FPT_ssel(u32 port,unsigned char p_card)2275391e2f25SKhalid Aziz static void FPT_ssel(u32 port, unsigned char p_card)
22761da177e4SLinus Torvalds {
22771da177e4SLinus Torvalds 
2278db038cf8SAlexey Dobriyan 	unsigned char auto_loaded, i, target, *theCCB;
22791da177e4SLinus Torvalds 
2280391e2f25SKhalid Aziz 	u32 cdb_reg;
228113e6851aSAlexey Dobriyan 	struct sccb_card *CurrCard;
228269eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
2283f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
2284db038cf8SAlexey Dobriyan 	unsigned char lastTag, lun;
22851da177e4SLinus Torvalds 
228647b5d69cSJames Bottomley  	CurrCard = &FPT_BL_Card[p_card];
22871da177e4SLinus Torvalds 	currSCCB = CurrCard->currentSCCB;
22881da177e4SLinus Torvalds 	target = currSCCB->TargID;
228947b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
22901da177e4SLinus Torvalds 	lastTag = CurrCard->tagQ_Lst;
22911da177e4SLinus Torvalds 
22921da177e4SLinus Torvalds 	ARAM_ACCESS(port);
22931da177e4SLinus Torvalds 
22941da177e4SLinus Torvalds 	if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
22951da177e4SLinus Torvalds 		currSCCB->ControlByte &= ~F_USE_CMD_Q;
22961da177e4SLinus Torvalds 
22971da177e4SLinus Torvalds 	if (((CurrCard->globalFlags & F_CONLUN_IO) &&
22981da177e4SLinus Torvalds 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
22991da177e4SLinus Torvalds 
23001da177e4SLinus Torvalds 		lun = currSCCB->Lun;
23011da177e4SLinus Torvalds 	else
23021da177e4SLinus Torvalds 		lun = 0;
23031da177e4SLinus Torvalds 
23045c04a7b8SAlexey Dobriyan 	if (CurrCard->globalFlags & F_TAG_STARTED) {
23055c04a7b8SAlexey Dobriyan 		if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
230647b5d69cSJames Bottomley  			if ((currTar_Info->TarLUN_CA == 0)
23071da177e4SLinus Torvalds 			    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
23085c04a7b8SAlexey Dobriyan 				== TAG_Q_TRYING)) {
23091da177e4SLinus Torvalds 
23105c04a7b8SAlexey Dobriyan 				if (currTar_Info->TarTagQ_Cnt != 0) {
231147b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[lun] = 1;
231247b5d69cSJames Bottomley  					FPT_queueSelectFail(CurrCard, p_card);
23131da177e4SLinus Torvalds 					SGRAM_ACCESS(port);
23141da177e4SLinus Torvalds 					return;
23151da177e4SLinus Torvalds 				}
23161da177e4SLinus Torvalds 
23171da177e4SLinus Torvalds 				else {
231847b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[lun] = 1;
23191da177e4SLinus Torvalds 				}
23201da177e4SLinus Torvalds 
23215c04a7b8SAlexey Dobriyan 			}
23225c04a7b8SAlexey Dobriyan 			/*End non-tagged */
23231da177e4SLinus Torvalds 			else {
232447b5d69cSJames Bottomley  				currTar_Info->TarLUNBusy[lun] = 1;
23251da177e4SLinus Torvalds 			}
23261da177e4SLinus Torvalds 
23275c04a7b8SAlexey Dobriyan 		}
23285c04a7b8SAlexey Dobriyan 		/*!Use cmd Q Tagged */
23291da177e4SLinus Torvalds 		else {
23305c04a7b8SAlexey Dobriyan 			if (currTar_Info->TarLUN_CA == 1) {
233147b5d69cSJames Bottomley  				FPT_queueSelectFail(CurrCard, p_card);
23321da177e4SLinus Torvalds 				SGRAM_ACCESS(port);
23331da177e4SLinus Torvalds 				return;
23341da177e4SLinus Torvalds 			}
23351da177e4SLinus Torvalds 
233647b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[lun] = 1;
23371da177e4SLinus Torvalds 
23381da177e4SLinus Torvalds 		}		/*else use cmd Q tagged */
23391da177e4SLinus Torvalds 
23405c04a7b8SAlexey Dobriyan 	}
23415c04a7b8SAlexey Dobriyan 	/*if glob tagged started */
23421da177e4SLinus Torvalds 	else {
234347b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[lun] = 1;
23441da177e4SLinus Torvalds 	}
23451da177e4SLinus Torvalds 
23461da177e4SLinus Torvalds 	if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
23471da177e4SLinus Torvalds 	      ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
23485c04a7b8SAlexey Dobriyan 	     || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
23495c04a7b8SAlexey Dobriyan 		if (CurrCard->discQCount >= QUEUE_DEPTH) {
235047b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[lun] = 1;
235147b5d69cSJames Bottomley  			FPT_queueSelectFail(CurrCard, p_card);
23521da177e4SLinus Torvalds 			SGRAM_ACCESS(port);
23531da177e4SLinus Torvalds 			return;
23541da177e4SLinus Torvalds 		}
23555c04a7b8SAlexey Dobriyan 		for (i = 1; i < QUEUE_DEPTH; i++) {
23565c04a7b8SAlexey Dobriyan 			if (++lastTag >= QUEUE_DEPTH)
23575c04a7b8SAlexey Dobriyan 				lastTag = 1;
23585c04a7b8SAlexey Dobriyan 			if (CurrCard->discQ_Tbl[lastTag] == NULL) {
23591da177e4SLinus Torvalds 				CurrCard->tagQ_Lst = lastTag;
23601da177e4SLinus Torvalds 				currTar_Info->LunDiscQ_Idx[lun] = lastTag;
23611da177e4SLinus Torvalds 				CurrCard->discQ_Tbl[lastTag] = currSCCB;
23621da177e4SLinus Torvalds 				CurrCard->discQCount++;
23631da177e4SLinus Torvalds 				break;
23641da177e4SLinus Torvalds 			}
23651da177e4SLinus Torvalds 		}
23665c04a7b8SAlexey Dobriyan 		if (i == QUEUE_DEPTH) {
236747b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[lun] = 1;
236847b5d69cSJames Bottomley  			FPT_queueSelectFail(CurrCard, p_card);
23691da177e4SLinus Torvalds 			SGRAM_ACCESS(port);
23701da177e4SLinus Torvalds 			return;
23711da177e4SLinus Torvalds 		}
23721da177e4SLinus Torvalds 	}
23731da177e4SLinus Torvalds 
237447b5d69cSJames Bottomley  	auto_loaded = 0;
23751da177e4SLinus Torvalds 
23761da177e4SLinus Torvalds 	WR_HARPOON(port + hp_select_id, target);
23771da177e4SLinus Torvalds 	WR_HARPOON(port + hp_gp_reg_3, target);	/* Use by new automation logic */
23781da177e4SLinus Torvalds 
23791da177e4SLinus Torvalds 	if (currSCCB->OperationCode == RESET_COMMAND) {
23801da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
23815c04a7b8SAlexey Dobriyan 						   (currSCCB->
23825c04a7b8SAlexey Dobriyan 						    Sccb_idmsg & ~DISC_PRIV)));
23831da177e4SLinus Torvalds 
23841da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
23851da177e4SLinus Torvalds 
2386a87afe28SHannes Reinecke 		currSCCB->Sccb_scsimsg = TARGET_RESET;
23871da177e4SLinus Torvalds 
23881da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
238947b5d69cSJames Bottomley  		auto_loaded = 1;
23901da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = SELECT_BDR_ST;
23911da177e4SLinus Torvalds 
23925c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
23931da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
23941da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
23951da177e4SLinus Torvalds 		}
23961da177e4SLinus Torvalds 
23975c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
23981da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
23991da177e4SLinus Torvalds 		}
24001da177e4SLinus Torvalds 
240147b5d69cSJames Bottomley  		FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
240247b5d69cSJames Bottomley  		FPT_SccbMgrTableInitTarget(p_card, target);
24031da177e4SLinus Torvalds 
24041da177e4SLinus Torvalds 	}
24051da177e4SLinus Torvalds 
24065c04a7b8SAlexey Dobriyan 	else if (currSCCB->Sccb_scsistat == ABORT_ST) {
24071da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
24085c04a7b8SAlexey Dobriyan 						   (currSCCB->
24095c04a7b8SAlexey Dobriyan 						    Sccb_idmsg & ~DISC_PRIV)));
24101da177e4SLinus Torvalds 
24111da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
24121da177e4SLinus Torvalds 
24131da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
24145c04a7b8SAlexey Dobriyan 						     (((unsigned
24155c04a7b8SAlexey Dobriyan 							char)(currSCCB->
24165c04a7b8SAlexey Dobriyan 							      ControlByte &
24175c04a7b8SAlexey Dobriyan 							      TAG_TYPE_MASK)
24185c04a7b8SAlexey Dobriyan 						       >> 6) | (unsigned char)
24195c04a7b8SAlexey Dobriyan 						      0x20)));
24201da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 2),
24211da177e4SLinus Torvalds 			    (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
24221da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
24231da177e4SLinus Torvalds 
24241da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
242547b5d69cSJames Bottomley  		auto_loaded = 1;
24261da177e4SLinus Torvalds 
24271da177e4SLinus Torvalds 	}
24281da177e4SLinus Torvalds 
24291da177e4SLinus Torvalds 	else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
243047b5d69cSJames Bottomley  		auto_loaded = FPT_siwidn(port, p_card);
24311da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = SELECT_WN_ST;
24321da177e4SLinus Torvalds 	}
24331da177e4SLinus Torvalds 
24341da177e4SLinus Torvalds 	else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
24351da177e4SLinus Torvalds 		   == SYNC_SUPPORTED)) {
243647b5d69cSJames Bottomley  		auto_loaded = FPT_sisyncn(port, p_card, 0);
24371da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = SELECT_SN_ST;
24381da177e4SLinus Torvalds 	}
24391da177e4SLinus Torvalds 
24405c04a7b8SAlexey Dobriyan 	if (!auto_loaded) {
24411da177e4SLinus Torvalds 
24425c04a7b8SAlexey Dobriyan 		if (currSCCB->ControlByte & F_USE_CMD_Q) {
24431da177e4SLinus Torvalds 
24441da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_TAG_STARTED;
24451da177e4SLinus Torvalds 
24461da177e4SLinus Torvalds 			if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
24475c04a7b8SAlexey Dobriyan 			    == TAG_Q_REJECT) {
24481da177e4SLinus Torvalds 				currSCCB->ControlByte &= ~F_USE_CMD_Q;
24491da177e4SLinus Torvalds 
24501da177e4SLinus Torvalds 				/* Fix up the start instruction with a jump to
24511da177e4SLinus Torvalds 				   Non-Tag-CMD handling */
24525c04a7b8SAlexey Dobriyan 				WRW_HARPOON((port + ID_MSG_STRT),
24535c04a7b8SAlexey Dobriyan 					    BRH_OP + ALWAYS + NTCMD);
24541da177e4SLinus Torvalds 
24551da177e4SLinus Torvalds 				WRW_HARPOON((port + NON_TAG_ID_MSG),
24565c04a7b8SAlexey Dobriyan 					    (MPM_OP + AMSG_OUT +
24575c04a7b8SAlexey Dobriyan 					     currSCCB->Sccb_idmsg));
24581da177e4SLinus Torvalds 
24595c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_3,
24605c04a7b8SAlexey Dobriyan 					   (SELECT + SELCHK_STRT));
24611da177e4SLinus Torvalds 
246225985edcSLucas De Marchi 				/* Setup our STATE so we know what happened when
24631da177e4SLinus Torvalds 				   the wheels fall off. */
24641da177e4SLinus Torvalds 				currSCCB->Sccb_scsistat = SELECT_ST;
24651da177e4SLinus Torvalds 
246647b5d69cSJames Bottomley  				currTar_Info->TarLUNBusy[lun] = 1;
24671da177e4SLinus Torvalds 			}
24681da177e4SLinus Torvalds 
24695c04a7b8SAlexey Dobriyan 			else {
24705c04a7b8SAlexey Dobriyan 				WRW_HARPOON((port + ID_MSG_STRT),
24715c04a7b8SAlexey Dobriyan 					    (MPM_OP + AMSG_OUT +
24725c04a7b8SAlexey Dobriyan 					     currSCCB->Sccb_idmsg));
24731da177e4SLinus Torvalds 
24745c04a7b8SAlexey Dobriyan 				WRW_HARPOON((port + ID_MSG_STRT + 2),
24755c04a7b8SAlexey Dobriyan 					    (MPM_OP + AMSG_OUT +
24765c04a7b8SAlexey Dobriyan 					     (((unsigned char)(currSCCB->
24775c04a7b8SAlexey Dobriyan 							       ControlByte &
24785c04a7b8SAlexey Dobriyan 							       TAG_TYPE_MASK)
2479db038cf8SAlexey Dobriyan 					       >> 6) | (unsigned char)0x20)));
24801da177e4SLinus Torvalds 
24815c04a7b8SAlexey Dobriyan 				for (i = 1; i < QUEUE_DEPTH; i++) {
24825c04a7b8SAlexey Dobriyan 					if (++lastTag >= QUEUE_DEPTH)
24835c04a7b8SAlexey Dobriyan 						lastTag = 1;
24845c04a7b8SAlexey Dobriyan 					if (CurrCard->discQ_Tbl[lastTag] ==
24855c04a7b8SAlexey Dobriyan 					    NULL) {
24865c04a7b8SAlexey Dobriyan 						WRW_HARPOON((port +
24875c04a7b8SAlexey Dobriyan 							     ID_MSG_STRT + 6),
24885c04a7b8SAlexey Dobriyan 							    (MPM_OP + AMSG_OUT +
24895c04a7b8SAlexey Dobriyan 							     lastTag));
24901da177e4SLinus Torvalds 						CurrCard->tagQ_Lst = lastTag;
24911da177e4SLinus Torvalds 						currSCCB->Sccb_tag = lastTag;
24925c04a7b8SAlexey Dobriyan 						CurrCard->discQ_Tbl[lastTag] =
24935c04a7b8SAlexey Dobriyan 						    currSCCB;
24941da177e4SLinus Torvalds 						CurrCard->discQCount++;
24951da177e4SLinus Torvalds 						break;
24961da177e4SLinus Torvalds 					}
24971da177e4SLinus Torvalds 				}
24981da177e4SLinus Torvalds 
24995c04a7b8SAlexey Dobriyan 				if (i == QUEUE_DEPTH) {
250047b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[lun] = 1;
250147b5d69cSJames Bottomley  					FPT_queueSelectFail(CurrCard, p_card);
25021da177e4SLinus Torvalds 					SGRAM_ACCESS(port);
25031da177e4SLinus Torvalds 					return;
25041da177e4SLinus Torvalds 				}
25051da177e4SLinus Torvalds 
25061da177e4SLinus Torvalds 				currSCCB->Sccb_scsistat = SELECT_Q_ST;
25071da177e4SLinus Torvalds 
25085c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_3,
25095c04a7b8SAlexey Dobriyan 					   (SELECT + SELCHK_STRT));
25101da177e4SLinus Torvalds 			}
25111da177e4SLinus Torvalds 		}
25121da177e4SLinus Torvalds 
25135c04a7b8SAlexey Dobriyan 		else {
25141da177e4SLinus Torvalds 
25155c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + ID_MSG_STRT),
25165c04a7b8SAlexey Dobriyan 				    BRH_OP + ALWAYS + NTCMD);
25171da177e4SLinus Torvalds 
25181da177e4SLinus Torvalds 			WRW_HARPOON((port + NON_TAG_ID_MSG),
25191da177e4SLinus Torvalds 				    (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
25201da177e4SLinus Torvalds 
25211da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = SELECT_ST;
25221da177e4SLinus Torvalds 
25235c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_3,
25245c04a7b8SAlexey Dobriyan 				   (SELECT + SELCHK_STRT));
25251da177e4SLinus Torvalds 		}
25261da177e4SLinus Torvalds 
2527db038cf8SAlexey Dobriyan 		theCCB = (unsigned char *)&currSCCB->Cdb[0];
25281da177e4SLinus Torvalds 
25291da177e4SLinus Torvalds 		cdb_reg = port + CMD_STRT;
25301da177e4SLinus Torvalds 
25315c04a7b8SAlexey Dobriyan 		for (i = 0; i < currSCCB->CdbLength; i++) {
25321da177e4SLinus Torvalds 			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
25331da177e4SLinus Torvalds 			cdb_reg += 2;
25341da177e4SLinus Torvalds 			theCCB++;
25351da177e4SLinus Torvalds 		}
25361da177e4SLinus Torvalds 
25371da177e4SLinus Torvalds 		if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
25381da177e4SLinus Torvalds 			WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
25391da177e4SLinus Torvalds 
25405c04a7b8SAlexey Dobriyan 	}
25415c04a7b8SAlexey Dobriyan 	/* auto_loaded */
2542c823feebSAlexey Dobriyan 	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
25431da177e4SLinus Torvalds 	WR_HARPOON(port + hp_xferstat, 0x00);
25441da177e4SLinus Torvalds 
25451da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
25461da177e4SLinus Torvalds 
25471da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
25481da177e4SLinus Torvalds 
25495c04a7b8SAlexey Dobriyan 	if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
25505c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_scsictrl_0,
25515c04a7b8SAlexey Dobriyan 			   (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
25525c04a7b8SAlexey Dobriyan 	} else {
25531da177e4SLinus Torvalds 
2554db038cf8SAlexey Dobriyan /*      auto_loaded =  (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
25551da177e4SLinus Torvalds       auto_loaded |= AUTO_IMMED; */
25561da177e4SLinus Torvalds 		auto_loaded = AUTO_IMMED;
25571da177e4SLinus Torvalds 
25581da177e4SLinus Torvalds 		DISABLE_AUTO(port);
25591da177e4SLinus Torvalds 
25601da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, auto_loaded);
25611da177e4SLinus Torvalds 	}
25621da177e4SLinus Torvalds 
25631da177e4SLinus Torvalds 	SGRAM_ACCESS(port);
25641da177e4SLinus Torvalds }
25651da177e4SLinus Torvalds 
25661da177e4SLinus Torvalds /*---------------------------------------------------------------------
25671da177e4SLinus Torvalds  *
256847b5d69cSJames Bottomley   * Function: FPT_sres
25691da177e4SLinus Torvalds  *
25701da177e4SLinus Torvalds  * Description: Hookup the correct CCB and handle the incoming messages.
25711da177e4SLinus Torvalds  *
25721da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
25731da177e4SLinus Torvalds 
FPT_sres(u32 port,unsigned char p_card,struct sccb_card * pCurrCard)2574391e2f25SKhalid Aziz static void FPT_sres(u32 port, unsigned char p_card,
25755c04a7b8SAlexey Dobriyan 		     struct sccb_card *pCurrCard)
25761da177e4SLinus Torvalds {
25771da177e4SLinus Torvalds 
2578db038cf8SAlexey Dobriyan 	unsigned char our_target, message, lun = 0, tag, msgRetryCount;
25791da177e4SLinus Torvalds 
2580f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
258169eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
25821da177e4SLinus Torvalds 
25835c04a7b8SAlexey Dobriyan 	if (pCurrCard->currentSCCB != NULL) {
25845c04a7b8SAlexey Dobriyan 		currTar_Info =
25855c04a7b8SAlexey Dobriyan 		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
25861da177e4SLinus Torvalds 		DISABLE_AUTO(port);
25871da177e4SLinus Torvalds 
25881da177e4SLinus Torvalds 		WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
25891da177e4SLinus Torvalds 
25901da177e4SLinus Torvalds 		currSCCB = pCurrCard->currentSCCB;
25915c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
25921da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
25931da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
25941da177e4SLinus Torvalds 		}
25955c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
25961da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
25971da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
25981da177e4SLinus Torvalds 		}
25991da177e4SLinus Torvalds 		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
26005c04a7b8SAlexey Dobriyan 		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
26015c04a7b8SAlexey Dobriyan 		      TAG_Q_TRYING))) {
260247b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
26035c04a7b8SAlexey Dobriyan 			if (currSCCB->Sccb_scsistat != ABORT_ST) {
26041da177e4SLinus Torvalds 				pCurrCard->discQCount--;
26055c04a7b8SAlexey Dobriyan 				pCurrCard->discQ_Tbl[currTar_Info->
26065c04a7b8SAlexey Dobriyan 						     LunDiscQ_Idx[currSCCB->
26075c04a7b8SAlexey Dobriyan 								  Lun]]
26081da177e4SLinus Torvalds 				    = NULL;
26091da177e4SLinus Torvalds 			}
26105c04a7b8SAlexey Dobriyan 		} else {
261147b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[0] = 0;
26125c04a7b8SAlexey Dobriyan 			if (currSCCB->Sccb_tag) {
26135c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_scsistat != ABORT_ST) {
26141da177e4SLinus Torvalds 					pCurrCard->discQCount--;
26155c04a7b8SAlexey Dobriyan 					pCurrCard->discQ_Tbl[currSCCB->
26165c04a7b8SAlexey Dobriyan 							     Sccb_tag] = NULL;
26171da177e4SLinus Torvalds 				}
26185c04a7b8SAlexey Dobriyan 			} else {
26195c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_scsistat != ABORT_ST) {
26201da177e4SLinus Torvalds 					pCurrCard->discQCount--;
26215c04a7b8SAlexey Dobriyan 					pCurrCard->discQ_Tbl[currTar_Info->
26225c04a7b8SAlexey Dobriyan 							     LunDiscQ_Idx[0]] =
26235c04a7b8SAlexey Dobriyan 					    NULL;
26241da177e4SLinus Torvalds 				}
26251da177e4SLinus Torvalds 			}
26261da177e4SLinus Torvalds 		}
26271da177e4SLinus Torvalds 
262847b5d69cSJames Bottomley  		FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
26291da177e4SLinus Torvalds 	}
26301da177e4SLinus Torvalds 
2631c823feebSAlexey Dobriyan 	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
26321da177e4SLinus Torvalds 
2633db038cf8SAlexey Dobriyan 	our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
263447b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
26351da177e4SLinus Torvalds 
26361da177e4SLinus Torvalds 	msgRetryCount = 0;
26375c04a7b8SAlexey Dobriyan 	do {
26381da177e4SLinus Torvalds 
263947b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
26401da177e4SLinus Torvalds 		tag = 0;
26411da177e4SLinus Torvalds 
26425c04a7b8SAlexey Dobriyan 		while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
26435c04a7b8SAlexey Dobriyan 			if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
26441da177e4SLinus Torvalds 
26451da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PHASE);
26461da177e4SLinus Torvalds 				return;
26471da177e4SLinus Torvalds 			}
26481da177e4SLinus Torvalds 		}
26491da177e4SLinus Torvalds 
26501da177e4SLinus Torvalds 		WRW_HARPOON((port + hp_intstat), PHASE);
26515c04a7b8SAlexey Dobriyan 		if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
26521da177e4SLinus Torvalds 
265347b5d69cSJames Bottomley  			message = FPT_sfm(port, pCurrCard->currentSCCB);
26545c04a7b8SAlexey Dobriyan 			if (message) {
26551da177e4SLinus Torvalds 
26565c04a7b8SAlexey Dobriyan 				if (message <= (0x80 | LUN_MASK)) {
2657db038cf8SAlexey Dobriyan 					lun = message & (unsigned char)LUN_MASK;
26581da177e4SLinus Torvalds 
26595c04a7b8SAlexey Dobriyan 					if ((currTar_Info->
26605c04a7b8SAlexey Dobriyan 					     TarStatus & TAR_TAG_Q_MASK) ==
26615c04a7b8SAlexey Dobriyan 					    TAG_Q_TRYING) {
26625c04a7b8SAlexey Dobriyan 						if (currTar_Info->TarTagQ_Cnt !=
26635c04a7b8SAlexey Dobriyan 						    0) {
26641da177e4SLinus Torvalds 
26655c04a7b8SAlexey Dobriyan 							if (!
26665c04a7b8SAlexey Dobriyan 							    (currTar_Info->
26675c04a7b8SAlexey Dobriyan 							     TarLUN_CA)) {
26681da177e4SLinus Torvalds 								ACCEPT_MSG(port);	/*Release the ACK for ID msg. */
26691da177e4SLinus Torvalds 
26705c04a7b8SAlexey Dobriyan 								message =
26715c04a7b8SAlexey Dobriyan 								    FPT_sfm
26725c04a7b8SAlexey Dobriyan 								    (port,
26735c04a7b8SAlexey Dobriyan 								     pCurrCard->
26745c04a7b8SAlexey Dobriyan 								     currentSCCB);
26755c04a7b8SAlexey Dobriyan 								if (message) {
26765c04a7b8SAlexey Dobriyan 									ACCEPT_MSG
26775c04a7b8SAlexey Dobriyan 									    (port);
26781da177e4SLinus Torvalds 								}
26791da177e4SLinus Torvalds 
26801da177e4SLinus Torvalds 								else
26815c04a7b8SAlexey Dobriyan 									message
26825c04a7b8SAlexey Dobriyan 									    = 0;
26831da177e4SLinus Torvalds 
26845c04a7b8SAlexey Dobriyan 								if (message !=
26855c04a7b8SAlexey Dobriyan 								    0) {
26865c04a7b8SAlexey Dobriyan 									tag =
26875c04a7b8SAlexey Dobriyan 									    FPT_sfm
26885c04a7b8SAlexey Dobriyan 									    (port,
26895c04a7b8SAlexey Dobriyan 									     pCurrCard->
26905c04a7b8SAlexey Dobriyan 									     currentSCCB);
26911da177e4SLinus Torvalds 
26925c04a7b8SAlexey Dobriyan 									if (!
26935c04a7b8SAlexey Dobriyan 									    (tag))
26945c04a7b8SAlexey Dobriyan 										message
26955c04a7b8SAlexey Dobriyan 										    =
26965c04a7b8SAlexey Dobriyan 										    0;
26971da177e4SLinus Torvalds 								}
26981da177e4SLinus Torvalds 
26995c04a7b8SAlexey Dobriyan 							}
27005c04a7b8SAlexey Dobriyan 							/*C.A. exists! */
27015c04a7b8SAlexey Dobriyan 						}
27025c04a7b8SAlexey Dobriyan 						/*End Q cnt != 0 */
27035c04a7b8SAlexey Dobriyan 					}
27045c04a7b8SAlexey Dobriyan 					/*End Tag cmds supported! */
27055c04a7b8SAlexey Dobriyan 				}
27065c04a7b8SAlexey Dobriyan 				/*End valid ID message.  */
27075c04a7b8SAlexey Dobriyan 				else {
27081da177e4SLinus Torvalds 
27091da177e4SLinus Torvalds 					ACCEPT_MSG_ATN(port);
27101da177e4SLinus Torvalds 				}
27111da177e4SLinus Torvalds 
27125c04a7b8SAlexey Dobriyan 			}
27135c04a7b8SAlexey Dobriyan 			/* End good id message. */
27145c04a7b8SAlexey Dobriyan 			else {
27151da177e4SLinus Torvalds 
271647b5d69cSJames Bottomley  				message = 0;
27171da177e4SLinus Torvalds 			}
27185c04a7b8SAlexey Dobriyan 		} else {
27191da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
27201da177e4SLinus Torvalds 
27215c04a7b8SAlexey Dobriyan 			while (!
27225c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((port + hp_intstat)) &
27235c04a7b8SAlexey Dobriyan 				(PHASE | RESET))
27245c04a7b8SAlexey Dobriyan 			       && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
27255c04a7b8SAlexey Dobriyan 			       && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
27261da177e4SLinus Torvalds 
27271da177e4SLinus Torvalds 			return;
27281da177e4SLinus Torvalds 		}
27291da177e4SLinus Torvalds 
27305c04a7b8SAlexey Dobriyan 		if (message == 0) {
27311da177e4SLinus Torvalds 			msgRetryCount++;
27325c04a7b8SAlexey Dobriyan 			if (msgRetryCount == 1) {
2733a87afe28SHannes Reinecke 				FPT_SendMsg(port, MSG_PARITY_ERROR);
27345c04a7b8SAlexey Dobriyan 			} else {
2735a87afe28SHannes Reinecke 				FPT_SendMsg(port, TARGET_RESET);
27361da177e4SLinus Torvalds 
27375c04a7b8SAlexey Dobriyan 				FPT_sssyncv(port, our_target, NARROW_SCSI,
27385c04a7b8SAlexey Dobriyan 					    currTar_Info);
27391da177e4SLinus Torvalds 
27405c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][our_target].
27415c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_SYNC_MASK) {
27421da177e4SLinus Torvalds 
27435c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][our_target].
27445c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_SYNC_MASK;
27451da177e4SLinus Torvalds 
27461da177e4SLinus Torvalds 				}
27471da177e4SLinus Torvalds 
27485c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][our_target].
27495c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_WIDE_SCSI) {
27501da177e4SLinus Torvalds 
27515c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][our_target].
27525c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_WIDE_MASK;
27531da177e4SLinus Torvalds 				}
27541da177e4SLinus Torvalds 
27555c04a7b8SAlexey Dobriyan 				FPT_queueFlushTargSccb(p_card, our_target,
27565c04a7b8SAlexey Dobriyan 						       SCCB_COMPLETE);
275747b5d69cSJames Bottomley  				FPT_SccbMgrTableInitTarget(p_card, our_target);
27581da177e4SLinus Torvalds 				return;
27591da177e4SLinus Torvalds 			}
27601da177e4SLinus Torvalds 		}
276147b5d69cSJames Bottomley  	} while (message == 0);
27621da177e4SLinus Torvalds 
27631da177e4SLinus Torvalds 	if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
27645c04a7b8SAlexey Dobriyan 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
276547b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[lun] = 1;
27665c04a7b8SAlexey Dobriyan 		pCurrCard->currentSCCB =
27675c04a7b8SAlexey Dobriyan 		    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
27685c04a7b8SAlexey Dobriyan 		if (pCurrCard->currentSCCB != NULL) {
27691da177e4SLinus Torvalds 			ACCEPT_MSG(port);
27705c04a7b8SAlexey Dobriyan 		} else {
27711da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
27721da177e4SLinus Torvalds 		}
27735c04a7b8SAlexey Dobriyan 	} else {
277447b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[0] = 1;
27751da177e4SLinus Torvalds 
27765c04a7b8SAlexey Dobriyan 		if (tag) {
27775c04a7b8SAlexey Dobriyan 			if (pCurrCard->discQ_Tbl[tag] != NULL) {
27785c04a7b8SAlexey Dobriyan 				pCurrCard->currentSCCB =
27795c04a7b8SAlexey Dobriyan 				    pCurrCard->discQ_Tbl[tag];
27801da177e4SLinus Torvalds 				currTar_Info->TarTagQ_Cnt--;
27811da177e4SLinus Torvalds 				ACCEPT_MSG(port);
27825c04a7b8SAlexey Dobriyan 			} else {
27831da177e4SLinus Torvalds 				ACCEPT_MSG_ATN(port);
27841da177e4SLinus Torvalds 			}
27855c04a7b8SAlexey Dobriyan 		} else {
27865c04a7b8SAlexey Dobriyan 			pCurrCard->currentSCCB =
27875c04a7b8SAlexey Dobriyan 			    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
27885c04a7b8SAlexey Dobriyan 			if (pCurrCard->currentSCCB != NULL) {
27891da177e4SLinus Torvalds 				ACCEPT_MSG(port);
27905c04a7b8SAlexey Dobriyan 			} else {
27911da177e4SLinus Torvalds 				ACCEPT_MSG_ATN(port);
27921da177e4SLinus Torvalds 			}
27931da177e4SLinus Torvalds 		}
27941da177e4SLinus Torvalds 	}
27951da177e4SLinus Torvalds 
27965c04a7b8SAlexey Dobriyan 	if (pCurrCard->currentSCCB != NULL) {
27975c04a7b8SAlexey Dobriyan 		if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
27981da177e4SLinus Torvalds 			/* During Abort Tag command, the target could have got re-selected
27991da177e4SLinus Torvalds 			   and completed the command. Check the select Q and remove the CCB
28001da177e4SLinus Torvalds 			   if it is in the Select Q */
280147b5d69cSJames Bottomley  			FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
28021da177e4SLinus Torvalds 		}
28031da177e4SLinus Torvalds 	}
28041da177e4SLinus Torvalds 
28051da177e4SLinus Torvalds 	while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
28061da177e4SLinus Torvalds 	       !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
28071da177e4SLinus Torvalds 	       (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
28081da177e4SLinus Torvalds }
28091da177e4SLinus Torvalds 
FPT_SendMsg(u32 port,unsigned char message)2810391e2f25SKhalid Aziz static void FPT_SendMsg(u32 port, unsigned char message)
28111da177e4SLinus Torvalds {
28125c04a7b8SAlexey Dobriyan 	while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
28135c04a7b8SAlexey Dobriyan 		if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
28141da177e4SLinus Torvalds 
28151da177e4SLinus Torvalds 			WRW_HARPOON((port + hp_intstat), PHASE);
28161da177e4SLinus Torvalds 			return;
28171da177e4SLinus Torvalds 		}
28181da177e4SLinus Torvalds 	}
28191da177e4SLinus Torvalds 
28201da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), PHASE);
28215c04a7b8SAlexey Dobriyan 	if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
28225c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + hp_intstat),
28235c04a7b8SAlexey Dobriyan 			    (BUS_FREE | PHASE | XFER_CNT_0));
28241da177e4SLinus Torvalds 
28251da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
28261da177e4SLinus Torvalds 
28271da177e4SLinus Torvalds 		WR_HARPOON(port + hp_scsidata_0, message);
28281da177e4SLinus Torvalds 
28291da177e4SLinus Torvalds 		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
28301da177e4SLinus Torvalds 
28311da177e4SLinus Torvalds 		ACCEPT_MSG(port);
28321da177e4SLinus Torvalds 
28331da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, 0x00);
28341da177e4SLinus Torvalds 
2835a87afe28SHannes Reinecke 		if ((message == ABORT_TASK_SET) || (message == TARGET_RESET) ||
2836a87afe28SHannes Reinecke 		    (message == ABORT_TASK)) {
28375c04a7b8SAlexey Dobriyan 			while (!
28385c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((port + hp_intstat)) &
28395c04a7b8SAlexey Dobriyan 				(BUS_FREE | PHASE))) {
28405c04a7b8SAlexey Dobriyan 			}
28411da177e4SLinus Torvalds 
28425c04a7b8SAlexey Dobriyan 			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
28431da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), BUS_FREE);
28441da177e4SLinus Torvalds 			}
28451da177e4SLinus Torvalds 		}
28461da177e4SLinus Torvalds 	}
28471da177e4SLinus Torvalds }
28481da177e4SLinus Torvalds 
28491da177e4SLinus Torvalds /*---------------------------------------------------------------------
28501da177e4SLinus Torvalds  *
285147b5d69cSJames Bottomley   * Function: FPT_sdecm
28521da177e4SLinus Torvalds  *
285325985edcSLucas De Marchi  * Description: Determine the proper response to the message from the
28541da177e4SLinus Torvalds  *              target device.
28551da177e4SLinus Torvalds  *
28561da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_sdecm(unsigned char message,u32 port,unsigned char p_card)2857391e2f25SKhalid Aziz static void FPT_sdecm(unsigned char message, u32 port, unsigned char p_card)
28581da177e4SLinus Torvalds {
285969eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
286013e6851aSAlexey Dobriyan 	struct sccb_card *CurrCard;
2861f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
28621da177e4SLinus Torvalds 
286347b5d69cSJames Bottomley  	CurrCard = &FPT_BL_Card[p_card];
28641da177e4SLinus Torvalds 	currSCCB = CurrCard->currentSCCB;
28651da177e4SLinus Torvalds 
286647b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
28671da177e4SLinus Torvalds 
2868a87afe28SHannes Reinecke 	if (message == RESTORE_POINTERS) {
28695c04a7b8SAlexey Dobriyan 		if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
28701da177e4SLinus Torvalds 			currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
28711da177e4SLinus Torvalds 
287247b5d69cSJames Bottomley  			FPT_hostDataXferRestart(currSCCB);
28731da177e4SLinus Torvalds 		}
28741da177e4SLinus Torvalds 
28751da177e4SLinus Torvalds 		ACCEPT_MSG(port);
28765c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
28775c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
28781da177e4SLinus Torvalds 	}
28791da177e4SLinus Torvalds 
2880a87afe28SHannes Reinecke 	else if (message == COMMAND_COMPLETE) {
28811da177e4SLinus Torvalds 
28825c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
28835c04a7b8SAlexey Dobriyan 			currTar_Info->TarStatus &=
28845c04a7b8SAlexey Dobriyan 			    ~(unsigned char)TAR_TAG_Q_MASK;
2885db038cf8SAlexey Dobriyan 			currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
28861da177e4SLinus Torvalds 		}
28871da177e4SLinus Torvalds 
28881da177e4SLinus Torvalds 		ACCEPT_MSG(port);
28891da177e4SLinus Torvalds 
28901da177e4SLinus Torvalds 	}
28911da177e4SLinus Torvalds 
2892a87afe28SHannes Reinecke 	else if ((message == NOP) || (message >= IDENTIFY_BASE) ||
2893a87afe28SHannes Reinecke 		 (message == INITIATE_RECOVERY) ||
2894a87afe28SHannes Reinecke 		 (message == RELEASE_RECOVERY)) {
28951da177e4SLinus Torvalds 
28961da177e4SLinus Torvalds 		ACCEPT_MSG(port);
28975c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
28985c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
28991da177e4SLinus Torvalds 	}
29001da177e4SLinus Torvalds 
2901a87afe28SHannes Reinecke 	else if (message == MESSAGE_REJECT) {
29021da177e4SLinus Torvalds 
29031da177e4SLinus Torvalds 		if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
29041da177e4SLinus Torvalds 		    (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
29055c04a7b8SAlexey Dobriyan 		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
29065c04a7b8SAlexey Dobriyan 		    || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
29075c04a7b8SAlexey Dobriyan 			TAG_Q_TRYING))
29081da177e4SLinus Torvalds 		{
29091da177e4SLinus Torvalds 			WRW_HARPOON((port + hp_intstat), BUS_FREE);
29101da177e4SLinus Torvalds 
29111da177e4SLinus Torvalds 			ACCEPT_MSG(port);
29121da177e4SLinus Torvalds 
29131da177e4SLinus Torvalds 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
29145c04a7b8SAlexey Dobriyan 			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
29151da177e4SLinus Torvalds 			{
29161da177e4SLinus Torvalds 			}
29171da177e4SLinus Torvalds 
29185c04a7b8SAlexey Dobriyan 			if (currSCCB->Lun == 0x00) {
2919adb11023SNathan Chancellor 				if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
29201da177e4SLinus Torvalds 
29215c04a7b8SAlexey Dobriyan 					currTar_Info->TarStatus |=
29225c04a7b8SAlexey Dobriyan 					    (unsigned char)SYNC_SUPPORTED;
29231da177e4SLinus Torvalds 
29245c04a7b8SAlexey Dobriyan 					currTar_Info->TarEEValue &=
29255c04a7b8SAlexey Dobriyan 					    ~EE_SYNC_MASK;
29265c04a7b8SAlexey Dobriyan 				}
29271da177e4SLinus Torvalds 
2928adb11023SNathan Chancellor 				else if (currSCCB->Sccb_scsistat ==
2929adb11023SNathan Chancellor 					  SELECT_WN_ST) {
29305c04a7b8SAlexey Dobriyan 
29315c04a7b8SAlexey Dobriyan 					currTar_Info->TarStatus =
29325c04a7b8SAlexey Dobriyan 					    (currTar_Info->
29335c04a7b8SAlexey Dobriyan 					     TarStatus & ~WIDE_ENABLED) |
29345c04a7b8SAlexey Dobriyan 					    WIDE_NEGOCIATED;
29355c04a7b8SAlexey Dobriyan 
29365c04a7b8SAlexey Dobriyan 					currTar_Info->TarEEValue &=
29375c04a7b8SAlexey Dobriyan 					    ~EE_WIDE_SCSI;
29381da177e4SLinus Torvalds 
29391da177e4SLinus Torvalds 				}
29401da177e4SLinus Torvalds 
29415c04a7b8SAlexey Dobriyan 				else if ((currTar_Info->
29425c04a7b8SAlexey Dobriyan 					  TarStatus & TAR_TAG_Q_MASK) ==
29435c04a7b8SAlexey Dobriyan 					 TAG_Q_TRYING) {
29445c04a7b8SAlexey Dobriyan 					currTar_Info->TarStatus =
29455c04a7b8SAlexey Dobriyan 					    (currTar_Info->
29465c04a7b8SAlexey Dobriyan 					     TarStatus & ~(unsigned char)
29475c04a7b8SAlexey Dobriyan 					     TAR_TAG_Q_MASK) | TAG_Q_REJECT;
29481da177e4SLinus Torvalds 
29491da177e4SLinus Torvalds 					currSCCB->ControlByte &= ~F_USE_CMD_Q;
29501da177e4SLinus Torvalds 					CurrCard->discQCount--;
29515c04a7b8SAlexey Dobriyan 					CurrCard->discQ_Tbl[currSCCB->
29525c04a7b8SAlexey Dobriyan 							    Sccb_tag] = NULL;
29531da177e4SLinus Torvalds 					currSCCB->Sccb_tag = 0x00;
29541da177e4SLinus Torvalds 
29551da177e4SLinus Torvalds 				}
29561da177e4SLinus Torvalds 			}
29571da177e4SLinus Torvalds 
29585c04a7b8SAlexey Dobriyan 			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
29591da177e4SLinus Torvalds 
29605c04a7b8SAlexey Dobriyan 				if (currSCCB->Lun == 0x00) {
29615c04a7b8SAlexey Dobriyan 					WRW_HARPOON((port + hp_intstat),
29625c04a7b8SAlexey Dobriyan 						    BUS_FREE);
29631da177e4SLinus Torvalds 					CurrCard->globalFlags |= F_NEW_SCCB_CMD;
29641da177e4SLinus Torvalds 				}
29651da177e4SLinus Torvalds 			}
29661da177e4SLinus Torvalds 
29675c04a7b8SAlexey Dobriyan 			else {
29681da177e4SLinus Torvalds 
29691da177e4SLinus Torvalds 				if ((CurrCard->globalFlags & F_CONLUN_IO) &&
29705c04a7b8SAlexey Dobriyan 				    ((currTar_Info->
29715c04a7b8SAlexey Dobriyan 				      TarStatus & TAR_TAG_Q_MASK) !=
29725c04a7b8SAlexey Dobriyan 				     TAG_Q_TRYING))
29735c04a7b8SAlexey Dobriyan 					currTar_Info->TarLUNBusy[currSCCB->
29745c04a7b8SAlexey Dobriyan 								 Lun] = 1;
29751da177e4SLinus Torvalds 				else
297647b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[0] = 1;
29771da177e4SLinus Torvalds 
29785c04a7b8SAlexey Dobriyan 				currSCCB->ControlByte &=
29795c04a7b8SAlexey Dobriyan 				    ~(unsigned char)F_USE_CMD_Q;
29801da177e4SLinus Torvalds 
29815c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_1,
29825c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + DISCONNECT_START));
29831da177e4SLinus Torvalds 
29841da177e4SLinus Torvalds 			}
29851da177e4SLinus Torvalds 		}
29861da177e4SLinus Torvalds 
29875c04a7b8SAlexey Dobriyan 		else {
29881da177e4SLinus Torvalds 			ACCEPT_MSG(port);
29891da177e4SLinus Torvalds 
29901da177e4SLinus Torvalds 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
29915c04a7b8SAlexey Dobriyan 			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
29921da177e4SLinus Torvalds 			{
29935c04a7b8SAlexey Dobriyan 			}
29945c04a7b8SAlexey Dobriyan 
29955c04a7b8SAlexey Dobriyan 			if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
29965c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_1,
29975c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + DISCONNECT_START));
29981da177e4SLinus Torvalds 			}
29991da177e4SLinus Torvalds 		}
30001da177e4SLinus Torvalds 	}
30011da177e4SLinus Torvalds 
3002a87afe28SHannes Reinecke 	else if (message == EXTENDED_MESSAGE) {
30031da177e4SLinus Torvalds 
30041da177e4SLinus Torvalds 		ACCEPT_MSG(port);
300547b5d69cSJames Bottomley  		FPT_shandem(port, p_card, currSCCB);
30061da177e4SLinus Torvalds 	}
30071da177e4SLinus Torvalds 
3008a87afe28SHannes Reinecke 	else if (message == IGNORE_WIDE_RESIDUE) {
30091da177e4SLinus Torvalds 
30101da177e4SLinus Torvalds 		ACCEPT_MSG(port);	/* ACK the RESIDUE MSG */
30111da177e4SLinus Torvalds 
301247b5d69cSJames Bottomley  		message = FPT_sfm(port, currSCCB);
30131da177e4SLinus Torvalds 
3014a87afe28SHannes Reinecke 		if (currSCCB->Sccb_scsimsg != MSG_PARITY_ERROR)
30151da177e4SLinus Torvalds 			ACCEPT_MSG(port);
30165c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
30175c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
30181da177e4SLinus Torvalds 	}
30191da177e4SLinus Torvalds 
30205c04a7b8SAlexey Dobriyan 	else {
30211da177e4SLinus Torvalds 
30221da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
3023a87afe28SHannes Reinecke 		currSCCB->Sccb_scsimsg = MESSAGE_REJECT;
30241da177e4SLinus Torvalds 
30251da177e4SLinus Torvalds 		ACCEPT_MSG_ATN(port);
30265c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
30275c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
30281da177e4SLinus Torvalds 	}
30291da177e4SLinus Torvalds }
30301da177e4SLinus Torvalds 
30311da177e4SLinus Torvalds /*---------------------------------------------------------------------
30321da177e4SLinus Torvalds  *
303347b5d69cSJames Bottomley   * Function: FPT_shandem
30341da177e4SLinus Torvalds  *
30351da177e4SLinus Torvalds  * Description: Decide what to do with the extended message.
30361da177e4SLinus Torvalds  *
30371da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_shandem(u32 port,unsigned char p_card,struct sccb * pCurrSCCB)3038391e2f25SKhalid Aziz static void FPT_shandem(u32 port, unsigned char p_card, struct sccb *pCurrSCCB)
30391da177e4SLinus Torvalds {
3040db038cf8SAlexey Dobriyan 	unsigned char length, message;
30411da177e4SLinus Torvalds 
304247b5d69cSJames Bottomley  	length = FPT_sfm(port, pCurrSCCB);
30435c04a7b8SAlexey Dobriyan 	if (length) {
30441da177e4SLinus Torvalds 
30451da177e4SLinus Torvalds 		ACCEPT_MSG(port);
304647b5d69cSJames Bottomley  		message = FPT_sfm(port, pCurrSCCB);
30475c04a7b8SAlexey Dobriyan 		if (message) {
30481da177e4SLinus Torvalds 
3049a87afe28SHannes Reinecke 			if (message == EXTENDED_SDTR) {
30501da177e4SLinus Torvalds 
30515c04a7b8SAlexey Dobriyan 				if (length == 0x03) {
30521da177e4SLinus Torvalds 
30531da177e4SLinus Torvalds 					ACCEPT_MSG(port);
305447b5d69cSJames Bottomley  					FPT_stsyncn(port, p_card);
30555c04a7b8SAlexey Dobriyan 				} else {
30561da177e4SLinus Torvalds 
3057a87afe28SHannes Reinecke 					pCurrSCCB->Sccb_scsimsg = MESSAGE_REJECT;
30581da177e4SLinus Torvalds 					ACCEPT_MSG_ATN(port);
30591da177e4SLinus Torvalds 				}
3060a87afe28SHannes Reinecke 			} else if (message == EXTENDED_WDTR) {
30611da177e4SLinus Torvalds 
30625c04a7b8SAlexey Dobriyan 				if (length == 0x02) {
30631da177e4SLinus Torvalds 
30641da177e4SLinus Torvalds 					ACCEPT_MSG(port);
306547b5d69cSJames Bottomley  					FPT_stwidn(port, p_card);
30665c04a7b8SAlexey Dobriyan 				} else {
30671da177e4SLinus Torvalds 
3068a87afe28SHannes Reinecke 					pCurrSCCB->Sccb_scsimsg = MESSAGE_REJECT;
30691da177e4SLinus Torvalds 					ACCEPT_MSG_ATN(port);
30701da177e4SLinus Torvalds 
30715c04a7b8SAlexey Dobriyan 					WR_HARPOON(port + hp_autostart_1,
30725c04a7b8SAlexey Dobriyan 						   (AUTO_IMMED +
30735c04a7b8SAlexey Dobriyan 						    DISCONNECT_START));
30741da177e4SLinus Torvalds 				}
30755c04a7b8SAlexey Dobriyan 			} else {
30761da177e4SLinus Torvalds 
3077a87afe28SHannes Reinecke 				pCurrSCCB->Sccb_scsimsg = MESSAGE_REJECT;
30781da177e4SLinus Torvalds 				ACCEPT_MSG_ATN(port);
30791da177e4SLinus Torvalds 
30805c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_1,
30815c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + DISCONNECT_START));
30821da177e4SLinus Torvalds 			}
30835c04a7b8SAlexey Dobriyan 		} else {
3084a87afe28SHannes Reinecke 			if (pCurrSCCB->Sccb_scsimsg != MSG_PARITY_ERROR)
30851da177e4SLinus Torvalds 				ACCEPT_MSG(port);
30865c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
30875c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
30881da177e4SLinus Torvalds 		}
30895c04a7b8SAlexey Dobriyan 	} else {
3090a87afe28SHannes Reinecke 		if (pCurrSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)
30915c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
30925c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
30931da177e4SLinus Torvalds 	}
30941da177e4SLinus Torvalds }
30951da177e4SLinus Torvalds 
30961da177e4SLinus Torvalds /*---------------------------------------------------------------------
30971da177e4SLinus Torvalds  *
309847b5d69cSJames Bottomley   * Function: FPT_sisyncn
30991da177e4SLinus Torvalds  *
31001da177e4SLinus Torvalds  * Description: Read in a message byte from the SCSI bus, and check
31011da177e4SLinus Torvalds  *              for a parity error.
31021da177e4SLinus Torvalds  *
31031da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
31041da177e4SLinus Torvalds 
FPT_sisyncn(u32 port,unsigned char p_card,unsigned char syncFlag)3105391e2f25SKhalid Aziz static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
31065c04a7b8SAlexey Dobriyan 				 unsigned char syncFlag)
31071da177e4SLinus Torvalds {
310869eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3109f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
31101da177e4SLinus Torvalds 
311147b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
311247b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
31131da177e4SLinus Torvalds 
31141da177e4SLinus Torvalds 	if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
31151da177e4SLinus Torvalds 
31161da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT),
31175c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT +
31185c04a7b8SAlexey Dobriyan 			     (currSCCB->
31195c04a7b8SAlexey Dobriyan 			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
31201da177e4SLinus Torvalds 
31211da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
31221da177e4SLinus Torvalds 
31235c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 0),
3124a87afe28SHannes Reinecke 			    (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
31251da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
31265c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 4),
3127a87afe28SHannes Reinecke 			    (MPM_OP + AMSG_OUT + EXTENDED_SDTR));
31281da177e4SLinus Torvalds 
31291da177e4SLinus Torvalds 		if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
31301da177e4SLinus Torvalds 
31315c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31325c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 12));
31331da177e4SLinus Torvalds 
31345c04a7b8SAlexey Dobriyan 		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
31355c04a7b8SAlexey Dobriyan 			 EE_SYNC_10MB)
31361da177e4SLinus Torvalds 
31375c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31385c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 25));
31391da177e4SLinus Torvalds 
31405c04a7b8SAlexey Dobriyan 		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
31415c04a7b8SAlexey Dobriyan 			 EE_SYNC_5MB)
31421da177e4SLinus Torvalds 
31435c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31445c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 50));
31451da177e4SLinus Torvalds 
31461da177e4SLinus Torvalds 		else
31475c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31485c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 00));
31491da177e4SLinus Torvalds 
31501da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
31515c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 10),
31525c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
31531da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
31541da177e4SLinus Torvalds 
31555c04a7b8SAlexey Dobriyan 		if (syncFlag == 0) {
31565c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_3,
31575c04a7b8SAlexey Dobriyan 				   (SELECT + SELCHK_STRT));
31585c04a7b8SAlexey Dobriyan 			currTar_Info->TarStatus =
31595c04a7b8SAlexey Dobriyan 			    ((currTar_Info->
31605c04a7b8SAlexey Dobriyan 			      TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
31615c04a7b8SAlexey Dobriyan 			     (unsigned char)SYNC_TRYING);
31625c04a7b8SAlexey Dobriyan 		} else {
31635c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_3,
31645c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + CMD_ONLY_STRT));
31651da177e4SLinus Torvalds 		}
31661da177e4SLinus Torvalds 
31675c1b85e2SAlexey Dobriyan 		return 1;
31681da177e4SLinus Torvalds 	}
31691da177e4SLinus Torvalds 
31701da177e4SLinus Torvalds 	else {
31711da177e4SLinus Torvalds 
3172db038cf8SAlexey Dobriyan 		currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
31731da177e4SLinus Torvalds 		currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
31745c1b85e2SAlexey Dobriyan 		return 0;
31751da177e4SLinus Torvalds 	}
31761da177e4SLinus Torvalds }
31771da177e4SLinus Torvalds 
31781da177e4SLinus Torvalds /*---------------------------------------------------------------------
31791da177e4SLinus Torvalds  *
318047b5d69cSJames Bottomley   * Function: FPT_stsyncn
31811da177e4SLinus Torvalds  *
31821da177e4SLinus Torvalds  * Description: The has sent us a Sync Nego message so handle it as
31831da177e4SLinus Torvalds  *              necessary.
31841da177e4SLinus Torvalds  *
31851da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_stsyncn(u32 port,unsigned char p_card)3186391e2f25SKhalid Aziz static void FPT_stsyncn(u32 port, unsigned char p_card)
31871da177e4SLinus Torvalds {
3188db038cf8SAlexey Dobriyan 	unsigned char sync_msg, offset, sync_reg, our_sync_msg;
318969eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3190f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
31911da177e4SLinus Torvalds 
319247b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
319347b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
31941da177e4SLinus Torvalds 
319547b5d69cSJames Bottomley  	sync_msg = FPT_sfm(port, currSCCB);
31961da177e4SLinus Torvalds 
3197a87afe28SHannes Reinecke 	if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)) {
31985c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
31995c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
32001da177e4SLinus Torvalds 		return;
32011da177e4SLinus Torvalds 	}
32021da177e4SLinus Torvalds 
32031da177e4SLinus Torvalds 	ACCEPT_MSG(port);
32041da177e4SLinus Torvalds 
320547b5d69cSJames Bottomley  	offset = FPT_sfm(port, currSCCB);
32061da177e4SLinus Torvalds 
3207a87afe28SHannes Reinecke 	if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)) {
32085c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
32095c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
32101da177e4SLinus Torvalds 		return;
32111da177e4SLinus Torvalds 	}
32121da177e4SLinus Torvalds 
32131da177e4SLinus Torvalds 	if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
32141da177e4SLinus Torvalds 
32151da177e4SLinus Torvalds 		our_sync_msg = 12;	/* Setup our Message to 20mb/s */
32161da177e4SLinus Torvalds 
32171da177e4SLinus Torvalds 	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
32181da177e4SLinus Torvalds 
32191da177e4SLinus Torvalds 		our_sync_msg = 25;	/* Setup our Message to 10mb/s */
32201da177e4SLinus Torvalds 
32211da177e4SLinus Torvalds 	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
32221da177e4SLinus Torvalds 
32231da177e4SLinus Torvalds 		our_sync_msg = 50;	/* Setup our Message to 5mb/s */
32241da177e4SLinus Torvalds 	else
32251da177e4SLinus Torvalds 
32261da177e4SLinus Torvalds 		our_sync_msg = 0;	/* Message = Async */
32271da177e4SLinus Torvalds 
32281da177e4SLinus Torvalds 	if (sync_msg < our_sync_msg) {
32291da177e4SLinus Torvalds 		sync_msg = our_sync_msg;	/*if faster, then set to max. */
32301da177e4SLinus Torvalds 	}
32311da177e4SLinus Torvalds 
32321da177e4SLinus Torvalds 	if (offset == ASYNC)
32331da177e4SLinus Torvalds 		sync_msg = ASYNC;
32341da177e4SLinus Torvalds 
32351da177e4SLinus Torvalds 	if (offset > MAX_OFFSET)
32361da177e4SLinus Torvalds 		offset = MAX_OFFSET;
32371da177e4SLinus Torvalds 
32381da177e4SLinus Torvalds 	sync_reg = 0x00;
32391da177e4SLinus Torvalds 
32401da177e4SLinus Torvalds 	if (sync_msg > 12)
32411da177e4SLinus Torvalds 
32421da177e4SLinus Torvalds 		sync_reg = 0x20;	/* Use 10MB/s */
32431da177e4SLinus Torvalds 
32441da177e4SLinus Torvalds 	if (sync_msg > 25)
32451da177e4SLinus Torvalds 
32461da177e4SLinus Torvalds 		sync_reg = 0x40;	/* Use 6.6MB/s */
32471da177e4SLinus Torvalds 
32481da177e4SLinus Torvalds 	if (sync_msg > 38)
32491da177e4SLinus Torvalds 
32501da177e4SLinus Torvalds 		sync_reg = 0x60;	/* Use 5MB/s */
32511da177e4SLinus Torvalds 
32521da177e4SLinus Torvalds 	if (sync_msg > 50)
32531da177e4SLinus Torvalds 
32541da177e4SLinus Torvalds 		sync_reg = 0x80;	/* Use 4MB/s */
32551da177e4SLinus Torvalds 
32561da177e4SLinus Torvalds 	if (sync_msg > 62)
32571da177e4SLinus Torvalds 
32581da177e4SLinus Torvalds 		sync_reg = 0xA0;	/* Use 3.33MB/s */
32591da177e4SLinus Torvalds 
32601da177e4SLinus Torvalds 	if (sync_msg > 75)
32611da177e4SLinus Torvalds 
32621da177e4SLinus Torvalds 		sync_reg = 0xC0;	/* Use 2.85MB/s */
32631da177e4SLinus Torvalds 
32641da177e4SLinus Torvalds 	if (sync_msg > 87)
32651da177e4SLinus Torvalds 
32661da177e4SLinus Torvalds 		sync_reg = 0xE0;	/* Use 2.5MB/s */
32671da177e4SLinus Torvalds 
32681da177e4SLinus Torvalds 	if (sync_msg > 100) {
32691da177e4SLinus Torvalds 
32701da177e4SLinus Torvalds 		sync_reg = 0x00;	/* Use ASYNC */
32711da177e4SLinus Torvalds 		offset = 0x00;
32721da177e4SLinus Torvalds 	}
32731da177e4SLinus Torvalds 
32741da177e4SLinus Torvalds 	if (currTar_Info->TarStatus & WIDE_ENABLED)
32751da177e4SLinus Torvalds 
32761da177e4SLinus Torvalds 		sync_reg |= offset;
32771da177e4SLinus Torvalds 
32781da177e4SLinus Torvalds 	else
32791da177e4SLinus Torvalds 
32801da177e4SLinus Torvalds 		sync_reg |= (offset | NARROW_SCSI);
32811da177e4SLinus Torvalds 
328247b5d69cSJames Bottomley  	FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
32831da177e4SLinus Torvalds 
32841da177e4SLinus Torvalds 	if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
32851da177e4SLinus Torvalds 
32861da177e4SLinus Torvalds 		ACCEPT_MSG(port);
32871da177e4SLinus Torvalds 
32881da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
32895c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_SYNC_MASK) |
32905c04a7b8SAlexey Dobriyan 					   (unsigned char)SYNC_SUPPORTED);
32911da177e4SLinus Torvalds 
32925c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
32935c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
32941da177e4SLinus Torvalds 	}
32951da177e4SLinus Torvalds 
32961da177e4SLinus Torvalds 	else {
32971da177e4SLinus Torvalds 
32981da177e4SLinus Torvalds 		ACCEPT_MSG_ATN(port);
32991da177e4SLinus Torvalds 
330047b5d69cSJames Bottomley  		FPT_sisyncr(port, sync_msg, offset);
33011da177e4SLinus Torvalds 
33021da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
33035c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_SYNC_MASK) |
33045c04a7b8SAlexey Dobriyan 					   (unsigned char)SYNC_SUPPORTED);
33051da177e4SLinus Torvalds 	}
33061da177e4SLinus Torvalds }
33071da177e4SLinus Torvalds 
33081da177e4SLinus Torvalds /*---------------------------------------------------------------------
33091da177e4SLinus Torvalds  *
331047b5d69cSJames Bottomley   * Function: FPT_sisyncr
33111da177e4SLinus Torvalds  *
33121da177e4SLinus Torvalds  * Description: Answer the targets sync message.
33131da177e4SLinus Torvalds  *
33141da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_sisyncr(u32 port,unsigned char sync_pulse,unsigned char offset)3315391e2f25SKhalid Aziz static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
33165c04a7b8SAlexey Dobriyan 			unsigned char offset)
33171da177e4SLinus Torvalds {
33181da177e4SLinus Torvalds 	ARAM_ACCESS(port);
3319a87afe28SHannes Reinecke 	WRW_HARPOON((port + SYNC_MSGS + 0),
3320a87afe28SHannes Reinecke 		    (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
33211da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3322a87afe28SHannes Reinecke 	WRW_HARPOON((port + SYNC_MSGS + 4),
3323a87afe28SHannes Reinecke 		    (MPM_OP + AMSG_OUT + EXTENDED_SDTR));
33241da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
33251da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
33261da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
33271da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
33281da177e4SLinus Torvalds 	SGRAM_ACCESS(port);
33291da177e4SLinus Torvalds 
33301da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
33311da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
33321da177e4SLinus Torvalds 
33331da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
33341da177e4SLinus Torvalds 
33355c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
33361da177e4SLinus Torvalds 	}
33375c04a7b8SAlexey Dobriyan }
33381da177e4SLinus Torvalds 
33391da177e4SLinus Torvalds /*---------------------------------------------------------------------
33401da177e4SLinus Torvalds  *
334147b5d69cSJames Bottomley   * Function: FPT_siwidn
33421da177e4SLinus Torvalds  *
33431da177e4SLinus Torvalds  * Description: Read in a message byte from the SCSI bus, and check
33441da177e4SLinus Torvalds  *              for a parity error.
33451da177e4SLinus Torvalds  *
33461da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
33471da177e4SLinus Torvalds 
FPT_siwidn(u32 port,unsigned char p_card)3348391e2f25SKhalid Aziz static unsigned char FPT_siwidn(u32 port, unsigned char p_card)
33491da177e4SLinus Torvalds {
335069eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3351f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
33521da177e4SLinus Torvalds 
335347b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
335447b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
33551da177e4SLinus Torvalds 
33561da177e4SLinus Torvalds 	if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
33571da177e4SLinus Torvalds 
33581da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT),
33595c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT +
33605c04a7b8SAlexey Dobriyan 			     (currSCCB->
33615c04a7b8SAlexey Dobriyan 			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
33621da177e4SLinus Torvalds 
33631da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
33641da177e4SLinus Torvalds 
33655c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 0),
3366a87afe28SHannes Reinecke 			    (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
33671da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
33685c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 4),
3369a87afe28SHannes Reinecke 			    (MPM_OP + AMSG_OUT + EXTENDED_WDTR));
33701da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
33715c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 8),
33725c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + SM16BIT));
33731da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
33741da177e4SLinus Torvalds 
33751da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
33761da177e4SLinus Torvalds 
33771da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
33785c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_WIDE_MASK) |
33795c04a7b8SAlexey Dobriyan 					   (unsigned char)WIDE_ENABLED);
33801da177e4SLinus Torvalds 
33815c1b85e2SAlexey Dobriyan 		return 1;
33821da177e4SLinus Torvalds 	}
33831da177e4SLinus Torvalds 
33841da177e4SLinus Torvalds 	else {
33851da177e4SLinus Torvalds 
33861da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
33875c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_WIDE_MASK) |
33885c04a7b8SAlexey Dobriyan 					   WIDE_NEGOCIATED);
33891da177e4SLinus Torvalds 
33901da177e4SLinus Torvalds 		currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
33915c1b85e2SAlexey Dobriyan 		return 0;
33921da177e4SLinus Torvalds 	}
33931da177e4SLinus Torvalds }
33941da177e4SLinus Torvalds 
33951da177e4SLinus Torvalds /*---------------------------------------------------------------------
33961da177e4SLinus Torvalds  *
339747b5d69cSJames Bottomley   * Function: FPT_stwidn
33981da177e4SLinus Torvalds  *
33991da177e4SLinus Torvalds  * Description: The has sent us a Wide Nego message so handle it as
34001da177e4SLinus Torvalds  *              necessary.
34011da177e4SLinus Torvalds  *
34021da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_stwidn(u32 port,unsigned char p_card)3403391e2f25SKhalid Aziz static void FPT_stwidn(u32 port, unsigned char p_card)
34041da177e4SLinus Torvalds {
3405db038cf8SAlexey Dobriyan 	unsigned char width;
340669eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3407f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
34081da177e4SLinus Torvalds 
340947b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
341047b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
34111da177e4SLinus Torvalds 
341247b5d69cSJames Bottomley  	width = FPT_sfm(port, currSCCB);
34131da177e4SLinus Torvalds 
3414a87afe28SHannes Reinecke 	if ((width == 0x00) && (currSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)) {
34155c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
34165c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
34171da177e4SLinus Torvalds 		return;
34181da177e4SLinus Torvalds 	}
34191da177e4SLinus Torvalds 
34201da177e4SLinus Torvalds 	if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
34211da177e4SLinus Torvalds 		width = 0;
34221da177e4SLinus Torvalds 
34231da177e4SLinus Torvalds 	if (width) {
34241da177e4SLinus Torvalds 		currTar_Info->TarStatus |= WIDE_ENABLED;
34251da177e4SLinus Torvalds 		width = 0;
34265c04a7b8SAlexey Dobriyan 	} else {
34271da177e4SLinus Torvalds 		width = NARROW_SCSI;
34281da177e4SLinus Torvalds 		currTar_Info->TarStatus &= ~WIDE_ENABLED;
34291da177e4SLinus Torvalds 	}
34301da177e4SLinus Torvalds 
343147b5d69cSJames Bottomley  	FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
34321da177e4SLinus Torvalds 
34335c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
34341da177e4SLinus Torvalds 
34351da177e4SLinus Torvalds 		currTar_Info->TarStatus |= WIDE_NEGOCIATED;
34361da177e4SLinus Torvalds 
34375c04a7b8SAlexey Dobriyan 		if (!
34385c04a7b8SAlexey Dobriyan 		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
34395c04a7b8SAlexey Dobriyan 		     SYNC_SUPPORTED)) {
34401da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
34411da177e4SLinus Torvalds 			ARAM_ACCESS(port);
344247b5d69cSJames Bottomley  			FPT_sisyncn(port, p_card, 1);
34431da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = SELECT_SN_ST;
34441da177e4SLinus Torvalds 			SGRAM_ACCESS(port);
34455c04a7b8SAlexey Dobriyan 		} else {
34461da177e4SLinus Torvalds 			ACCEPT_MSG(port);
34475c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
34485c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
34491da177e4SLinus Torvalds 		}
34501da177e4SLinus Torvalds 	}
34511da177e4SLinus Torvalds 
34521da177e4SLinus Torvalds 	else {
34531da177e4SLinus Torvalds 
34541da177e4SLinus Torvalds 		ACCEPT_MSG_ATN(port);
34551da177e4SLinus Torvalds 
34561da177e4SLinus Torvalds 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
34571da177e4SLinus Torvalds 			width = SM16BIT;
34581da177e4SLinus Torvalds 		else
34591da177e4SLinus Torvalds 			width = SM8BIT;
34601da177e4SLinus Torvalds 
346147b5d69cSJames Bottomley  		FPT_siwidr(port, width);
34621da177e4SLinus Torvalds 
34631da177e4SLinus Torvalds 		currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
34641da177e4SLinus Torvalds 	}
34651da177e4SLinus Torvalds }
34661da177e4SLinus Torvalds 
34671da177e4SLinus Torvalds /*---------------------------------------------------------------------
34681da177e4SLinus Torvalds  *
346947b5d69cSJames Bottomley   * Function: FPT_siwidr
34701da177e4SLinus Torvalds  *
34711da177e4SLinus Torvalds  * Description: Answer the targets Wide nego message.
34721da177e4SLinus Torvalds  *
34731da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_siwidr(u32 port,unsigned char width)3474391e2f25SKhalid Aziz static void FPT_siwidr(u32 port, unsigned char width)
34751da177e4SLinus Torvalds {
34761da177e4SLinus Torvalds 	ARAM_ACCESS(port);
3477a87afe28SHannes Reinecke 	WRW_HARPOON((port + SYNC_MSGS + 0),
3478a87afe28SHannes Reinecke 		    (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
34791da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3480a87afe28SHannes Reinecke 	WRW_HARPOON((port + SYNC_MSGS + 4),
3481a87afe28SHannes Reinecke 		    (MPM_OP + AMSG_OUT + EXTENDED_WDTR));
34821da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
34831da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
34841da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
34851da177e4SLinus Torvalds 	SGRAM_ACCESS(port);
34861da177e4SLinus Torvalds 
34871da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
34881da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
34891da177e4SLinus Torvalds 
34901da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
34911da177e4SLinus Torvalds 
34925c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
34931da177e4SLinus Torvalds 	}
34945c04a7b8SAlexey Dobriyan }
34951da177e4SLinus Torvalds 
34961da177e4SLinus Torvalds /*---------------------------------------------------------------------
34971da177e4SLinus Torvalds  *
349847b5d69cSJames Bottomley   * Function: FPT_sssyncv
34991da177e4SLinus Torvalds  *
35001da177e4SLinus Torvalds  * Description: Write the desired value to the Sync Register for the
35011da177e4SLinus Torvalds  *              ID specified.
35021da177e4SLinus Torvalds  *
35031da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_sssyncv(u32 p_port,unsigned char p_id,unsigned char p_sync_value,struct sccb_mgr_tar_info * currTar_Info)3504391e2f25SKhalid Aziz static void FPT_sssyncv(u32 p_port, unsigned char p_id,
35055c04a7b8SAlexey Dobriyan 			unsigned char p_sync_value,
3506f31dc0cdSAlexey Dobriyan 			struct sccb_mgr_tar_info *currTar_Info)
35071da177e4SLinus Torvalds {
3508db038cf8SAlexey Dobriyan 	unsigned char index;
35091da177e4SLinus Torvalds 
35101da177e4SLinus Torvalds 	index = p_id;
35111da177e4SLinus Torvalds 
35121da177e4SLinus Torvalds 	switch (index) {
35131da177e4SLinus Torvalds 
35141da177e4SLinus Torvalds 	case 0:
35151da177e4SLinus Torvalds 		index = 12;	/* hp_synctarg_0 */
35161da177e4SLinus Torvalds 		break;
35171da177e4SLinus Torvalds 	case 1:
35181da177e4SLinus Torvalds 		index = 13;	/* hp_synctarg_1 */
35191da177e4SLinus Torvalds 		break;
35201da177e4SLinus Torvalds 	case 2:
35211da177e4SLinus Torvalds 		index = 14;	/* hp_synctarg_2 */
35221da177e4SLinus Torvalds 		break;
35231da177e4SLinus Torvalds 	case 3:
35241da177e4SLinus Torvalds 		index = 15;	/* hp_synctarg_3 */
35251da177e4SLinus Torvalds 		break;
35261da177e4SLinus Torvalds 	case 4:
35271da177e4SLinus Torvalds 		index = 8;	/* hp_synctarg_4 */
35281da177e4SLinus Torvalds 		break;
35291da177e4SLinus Torvalds 	case 5:
35301da177e4SLinus Torvalds 		index = 9;	/* hp_synctarg_5 */
35311da177e4SLinus Torvalds 		break;
35321da177e4SLinus Torvalds 	case 6:
35331da177e4SLinus Torvalds 		index = 10;	/* hp_synctarg_6 */
35341da177e4SLinus Torvalds 		break;
35351da177e4SLinus Torvalds 	case 7:
35361da177e4SLinus Torvalds 		index = 11;	/* hp_synctarg_7 */
35371da177e4SLinus Torvalds 		break;
35381da177e4SLinus Torvalds 	case 8:
35391da177e4SLinus Torvalds 		index = 4;	/* hp_synctarg_8 */
35401da177e4SLinus Torvalds 		break;
35411da177e4SLinus Torvalds 	case 9:
35421da177e4SLinus Torvalds 		index = 5;	/* hp_synctarg_9 */
35431da177e4SLinus Torvalds 		break;
35441da177e4SLinus Torvalds 	case 10:
35451da177e4SLinus Torvalds 		index = 6;	/* hp_synctarg_10 */
35461da177e4SLinus Torvalds 		break;
35471da177e4SLinus Torvalds 	case 11:
35481da177e4SLinus Torvalds 		index = 7;	/* hp_synctarg_11 */
35491da177e4SLinus Torvalds 		break;
35501da177e4SLinus Torvalds 	case 12:
35511da177e4SLinus Torvalds 		index = 0;	/* hp_synctarg_12 */
35521da177e4SLinus Torvalds 		break;
35531da177e4SLinus Torvalds 	case 13:
35541da177e4SLinus Torvalds 		index = 1;	/* hp_synctarg_13 */
35551da177e4SLinus Torvalds 		break;
35561da177e4SLinus Torvalds 	case 14:
35571da177e4SLinus Torvalds 		index = 2;	/* hp_synctarg_14 */
35581da177e4SLinus Torvalds 		break;
35591da177e4SLinus Torvalds 	case 15:
35601da177e4SLinus Torvalds 		index = 3;	/* hp_synctarg_15 */
35611da177e4SLinus Torvalds 
35621da177e4SLinus Torvalds 	}
35631da177e4SLinus Torvalds 
35641da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
35651da177e4SLinus Torvalds 
35661da177e4SLinus Torvalds 	currTar_Info->TarSyncCtrl = p_sync_value;
35671da177e4SLinus Torvalds }
35681da177e4SLinus Torvalds 
35691da177e4SLinus Torvalds /*---------------------------------------------------------------------
35701da177e4SLinus Torvalds  *
357147b5d69cSJames Bottomley   * Function: FPT_sresb
35721da177e4SLinus Torvalds  *
35731da177e4SLinus Torvalds  * Description: Reset the desired card's SCSI bus.
35741da177e4SLinus Torvalds  *
35751da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_sresb(u32 port,unsigned char p_card)3576391e2f25SKhalid Aziz static void FPT_sresb(u32 port, unsigned char p_card)
35771da177e4SLinus Torvalds {
3578db038cf8SAlexey Dobriyan 	unsigned char scsiID, i;
35791da177e4SLinus Torvalds 
3580f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
35811da177e4SLinus Torvalds 
35821da177e4SLinus Torvalds 	WR_HARPOON(port + hp_page_ctrl,
35831da177e4SLinus Torvalds 		   (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
35841da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
35851da177e4SLinus Torvalds 
35861da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
35871da177e4SLinus Torvalds 
35881da177e4SLinus Torvalds 	scsiID = RD_HARPOON(port + hp_seltimeout);
35891da177e4SLinus Torvalds 	WR_HARPOON(port + hp_seltimeout, TO_5ms);
35901da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), TIMEOUT);
35911da177e4SLinus Torvalds 
35921da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
35931da177e4SLinus Torvalds 
35945c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
35955c04a7b8SAlexey Dobriyan 	}
35961da177e4SLinus Torvalds 
35971da177e4SLinus Torvalds 	WR_HARPOON(port + hp_seltimeout, scsiID);
35981da177e4SLinus Torvalds 
35991da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
36001da177e4SLinus Torvalds 
360147b5d69cSJames Bottomley  	FPT_Wait(port, TO_5ms);
36021da177e4SLinus Torvalds 
36031da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
36041da177e4SLinus Torvalds 
36051da177e4SLinus Torvalds 	WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
36061da177e4SLinus Torvalds 
36075c04a7b8SAlexey Dobriyan 	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
360847b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
36091da177e4SLinus Torvalds 
36105c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
36111da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
36121da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
36131da177e4SLinus Torvalds 		}
36141da177e4SLinus Torvalds 
36155c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
36161da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
36171da177e4SLinus Torvalds 		}
36181da177e4SLinus Torvalds 
361947b5d69cSJames Bottomley  		FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
36201da177e4SLinus Torvalds 
362147b5d69cSJames Bottomley  		FPT_SccbMgrTableInitTarget(p_card, scsiID);
36221da177e4SLinus Torvalds 	}
36231da177e4SLinus Torvalds 
362447b5d69cSJames Bottomley  	FPT_BL_Card[p_card].scanIndex = 0x00;
362547b5d69cSJames Bottomley  	FPT_BL_Card[p_card].currentSCCB = NULL;
362647b5d69cSJames Bottomley  	FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
36271da177e4SLinus Torvalds 					     | F_NEW_SCCB_CMD);
362847b5d69cSJames Bottomley  	FPT_BL_Card[p_card].cmdCounter = 0x00;
362947b5d69cSJames Bottomley  	FPT_BL_Card[p_card].discQCount = 0x00;
363047b5d69cSJames Bottomley  	FPT_BL_Card[p_card].tagQ_Lst = 0x01;
36311da177e4SLinus Torvalds 
36321da177e4SLinus Torvalds 	for (i = 0; i < QUEUE_DEPTH; i++)
363347b5d69cSJames Bottomley  		FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
36341da177e4SLinus Torvalds 
36351da177e4SLinus Torvalds 	WR_HARPOON(port + hp_page_ctrl,
36361da177e4SLinus Torvalds 		   (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
36371da177e4SLinus Torvalds 
36381da177e4SLinus Torvalds }
36391da177e4SLinus Torvalds 
36401da177e4SLinus Torvalds /*---------------------------------------------------------------------
36411da177e4SLinus Torvalds  *
364247b5d69cSJames Bottomley   * Function: FPT_ssenss
36431da177e4SLinus Torvalds  *
36441da177e4SLinus Torvalds  * Description: Setup for the Auto Sense command.
36451da177e4SLinus Torvalds  *
36461da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_ssenss(struct sccb_card * pCurrCard)364713e6851aSAlexey Dobriyan static void FPT_ssenss(struct sccb_card *pCurrCard)
36481da177e4SLinus Torvalds {
3649db038cf8SAlexey Dobriyan 	unsigned char i;
365069eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
36511da177e4SLinus Torvalds 
36521da177e4SLinus Torvalds 	currSCCB = pCurrCard->currentSCCB;
36531da177e4SLinus Torvalds 
36541da177e4SLinus Torvalds 	currSCCB->Save_CdbLen = currSCCB->CdbLength;
36551da177e4SLinus Torvalds 
36561da177e4SLinus Torvalds 	for (i = 0; i < 6; i++) {
36571da177e4SLinus Torvalds 
36581da177e4SLinus Torvalds 		currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
36591da177e4SLinus Torvalds 	}
36601da177e4SLinus Torvalds 
36611da177e4SLinus Torvalds 	currSCCB->CdbLength = SIX_BYTE_CMD;
3662a87afe28SHannes Reinecke 	currSCCB->Cdb[0] = REQUEST_SENSE;
3663db038cf8SAlexey Dobriyan 	currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0;	/*Keep LUN. */
36641da177e4SLinus Torvalds 	currSCCB->Cdb[2] = 0x00;
36651da177e4SLinus Torvalds 	currSCCB->Cdb[3] = 0x00;
36661da177e4SLinus Torvalds 	currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
36671da177e4SLinus Torvalds 	currSCCB->Cdb[5] = 0x00;
36681da177e4SLinus Torvalds 
3669391e2f25SKhalid Aziz 	currSCCB->Sccb_XferCnt = (u32)currSCCB->RequestSenseLength;
36701da177e4SLinus Torvalds 
36711da177e4SLinus Torvalds 	currSCCB->Sccb_ATC = 0x00;
36721da177e4SLinus Torvalds 
36731da177e4SLinus Torvalds 	currSCCB->Sccb_XferState |= F_AUTO_SENSE;
36741da177e4SLinus Torvalds 
36751da177e4SLinus Torvalds 	currSCCB->Sccb_XferState &= ~F_SG_XFER;
36761da177e4SLinus Torvalds 
3677db038cf8SAlexey Dobriyan 	currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
36781da177e4SLinus Torvalds 
36791da177e4SLinus Torvalds 	currSCCB->ControlByte = 0x00;
36801da177e4SLinus Torvalds 
36811da177e4SLinus Torvalds 	currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
36821da177e4SLinus Torvalds }
36831da177e4SLinus Torvalds 
36841da177e4SLinus Torvalds /*---------------------------------------------------------------------
36851da177e4SLinus Torvalds  *
368647b5d69cSJames Bottomley   * Function: FPT_sxfrp
36871da177e4SLinus Torvalds  *
36881da177e4SLinus Torvalds  * Description: Transfer data into the bit bucket until the device
36891da177e4SLinus Torvalds  *              decides to switch phase.
36901da177e4SLinus Torvalds  *
36911da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
36921da177e4SLinus Torvalds 
FPT_sxfrp(u32 p_port,unsigned char p_card)3693391e2f25SKhalid Aziz static void FPT_sxfrp(u32 p_port, unsigned char p_card)
36941da177e4SLinus Torvalds {
3695db038cf8SAlexey Dobriyan 	unsigned char curr_phz;
36961da177e4SLinus Torvalds 
36971da177e4SLinus Torvalds 	DISABLE_AUTO(p_port);
36981da177e4SLinus Torvalds 
369947b5d69cSJames Bottomley  	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
37001da177e4SLinus Torvalds 
37015c04a7b8SAlexey Dobriyan 		FPT_hostDataXferAbort(p_port, p_card,
37025c04a7b8SAlexey Dobriyan 				      FPT_BL_Card[p_card].currentSCCB);
37031da177e4SLinus Torvalds 
37041da177e4SLinus Torvalds 	}
37051da177e4SLinus Torvalds 
37061da177e4SLinus Torvalds 	/* If the Automation handled the end of the transfer then do not
37071da177e4SLinus Torvalds 	   match the phase or we will get out of sync with the ISR.       */
37081da177e4SLinus Torvalds 
37095c04a7b8SAlexey Dobriyan 	if (RDW_HARPOON((p_port + hp_intstat)) &
37105c04a7b8SAlexey Dobriyan 	    (BUS_FREE | XFER_CNT_0 | AUTO_INT))
37111da177e4SLinus Torvalds 		return;
37121da177e4SLinus Torvalds 
37131da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
37141da177e4SLinus Torvalds 
3715db038cf8SAlexey Dobriyan 	curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
37161da177e4SLinus Torvalds 
37171da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
37181da177e4SLinus Torvalds 
37191da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, curr_phz);
37201da177e4SLinus Torvalds 
37211da177e4SLinus Torvalds 	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
37225c04a7b8SAlexey Dobriyan 	       (curr_phz ==
37235c04a7b8SAlexey Dobriyan 		(RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
37241da177e4SLinus Torvalds 	{
37255c04a7b8SAlexey Dobriyan 		if (curr_phz & (unsigned char)SCSI_IOBIT) {
37265c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_portctrl_0,
37275c04a7b8SAlexey Dobriyan 				   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
37281da177e4SLinus Torvalds 
37295c04a7b8SAlexey Dobriyan 			if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
37301da177e4SLinus Torvalds 				RD_HARPOON(p_port + hp_fifodata_0);
37311da177e4SLinus Torvalds 			}
37325c04a7b8SAlexey Dobriyan 		} else {
37335c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_portctrl_0,
37345c04a7b8SAlexey Dobriyan 				   (SCSI_PORT | HOST_PORT | HOST_WRT));
37355c04a7b8SAlexey Dobriyan 			if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
37361da177e4SLinus Torvalds 				WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
37371da177e4SLinus Torvalds 			}
37381da177e4SLinus Torvalds 		}
37391da177e4SLinus Torvalds 	}			/* End of While loop for padding data I/O phase */
37401da177e4SLinus Torvalds 
37415c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
37421da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
37431da177e4SLinus Torvalds 			break;
37441da177e4SLinus Torvalds 	}
37451da177e4SLinus Torvalds 
37465c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_portctrl_0,
37475c04a7b8SAlexey Dobriyan 		   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
37485c04a7b8SAlexey Dobriyan 	while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
37491da177e4SLinus Torvalds 		RD_HARPOON(p_port + hp_fifodata_0);
37501da177e4SLinus Torvalds 	}
37511da177e4SLinus Torvalds 
37525c04a7b8SAlexey Dobriyan 	if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
37535c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_autostart_0,
37545c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
37555c04a7b8SAlexey Dobriyan 		while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
37561da177e4SLinus Torvalds 		}
37571da177e4SLinus Torvalds 
37585c04a7b8SAlexey Dobriyan 		if (RDW_HARPOON((p_port + hp_intstat)) &
37595c04a7b8SAlexey Dobriyan 		    (ICMD_COMP | ITAR_DISC))
37605c04a7b8SAlexey Dobriyan 			while (!
37615c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((p_port + hp_intstat)) &
37625c04a7b8SAlexey Dobriyan 				(BUS_FREE | RSEL))) ;
37635c04a7b8SAlexey Dobriyan 	}
37645c04a7b8SAlexey Dobriyan }
37651da177e4SLinus Torvalds 
37661da177e4SLinus Torvalds /*---------------------------------------------------------------------
37671da177e4SLinus Torvalds  *
376847b5d69cSJames Bottomley   * Function: FPT_schkdd
37691da177e4SLinus Torvalds  *
37701da177e4SLinus Torvalds  * Description: Make sure data has been flushed from both FIFOs and abort
37711da177e4SLinus Torvalds  *              the operations if necessary.
37721da177e4SLinus Torvalds  *
37731da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
37741da177e4SLinus Torvalds 
FPT_schkdd(u32 port,unsigned char p_card)3775391e2f25SKhalid Aziz static void FPT_schkdd(u32 port, unsigned char p_card)
37761da177e4SLinus Torvalds {
3777c823feebSAlexey Dobriyan 	unsigned short TimeOutLoop;
3778db038cf8SAlexey Dobriyan 	unsigned char sPhase;
37791da177e4SLinus Torvalds 
378069eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
37811da177e4SLinus Torvalds 
378247b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
37831da177e4SLinus Torvalds 
37841da177e4SLinus Torvalds 	if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
37851da177e4SLinus Torvalds 	    (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
37861da177e4SLinus Torvalds 		return;
37871da177e4SLinus Torvalds 	}
37881da177e4SLinus Torvalds 
37895c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
37901da177e4SLinus Torvalds 
37911da177e4SLinus Torvalds 		currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
37921da177e4SLinus Torvalds 
37931da177e4SLinus Torvalds 		currSCCB->Sccb_XferCnt = 1;
37941da177e4SLinus Torvalds 
37951da177e4SLinus Torvalds 		currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3796c823feebSAlexey Dobriyan 		WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
37971da177e4SLinus Torvalds 		WR_HARPOON(port + hp_xferstat, 0x00);
37981da177e4SLinus Torvalds 	}
37991da177e4SLinus Torvalds 
38005c04a7b8SAlexey Dobriyan 	else {
38011da177e4SLinus Torvalds 
38021da177e4SLinus Torvalds 		currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
38031da177e4SLinus Torvalds 
38041da177e4SLinus Torvalds 		currSCCB->Sccb_XferCnt = 0;
38051da177e4SLinus Torvalds 	}
38061da177e4SLinus Torvalds 
38071da177e4SLinus Torvalds 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
38081da177e4SLinus Torvalds 	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
38091da177e4SLinus Torvalds 
38101da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PARITY_ERR;
38111da177e4SLinus Torvalds 		WRW_HARPOON((port + hp_intstat), PARITY);
38121da177e4SLinus Torvalds 	}
38131da177e4SLinus Torvalds 
381447b5d69cSJames Bottomley  	FPT_hostDataXferAbort(port, p_card, currSCCB);
38151da177e4SLinus Torvalds 
38165c04a7b8SAlexey Dobriyan 	while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
38175c04a7b8SAlexey Dobriyan 	}
38181da177e4SLinus Torvalds 
38191da177e4SLinus Torvalds 	TimeOutLoop = 0;
38201da177e4SLinus Torvalds 
38215c04a7b8SAlexey Dobriyan 	while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
38221da177e4SLinus Torvalds 		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
38231da177e4SLinus Torvalds 			return;
38241da177e4SLinus Torvalds 		}
3825db038cf8SAlexey Dobriyan 		if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
38261da177e4SLinus Torvalds 			break;
38271da177e4SLinus Torvalds 		}
38281da177e4SLinus Torvalds 		if (RDW_HARPOON((port + hp_intstat)) & RESET) {
38291da177e4SLinus Torvalds 			return;
38301da177e4SLinus Torvalds 		}
38315c04a7b8SAlexey Dobriyan 		if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
38325c04a7b8SAlexey Dobriyan 		    || (TimeOutLoop++ > 0x3000))
38331da177e4SLinus Torvalds 			break;
38341da177e4SLinus Torvalds 	}
38351da177e4SLinus Torvalds 
38361da177e4SLinus Torvalds 	sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
38371da177e4SLinus Torvalds 	if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3838db038cf8SAlexey Dobriyan 	    (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
38391da177e4SLinus Torvalds 	    (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
38405c04a7b8SAlexey Dobriyan 	    (sPhase == (SCSI_BSY | S_DATAI_PH))) {
38411da177e4SLinus Torvalds 
38421da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
38431da177e4SLinus Torvalds 
38445c04a7b8SAlexey Dobriyan 		if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
38451da177e4SLinus Torvalds 			if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
384647b5d69cSJames Bottomley  				FPT_phaseDataIn(port, p_card);
38471da177e4SLinus Torvalds 			}
38481da177e4SLinus Torvalds 
38491da177e4SLinus Torvalds 			else {
385047b5d69cSJames Bottomley  				FPT_phaseDataOut(port, p_card);
38511da177e4SLinus Torvalds 			}
38525c04a7b8SAlexey Dobriyan 		} else {
385347b5d69cSJames Bottomley  			FPT_sxfrp(port, p_card);
38541da177e4SLinus Torvalds 			if (!(RDW_HARPOON((port + hp_intstat)) &
38555c04a7b8SAlexey Dobriyan 			      (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
38561da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), AUTO_INT);
385747b5d69cSJames Bottomley  				FPT_phaseDecode(port, p_card);
38581da177e4SLinus Torvalds 			}
38591da177e4SLinus Torvalds 		}
38601da177e4SLinus Torvalds 
38611da177e4SLinus Torvalds 	}
38621da177e4SLinus Torvalds 
38631da177e4SLinus Torvalds 	else {
38641da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, 0x00);
38651da177e4SLinus Torvalds 	}
38661da177e4SLinus Torvalds }
38671da177e4SLinus Torvalds 
38681da177e4SLinus Torvalds /*---------------------------------------------------------------------
38691da177e4SLinus Torvalds  *
387047b5d69cSJames Bottomley   * Function: FPT_sinits
38711da177e4SLinus Torvalds  *
38721da177e4SLinus Torvalds  * Description: Setup SCCB manager fields in this SCCB.
38731da177e4SLinus Torvalds  *
38741da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
38751da177e4SLinus Torvalds 
FPT_sinits(struct sccb * p_sccb,unsigned char p_card)387669eb2ea4SAlexey Dobriyan static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
38771da177e4SLinus Torvalds {
3878f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
38791da177e4SLinus Torvalds 
38805d7ebb9cSDan Carpenter 	if ((p_sccb->TargID >= MAX_SCSI_TAR) || (p_sccb->Lun >= MAX_LUN)) {
38811da177e4SLinus Torvalds 		return;
38821da177e4SLinus Torvalds 	}
388347b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
38841da177e4SLinus Torvalds 
38851da177e4SLinus Torvalds 	p_sccb->Sccb_XferState = 0x00;
38861da177e4SLinus Torvalds 	p_sccb->Sccb_XferCnt = p_sccb->DataLength;
38871da177e4SLinus Torvalds 
38881da177e4SLinus Torvalds 	if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
38891da177e4SLinus Torvalds 	    (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
38901da177e4SLinus Torvalds 
38911da177e4SLinus Torvalds 		p_sccb->Sccb_SGoffset = 0;
38921da177e4SLinus Torvalds 		p_sccb->Sccb_XferState = F_SG_XFER;
38931da177e4SLinus Torvalds 		p_sccb->Sccb_XferCnt = 0x00;
38941da177e4SLinus Torvalds 	}
38951da177e4SLinus Torvalds 
38961da177e4SLinus Torvalds 	if (p_sccb->DataLength == 0x00)
38971da177e4SLinus Torvalds 
38981da177e4SLinus Torvalds 		p_sccb->Sccb_XferState |= F_ALL_XFERRED;
38991da177e4SLinus Torvalds 
39005c04a7b8SAlexey Dobriyan 	if (p_sccb->ControlByte & F_USE_CMD_Q) {
39011da177e4SLinus Torvalds 		if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
39021da177e4SLinus Torvalds 			p_sccb->ControlByte &= ~F_USE_CMD_Q;
39031da177e4SLinus Torvalds 
39041da177e4SLinus Torvalds 		else
39051da177e4SLinus Torvalds 			currTar_Info->TarStatus |= TAG_Q_TRYING;
39061da177e4SLinus Torvalds 	}
39071da177e4SLinus Torvalds 
39081da177e4SLinus Torvalds /*      For !single SCSI device in system  & device allow Disconnect
39091da177e4SLinus Torvalds 	or command is tag_q type then send Cmd with Disconnect Enable
39101da177e4SLinus Torvalds 	else send Cmd with Disconnect Disable */
39111da177e4SLinus Torvalds 
39121da177e4SLinus Torvalds /*
391347b5d69cSJames Bottomley     if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
39141da177e4SLinus Torvalds       (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
39151da177e4SLinus Torvalds       (currTar_Info->TarStatus & TAG_Q_TRYING)) {
39161da177e4SLinus Torvalds */
39171da177e4SLinus Torvalds 	if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
39181da177e4SLinus Torvalds 	    (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3919a87afe28SHannes Reinecke 		p_sccb->Sccb_idmsg = IDENTIFY(true, p_sccb->Lun);
3920a87afe28SHannes Reinecke 	} else {
3921a87afe28SHannes Reinecke 		p_sccb->Sccb_idmsg = IDENTIFY(false, p_sccb->Lun);
39221da177e4SLinus Torvalds 	}
39231da177e4SLinus Torvalds 
39241da177e4SLinus Torvalds 	p_sccb->HostStatus = 0x00;
39251da177e4SLinus Torvalds 	p_sccb->TargetStatus = 0x00;
39261da177e4SLinus Torvalds 	p_sccb->Sccb_tag = 0x00;
39271da177e4SLinus Torvalds 	p_sccb->Sccb_MGRFlags = 0x00;
39281da177e4SLinus Torvalds 	p_sccb->Sccb_sgseg = 0x00;
39291da177e4SLinus Torvalds 	p_sccb->Sccb_ATC = 0x00;
39301da177e4SLinus Torvalds 	p_sccb->Sccb_savedATC = 0x00;
39311da177e4SLinus Torvalds /*
39321da177e4SLinus Torvalds    p_sccb->SccbVirtDataPtr    = 0x00;
39331da177e4SLinus Torvalds    p_sccb->Sccb_forwardlink   = NULL;
39341da177e4SLinus Torvalds    p_sccb->Sccb_backlink      = NULL;
39351da177e4SLinus Torvalds  */
39361da177e4SLinus Torvalds 	p_sccb->Sccb_scsistat = BUS_FREE_ST;
39371da177e4SLinus Torvalds 	p_sccb->SccbStatus = SCCB_IN_PROCESS;
3938a87afe28SHannes Reinecke 	p_sccb->Sccb_scsimsg = NOP;
39391da177e4SLinus Torvalds 
39401da177e4SLinus Torvalds }
39411da177e4SLinus Torvalds 
39421da177e4SLinus Torvalds /*---------------------------------------------------------------------
39431da177e4SLinus Torvalds  *
39441da177e4SLinus Torvalds  * Function: Phase Decode
39451da177e4SLinus Torvalds  *
39461da177e4SLinus Torvalds  * Description: Determine the phase and call the appropriate function.
39471da177e4SLinus Torvalds  *
39481da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
39491da177e4SLinus Torvalds 
FPT_phaseDecode(u32 p_port,unsigned char p_card)3950391e2f25SKhalid Aziz static void FPT_phaseDecode(u32 p_port, unsigned char p_card)
39511da177e4SLinus Torvalds {
39521da177e4SLinus Torvalds 	unsigned char phase_ref;
3953391e2f25SKhalid Aziz 	void (*phase) (u32, unsigned char);
39541da177e4SLinus Torvalds 
39551da177e4SLinus Torvalds 	DISABLE_AUTO(p_port);
39561da177e4SLinus Torvalds 
39575c04a7b8SAlexey Dobriyan 	phase_ref =
39585c04a7b8SAlexey Dobriyan 	    (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
39591da177e4SLinus Torvalds 
396047b5d69cSJames Bottomley  	phase = FPT_s_PhaseTbl[phase_ref];
39611da177e4SLinus Torvalds 
39621da177e4SLinus Torvalds 	(*phase) (p_port, p_card);	/* Call the correct phase func */
39631da177e4SLinus Torvalds }
39641da177e4SLinus Torvalds 
39651da177e4SLinus Torvalds /*---------------------------------------------------------------------
39661da177e4SLinus Torvalds  *
39671da177e4SLinus Torvalds  * Function: Data Out Phase
39681da177e4SLinus Torvalds  *
39691da177e4SLinus Torvalds  * Description: Start up both the BusMaster and Xbow.
39701da177e4SLinus Torvalds  *
39711da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
39721da177e4SLinus Torvalds 
FPT_phaseDataOut(u32 port,unsigned char p_card)3973391e2f25SKhalid Aziz static void FPT_phaseDataOut(u32 port, unsigned char p_card)
39741da177e4SLinus Torvalds {
39751da177e4SLinus Torvalds 
397669eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
39771da177e4SLinus Torvalds 
397847b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
39795c04a7b8SAlexey Dobriyan 	if (currSCCB == NULL) {
39801da177e4SLinus Torvalds 		return;		/* Exit if No SCCB record */
39811da177e4SLinus Torvalds 	}
39821da177e4SLinus Torvalds 
39831da177e4SLinus Torvalds 	currSCCB->Sccb_scsistat = DATA_OUT_ST;
39841da177e4SLinus Torvalds 	currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
39851da177e4SLinus Torvalds 
39861da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
39871da177e4SLinus Torvalds 
39881da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
39891da177e4SLinus Torvalds 
39901da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
39911da177e4SLinus Torvalds 
399247b5d69cSJames Bottomley  	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
39931da177e4SLinus Torvalds 
39941da177e4SLinus Torvalds 	if (currSCCB->Sccb_XferCnt == 0) {
39951da177e4SLinus Torvalds 
39961da177e4SLinus Torvalds 		if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
39971da177e4SLinus Torvalds 		    (currSCCB->HostStatus == SCCB_COMPLETE))
39981da177e4SLinus Torvalds 			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
39991da177e4SLinus Torvalds 
400047b5d69cSJames Bottomley  		FPT_sxfrp(port, p_card);
40011da177e4SLinus Torvalds 		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
400247b5d69cSJames Bottomley  			FPT_phaseDecode(port, p_card);
40031da177e4SLinus Torvalds 	}
40041da177e4SLinus Torvalds }
40051da177e4SLinus Torvalds 
40061da177e4SLinus Torvalds /*---------------------------------------------------------------------
40071da177e4SLinus Torvalds  *
40081da177e4SLinus Torvalds  * Function: Data In Phase
40091da177e4SLinus Torvalds  *
40101da177e4SLinus Torvalds  * Description: Startup the BusMaster and the XBOW.
40111da177e4SLinus Torvalds  *
40121da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
40131da177e4SLinus Torvalds 
FPT_phaseDataIn(u32 port,unsigned char p_card)4014391e2f25SKhalid Aziz static void FPT_phaseDataIn(u32 port, unsigned char p_card)
40151da177e4SLinus Torvalds {
40161da177e4SLinus Torvalds 
401769eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
40181da177e4SLinus Torvalds 
401947b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
40201da177e4SLinus Torvalds 
40215c04a7b8SAlexey Dobriyan 	if (currSCCB == NULL) {
40221da177e4SLinus Torvalds 		return;		/* Exit if No SCCB record */
40231da177e4SLinus Torvalds 	}
40241da177e4SLinus Torvalds 
40251da177e4SLinus Torvalds 	currSCCB->Sccb_scsistat = DATA_IN_ST;
40261da177e4SLinus Torvalds 	currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
40271da177e4SLinus Torvalds 	currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
40281da177e4SLinus Torvalds 
40291da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
40301da177e4SLinus Torvalds 
40311da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
40321da177e4SLinus Torvalds 
40331da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
40341da177e4SLinus Torvalds 
403547b5d69cSJames Bottomley  	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
40361da177e4SLinus Torvalds 
40371da177e4SLinus Torvalds 	if (currSCCB->Sccb_XferCnt == 0) {
40381da177e4SLinus Torvalds 
40391da177e4SLinus Torvalds 		if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
40401da177e4SLinus Torvalds 		    (currSCCB->HostStatus == SCCB_COMPLETE))
40411da177e4SLinus Torvalds 			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
40421da177e4SLinus Torvalds 
404347b5d69cSJames Bottomley  		FPT_sxfrp(port, p_card);
40441da177e4SLinus Torvalds 		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
404547b5d69cSJames Bottomley  			FPT_phaseDecode(port, p_card);
40461da177e4SLinus Torvalds 
40471da177e4SLinus Torvalds 	}
40481da177e4SLinus Torvalds }
40491da177e4SLinus Torvalds 
40501da177e4SLinus Torvalds /*---------------------------------------------------------------------
40511da177e4SLinus Torvalds  *
40521da177e4SLinus Torvalds  * Function: Command Phase
40531da177e4SLinus Torvalds  *
40541da177e4SLinus Torvalds  * Description: Load the CDB into the automation and start it up.
40551da177e4SLinus Torvalds  *
40561da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
40571da177e4SLinus Torvalds 
FPT_phaseCommand(u32 p_port,unsigned char p_card)4058391e2f25SKhalid Aziz static void FPT_phaseCommand(u32 p_port, unsigned char p_card)
40591da177e4SLinus Torvalds {
406069eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
4061391e2f25SKhalid Aziz 	u32 cdb_reg;
4062db038cf8SAlexey Dobriyan 	unsigned char i;
40631da177e4SLinus Torvalds 
406447b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
40651da177e4SLinus Torvalds 
40661da177e4SLinus Torvalds 	if (currSCCB->OperationCode == RESET_COMMAND) {
40671da177e4SLinus Torvalds 
40681da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
40691da177e4SLinus Torvalds 		currSCCB->CdbLength = SIX_BYTE_CMD;
40701da177e4SLinus Torvalds 	}
40711da177e4SLinus Torvalds 
40721da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, 0x00);
40731da177e4SLinus Torvalds 
40741da177e4SLinus Torvalds 	ARAM_ACCESS(p_port);
40751da177e4SLinus Torvalds 
40761da177e4SLinus Torvalds 	cdb_reg = p_port + CMD_STRT;
40771da177e4SLinus Torvalds 
40781da177e4SLinus Torvalds 	for (i = 0; i < currSCCB->CdbLength; i++) {
40791da177e4SLinus Torvalds 
40801da177e4SLinus Torvalds 		if (currSCCB->OperationCode == RESET_COMMAND)
40811da177e4SLinus Torvalds 
40821da177e4SLinus Torvalds 			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
40831da177e4SLinus Torvalds 
40841da177e4SLinus Torvalds 		else
40855c04a7b8SAlexey Dobriyan 			WRW_HARPOON(cdb_reg,
40865c04a7b8SAlexey Dobriyan 				    (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
40871da177e4SLinus Torvalds 		cdb_reg += 2;
40881da177e4SLinus Torvalds 	}
40891da177e4SLinus Torvalds 
40901da177e4SLinus Torvalds 	if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
40911da177e4SLinus Torvalds 		WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
40921da177e4SLinus Torvalds 
40931da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
40941da177e4SLinus Torvalds 
40951da177e4SLinus Torvalds 	currSCCB->Sccb_scsistat = COMMAND_ST;
40961da177e4SLinus Torvalds 
40971da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
40981da177e4SLinus Torvalds 	SGRAM_ACCESS(p_port);
40991da177e4SLinus Torvalds }
41001da177e4SLinus Torvalds 
41011da177e4SLinus Torvalds /*---------------------------------------------------------------------
41021da177e4SLinus Torvalds  *
41031da177e4SLinus Torvalds  * Function: Status phase
41041da177e4SLinus Torvalds  *
41051da177e4SLinus Torvalds  * Description: Bring in the status and command complete message bytes
41061da177e4SLinus Torvalds  *
41071da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
41081da177e4SLinus Torvalds 
FPT_phaseStatus(u32 port,unsigned char p_card)4109391e2f25SKhalid Aziz static void FPT_phaseStatus(u32 port, unsigned char p_card)
41101da177e4SLinus Torvalds {
41111da177e4SLinus Torvalds 	/* Start-up the automation to finish off this command and let the
41121da177e4SLinus Torvalds 	   isr handle the interrupt for command complete when it comes in.
41131da177e4SLinus Torvalds 	   We could wait here for the interrupt to be generated?
41141da177e4SLinus Torvalds 	 */
41151da177e4SLinus Torvalds 
41161da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, 0x00);
41171da177e4SLinus Torvalds 
41181da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
41191da177e4SLinus Torvalds }
41201da177e4SLinus Torvalds 
41211da177e4SLinus Torvalds /*---------------------------------------------------------------------
41221da177e4SLinus Torvalds  *
41231da177e4SLinus Torvalds  * Function: Phase Message Out
41241da177e4SLinus Torvalds  *
41251da177e4SLinus Torvalds  * Description: Send out our message (if we have one) and handle whatever
41261da177e4SLinus Torvalds  *              else is involed.
41271da177e4SLinus Torvalds  *
41281da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
41291da177e4SLinus Torvalds 
FPT_phaseMsgOut(u32 port,unsigned char p_card)4130391e2f25SKhalid Aziz static void FPT_phaseMsgOut(u32 port, unsigned char p_card)
41311da177e4SLinus Torvalds {
4132db038cf8SAlexey Dobriyan 	unsigned char message, scsiID;
413369eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
4134f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
41351da177e4SLinus Torvalds 
413647b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
41371da177e4SLinus Torvalds 
41381da177e4SLinus Torvalds 	if (currSCCB != NULL) {
41391da177e4SLinus Torvalds 
41401da177e4SLinus Torvalds 		message = currSCCB->Sccb_scsimsg;
41411da177e4SLinus Torvalds 		scsiID = currSCCB->TargID;
41421da177e4SLinus Torvalds 
4143a87afe28SHannes Reinecke 		if (message == TARGET_RESET) {
41441da177e4SLinus Torvalds 
414547b5d69cSJames Bottomley  			currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
41461da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
414747b5d69cSJames Bottomley  			FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
41481da177e4SLinus Torvalds 
41495c04a7b8SAlexey Dobriyan 			if (FPT_sccbMgrTbl[p_card][scsiID].
41505c04a7b8SAlexey Dobriyan 			    TarEEValue & EE_SYNC_MASK) {
41511da177e4SLinus Torvalds 
41525c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
41535c04a7b8SAlexey Dobriyan 				    ~TAR_SYNC_MASK;
41541da177e4SLinus Torvalds 
41551da177e4SLinus Torvalds 			}
41561da177e4SLinus Torvalds 
41575c04a7b8SAlexey Dobriyan 			if (FPT_sccbMgrTbl[p_card][scsiID].
41585c04a7b8SAlexey Dobriyan 			    TarEEValue & EE_WIDE_SCSI) {
41591da177e4SLinus Torvalds 
41605c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
41615c04a7b8SAlexey Dobriyan 				    ~TAR_WIDE_MASK;
41621da177e4SLinus Torvalds 			}
41631da177e4SLinus Torvalds 
416447b5d69cSJames Bottomley  			FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
416547b5d69cSJames Bottomley  			FPT_SccbMgrTableInitTarget(p_card, scsiID);
41665c04a7b8SAlexey Dobriyan 		} else if (currSCCB->Sccb_scsistat == ABORT_ST) {
41671da177e4SLinus Torvalds 			currSCCB->HostStatus = SCCB_COMPLETE;
41685c04a7b8SAlexey Dobriyan 			if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
41695c04a7b8SAlexey Dobriyan 			    NULL) {
41705c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
41715c04a7b8SAlexey Dobriyan 							      Sccb_tag] = NULL;
417247b5d69cSJames Bottomley  				FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
41731da177e4SLinus Torvalds 			}
41741da177e4SLinus Torvalds 
41751da177e4SLinus Torvalds 		}
41761da177e4SLinus Torvalds 
41775c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
41781da177e4SLinus Torvalds 
4179a87afe28SHannes Reinecke 			if (message == NOP) {
41801da177e4SLinus Torvalds 				currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
41811da177e4SLinus Torvalds 
418247b5d69cSJames Bottomley  				FPT_ssel(port, p_card);
41831da177e4SLinus Torvalds 				return;
41841da177e4SLinus Torvalds 			}
41855c04a7b8SAlexey Dobriyan 		} else {
41861da177e4SLinus Torvalds 
4187a87afe28SHannes Reinecke 			if (message == ABORT_TASK_SET)
41881da177e4SLinus Torvalds 
418947b5d69cSJames Bottomley  				FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
41901da177e4SLinus Torvalds 		}
41911da177e4SLinus Torvalds 
41925c04a7b8SAlexey Dobriyan 	} else {
4193a87afe28SHannes Reinecke 		message = ABORT_TASK_SET;
41941da177e4SLinus Torvalds 	}
41951da177e4SLinus Torvalds 
41961da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
41971da177e4SLinus Torvalds 
41981da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
41991da177e4SLinus Torvalds 
42001da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsidata_0, message);
42011da177e4SLinus Torvalds 
42021da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
42031da177e4SLinus Torvalds 
42041da177e4SLinus Torvalds 	ACCEPT_MSG(port);
42051da177e4SLinus Torvalds 
42061da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, 0x00);
42071da177e4SLinus Torvalds 
4208a87afe28SHannes Reinecke 	if ((message == ABORT_TASK_SET) || (message == TARGET_RESET) ||
4209a87afe28SHannes Reinecke 	    (message == ABORT_TASK)) {
42101da177e4SLinus Torvalds 
42115c04a7b8SAlexey Dobriyan 		while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
42125c04a7b8SAlexey Dobriyan 		}
42131da177e4SLinus Torvalds 
42145c04a7b8SAlexey Dobriyan 		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
42151da177e4SLinus Torvalds 			WRW_HARPOON((port + hp_intstat), BUS_FREE);
42161da177e4SLinus Torvalds 
42175c04a7b8SAlexey Dobriyan 			if (currSCCB != NULL) {
42181da177e4SLinus Torvalds 
42195c04a7b8SAlexey Dobriyan 				if ((FPT_BL_Card[p_card].
42205c04a7b8SAlexey Dobriyan 				     globalFlags & F_CONLUN_IO)
42215c04a7b8SAlexey Dobriyan 				    &&
42225c04a7b8SAlexey Dobriyan 				    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
42235c04a7b8SAlexey Dobriyan 				      TarStatus & TAR_TAG_Q_MASK) !=
42245c04a7b8SAlexey Dobriyan 				     TAG_Q_TRYING))
42255c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
42265c04a7b8SAlexey Dobriyan 							       TargID].
42275c04a7b8SAlexey Dobriyan 					    TarLUNBusy[currSCCB->Lun] = 0;
42281da177e4SLinus Torvalds 				else
42295c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
42305c04a7b8SAlexey Dobriyan 							       TargID].
42315c04a7b8SAlexey Dobriyan 					    TarLUNBusy[0] = 0;
42321da177e4SLinus Torvalds 
42335c04a7b8SAlexey Dobriyan 				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
42345c04a7b8SAlexey Dobriyan 						     currSCCB, p_card);
42351da177e4SLinus Torvalds 			}
42361da177e4SLinus Torvalds 
42375c04a7b8SAlexey Dobriyan 			else {
42385c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].globalFlags |=
42395c04a7b8SAlexey Dobriyan 				    F_NEW_SCCB_CMD;
42401da177e4SLinus Torvalds 			}
42411da177e4SLinus Torvalds 		}
42421da177e4SLinus Torvalds 
42435c04a7b8SAlexey Dobriyan 		else {
42441da177e4SLinus Torvalds 
424547b5d69cSJames Bottomley  			FPT_sxfrp(port, p_card);
42461da177e4SLinus Torvalds 		}
42471da177e4SLinus Torvalds 	}
42481da177e4SLinus Torvalds 
42495c04a7b8SAlexey Dobriyan 	else {
42501da177e4SLinus Torvalds 
4251a87afe28SHannes Reinecke 		if (message == MSG_PARITY_ERROR) {
4252a87afe28SHannes Reinecke 			currSCCB->Sccb_scsimsg = NOP;
42535c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
42545c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
42555c04a7b8SAlexey Dobriyan 		} else {
425647b5d69cSJames Bottomley  			FPT_sxfrp(port, p_card);
42571da177e4SLinus Torvalds 		}
42581da177e4SLinus Torvalds 	}
42591da177e4SLinus Torvalds }
42601da177e4SLinus Torvalds 
42611da177e4SLinus Torvalds /*---------------------------------------------------------------------
42621da177e4SLinus Torvalds  *
42631da177e4SLinus Torvalds  * Function: Message In phase
42641da177e4SLinus Torvalds  *
42651da177e4SLinus Torvalds  * Description: Bring in the message and determine what to do with it.
42661da177e4SLinus Torvalds  *
42671da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
42681da177e4SLinus Torvalds 
FPT_phaseMsgIn(u32 port,unsigned char p_card)4269391e2f25SKhalid Aziz static void FPT_phaseMsgIn(u32 port, unsigned char p_card)
42701da177e4SLinus Torvalds {
4271db038cf8SAlexey Dobriyan 	unsigned char message;
427269eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
42731da177e4SLinus Torvalds 
427447b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
42751da177e4SLinus Torvalds 
42765c04a7b8SAlexey Dobriyan 	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
42771da177e4SLinus Torvalds 
427847b5d69cSJames Bottomley  		FPT_phaseChkFifo(port, p_card);
42791da177e4SLinus Torvalds 	}
42801da177e4SLinus Torvalds 
42811da177e4SLinus Torvalds 	message = RD_HARPOON(port + hp_scsidata_0);
4282a87afe28SHannes Reinecke 	if ((message == DISCONNECT) || (message == SAVE_POINTERS)) {
42831da177e4SLinus Torvalds 
42845c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
42855c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + END_DATA_START));
42861da177e4SLinus Torvalds 
42871da177e4SLinus Torvalds 	}
42881da177e4SLinus Torvalds 
42895c04a7b8SAlexey Dobriyan 	else {
42901da177e4SLinus Torvalds 
429147b5d69cSJames Bottomley  		message = FPT_sfm(port, currSCCB);
42925c04a7b8SAlexey Dobriyan 		if (message) {
42931da177e4SLinus Torvalds 
429447b5d69cSJames Bottomley  			FPT_sdecm(message, port, p_card);
42951da177e4SLinus Torvalds 
42965c04a7b8SAlexey Dobriyan 		} else {
4297a87afe28SHannes Reinecke 			if (currSCCB->Sccb_scsimsg != MSG_PARITY_ERROR)
42981da177e4SLinus Torvalds 				ACCEPT_MSG(port);
42995c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
43005c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
43011da177e4SLinus Torvalds 		}
43021da177e4SLinus Torvalds 	}
43031da177e4SLinus Torvalds 
43041da177e4SLinus Torvalds }
43051da177e4SLinus Torvalds 
43061da177e4SLinus Torvalds /*---------------------------------------------------------------------
43071da177e4SLinus Torvalds  *
43081da177e4SLinus Torvalds  * Function: Illegal phase
43091da177e4SLinus Torvalds  *
43101da177e4SLinus Torvalds  * Description: Target switched to some illegal phase, so all we can do
43111da177e4SLinus Torvalds  *              is report an error back to the host (if that is possible)
43121da177e4SLinus Torvalds  *              and send an ABORT message to the misbehaving target.
43131da177e4SLinus Torvalds  *
43141da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
43151da177e4SLinus Torvalds 
FPT_phaseIllegal(u32 port,unsigned char p_card)4316391e2f25SKhalid Aziz static void FPT_phaseIllegal(u32 port, unsigned char p_card)
43171da177e4SLinus Torvalds {
431869eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
43191da177e4SLinus Torvalds 
432047b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
43211da177e4SLinus Torvalds 
43221da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
43231da177e4SLinus Torvalds 	if (currSCCB != NULL) {
43241da177e4SLinus Torvalds 
43251da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
43261da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = ABORT_ST;
4327a87afe28SHannes Reinecke 		currSCCB->Sccb_scsimsg = ABORT_TASK_SET;
43281da177e4SLinus Torvalds 	}
43291da177e4SLinus Torvalds 
43301da177e4SLinus Torvalds 	ACCEPT_MSG_ATN(port);
43311da177e4SLinus Torvalds }
43321da177e4SLinus Torvalds 
43331da177e4SLinus Torvalds /*---------------------------------------------------------------------
43341da177e4SLinus Torvalds  *
43351da177e4SLinus Torvalds  * Function: Phase Check FIFO
43361da177e4SLinus Torvalds  *
43371da177e4SLinus Torvalds  * Description: Make sure data has been flushed from both FIFOs and abort
43381da177e4SLinus Torvalds  *              the operations if necessary.
43391da177e4SLinus Torvalds  *
43401da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
43411da177e4SLinus Torvalds 
FPT_phaseChkFifo(u32 port,unsigned char p_card)4342391e2f25SKhalid Aziz static void FPT_phaseChkFifo(u32 port, unsigned char p_card)
43431da177e4SLinus Torvalds {
4344391e2f25SKhalid Aziz 	u32 xfercnt;
434569eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
43461da177e4SLinus Torvalds 
434747b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
43481da177e4SLinus Torvalds 
43495c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
43501da177e4SLinus Torvalds 
43511da177e4SLinus Torvalds 		while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
43525c04a7b8SAlexey Dobriyan 		       (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
43535c04a7b8SAlexey Dobriyan 		}
43541da177e4SLinus Torvalds 
43555c04a7b8SAlexey Dobriyan 		if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
43561da177e4SLinus Torvalds 			currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
43571da177e4SLinus Torvalds 
43581da177e4SLinus Torvalds 			currSCCB->Sccb_XferCnt = 0;
43591da177e4SLinus Torvalds 
43601da177e4SLinus Torvalds 			if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
43615c04a7b8SAlexey Dobriyan 			    (currSCCB->HostStatus == SCCB_COMPLETE)) {
43621da177e4SLinus Torvalds 				currSCCB->HostStatus = SCCB_PARITY_ERR;
43631da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PARITY);
43641da177e4SLinus Torvalds 			}
43651da177e4SLinus Torvalds 
436647b5d69cSJames Bottomley  			FPT_hostDataXferAbort(port, p_card, currSCCB);
43671da177e4SLinus Torvalds 
436847b5d69cSJames Bottomley  			FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
43691da177e4SLinus Torvalds 
43705c04a7b8SAlexey Dobriyan 			while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
43715c04a7b8SAlexey Dobriyan 			       && (RD_HARPOON(port + hp_ext_status) &
43725c04a7b8SAlexey Dobriyan 				   BM_CMD_BUSY)) {
43735c04a7b8SAlexey Dobriyan 			}
43741da177e4SLinus Torvalds 
43751da177e4SLinus Torvalds 		}
43765c04a7b8SAlexey Dobriyan 	}
43771da177e4SLinus Torvalds 
43785c04a7b8SAlexey Dobriyan 	/*End Data In specific code. */
43791da177e4SLinus Torvalds 	GET_XFER_CNT(port, xfercnt);
43801da177e4SLinus Torvalds 
43811da177e4SLinus Torvalds 	WR_HARPOON(port + hp_xfercnt_0, 0x00);
43821da177e4SLinus Torvalds 
43831da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, 0x00);
43841da177e4SLinus Torvalds 
43851da177e4SLinus Torvalds 	currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
43861da177e4SLinus Torvalds 
43871da177e4SLinus Torvalds 	currSCCB->Sccb_XferCnt = xfercnt;
43881da177e4SLinus Torvalds 
43891da177e4SLinus Torvalds 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
43901da177e4SLinus Torvalds 	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
43911da177e4SLinus Torvalds 
43921da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PARITY_ERR;
43931da177e4SLinus Torvalds 		WRW_HARPOON((port + hp_intstat), PARITY);
43941da177e4SLinus Torvalds 	}
43951da177e4SLinus Torvalds 
439647b5d69cSJames Bottomley  	FPT_hostDataXferAbort(port, p_card, currSCCB);
43971da177e4SLinus Torvalds 
43981da177e4SLinus Torvalds 	WR_HARPOON(port + hp_fifowrite, 0x00);
43991da177e4SLinus Torvalds 	WR_HARPOON(port + hp_fiforead, 0x00);
44001da177e4SLinus Torvalds 	WR_HARPOON(port + hp_xferstat, 0x00);
44011da177e4SLinus Torvalds 
44021da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
44031da177e4SLinus Torvalds }
44041da177e4SLinus Torvalds 
44051da177e4SLinus Torvalds /*---------------------------------------------------------------------
44061da177e4SLinus Torvalds  *
44071da177e4SLinus Torvalds  * Function: Phase Bus Free
44081da177e4SLinus Torvalds  *
44091da177e4SLinus Torvalds  * Description: We just went bus free so figure out if it was
44101da177e4SLinus Torvalds  *              because of command complete or from a disconnect.
44111da177e4SLinus Torvalds  *
44121da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_phaseBusFree(u32 port,unsigned char p_card)4413391e2f25SKhalid Aziz static void FPT_phaseBusFree(u32 port, unsigned char p_card)
44141da177e4SLinus Torvalds {
441569eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
44161da177e4SLinus Torvalds 
441747b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
44181da177e4SLinus Torvalds 
44195c04a7b8SAlexey Dobriyan 	if (currSCCB != NULL) {
44201da177e4SLinus Torvalds 
44211da177e4SLinus Torvalds 		DISABLE_AUTO(port);
44221da177e4SLinus Torvalds 
44235c04a7b8SAlexey Dobriyan 		if (currSCCB->OperationCode == RESET_COMMAND) {
44241da177e4SLinus Torvalds 
442547b5d69cSJames Bottomley  			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
44265c04a7b8SAlexey Dobriyan 			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44275c04a7b8SAlexey Dobriyan 			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
44285c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44295c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 0;
44301da177e4SLinus Torvalds 			else
44315c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44325c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 0;
44331da177e4SLinus Torvalds 
44345c04a7b8SAlexey Dobriyan 			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
44355c04a7b8SAlexey Dobriyan 					     p_card);
44361da177e4SLinus Torvalds 
443747b5d69cSJames Bottomley  			FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
44381da177e4SLinus Torvalds 
44391da177e4SLinus Torvalds 		}
44401da177e4SLinus Torvalds 
44415c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
444247b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4443db038cf8SAlexey Dobriyan 			    (unsigned char)SYNC_SUPPORTED;
44445c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
44455c04a7b8SAlexey Dobriyan 			    ~EE_SYNC_MASK;
44461da177e4SLinus Torvalds 		}
44471da177e4SLinus Torvalds 
44485c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
444947b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
445047b5d69cSJames Bottomley  			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44511da177e4SLinus Torvalds 			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
44521da177e4SLinus Torvalds 
44535c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
44545c04a7b8SAlexey Dobriyan 			    ~EE_WIDE_SCSI;
44551da177e4SLinus Torvalds 		}
44561da177e4SLinus Torvalds 
44575c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
44581da177e4SLinus Torvalds 			/* Make sure this is not a phony BUS_FREE.  If we were
44591da177e4SLinus Torvalds 			   reselected or if BUSY is NOT on then this is a
44601da177e4SLinus Torvalds 			   valid BUS FREE.  SRR Wednesday, 5/10/1995.     */
44611da177e4SLinus Torvalds 
44621da177e4SLinus Torvalds 			if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
44635c04a7b8SAlexey Dobriyan 			    (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
44645c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44655c04a7b8SAlexey Dobriyan 				    TarStatus &= ~TAR_TAG_Q_MASK;
44665c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44675c04a7b8SAlexey Dobriyan 				    TarStatus |= TAG_Q_REJECT;
44681da177e4SLinus Torvalds 			}
44691da177e4SLinus Torvalds 
44705c04a7b8SAlexey Dobriyan 			else {
44711da177e4SLinus Torvalds 				return;
44721da177e4SLinus Torvalds 			}
44731da177e4SLinus Torvalds 		}
44741da177e4SLinus Torvalds 
44755c04a7b8SAlexey Dobriyan 		else {
44761da177e4SLinus Torvalds 
44771da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
44781da177e4SLinus Torvalds 
44795c04a7b8SAlexey Dobriyan 			if (!currSCCB->HostStatus) {
44801da177e4SLinus Torvalds 				currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
44811da177e4SLinus Torvalds 			}
44821da177e4SLinus Torvalds 
448347b5d69cSJames Bottomley  			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
44845c04a7b8SAlexey Dobriyan 			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44855c04a7b8SAlexey Dobriyan 			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
44865c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44875c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 0;
44881da177e4SLinus Torvalds 			else
44895c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44905c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 0;
44911da177e4SLinus Torvalds 
44925c04a7b8SAlexey Dobriyan 			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
44935c04a7b8SAlexey Dobriyan 					     p_card);
44941da177e4SLinus Torvalds 			return;
44951da177e4SLinus Torvalds 		}
44961da177e4SLinus Torvalds 
449747b5d69cSJames Bottomley  		FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
44981da177e4SLinus Torvalds 
44991da177e4SLinus Torvalds 	}			/*end if !=null */
45001da177e4SLinus Torvalds }
45011da177e4SLinus Torvalds 
45021da177e4SLinus Torvalds /*---------------------------------------------------------------------
45031da177e4SLinus Torvalds  *
45041da177e4SLinus Torvalds  * Function: Auto Load Default Map
45051da177e4SLinus Torvalds  *
4506083d248bSzuoqilin  * Description: Load the Automation RAM with the default map values.
45071da177e4SLinus Torvalds  *
45081da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_autoLoadDefaultMap(u32 p_port)4509391e2f25SKhalid Aziz static void FPT_autoLoadDefaultMap(u32 p_port)
45101da177e4SLinus Torvalds {
4511391e2f25SKhalid Aziz 	u32 map_addr;
45121da177e4SLinus Torvalds 
45131da177e4SLinus Torvalds 	ARAM_ACCESS(p_port);
45141da177e4SLinus Torvalds 	map_addr = p_port + hp_aramBase;
45151da177e4SLinus Torvalds 
45161da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0));	/*ID MESSAGE */
45171da177e4SLinus Torvalds 	map_addr += 2;
45181da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20));	/*SIMPLE TAG QUEUEING MSG */
45191da177e4SLinus Torvalds 	map_addr += 2;
45201da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, RAT_OP);	/*RESET ATTENTION */
45211da177e4SLinus Torvalds 	map_addr += 2;
45221da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00));	/*TAG ID MSG */
45231da177e4SLinus Torvalds 	map_addr += 2;
45241da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 0 */
45251da177e4SLinus Torvalds 	map_addr += 2;
45261da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 1 */
45271da177e4SLinus Torvalds 	map_addr += 2;
45281da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 2 */
45291da177e4SLinus Torvalds 	map_addr += 2;
45301da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 3 */
45311da177e4SLinus Torvalds 	map_addr += 2;
45321da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 4 */
45331da177e4SLinus Torvalds 	map_addr += 2;
45341da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 5 */
45351da177e4SLinus Torvalds 	map_addr += 2;
45361da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 6 */
45371da177e4SLinus Torvalds 	map_addr += 2;
45381da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 7 */
45391da177e4SLinus Torvalds 	map_addr += 2;
45401da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 8 */
45411da177e4SLinus Torvalds 	map_addr += 2;
45421da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 9 */
45431da177e4SLinus Torvalds 	map_addr += 2;
45441da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 10 */
45451da177e4SLinus Torvalds 	map_addr += 2;
45461da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 11 */
45471da177e4SLinus Torvalds 	map_addr += 2;
45481da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT));	/*JUMP IF DATA OUT */
45491da177e4SLinus Torvalds 	map_addr += 2;
45501da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI));	/*JUMP IF NO DATA IN FIFO */
45511da177e4SLinus Torvalds 	map_addr += 2;		/*This means AYNC DATA IN */
45521da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT));	/*STOP AND INTERRUPT */
45531da177e4SLinus Torvalds 	map_addr += 2;
45541da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT));	/*JUMP IF NOT DATA IN PHZ */
45551da177e4SLinus Torvalds 	map_addr += 2;
45561da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK 4 DATA IN */
45571da177e4SLinus Torvalds 	map_addr += 2;
45581da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02));	/*SAVE DATA PTR MSG? */
45591da177e4SLinus Torvalds 	map_addr += 2;
45601da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC));	/*GO CHECK FOR DISCONNECT MSG */
45611da177e4SLinus Torvalds 	map_addr += 2;
45621da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1));	/*SAVE DATA PTRS MSG */
45631da177e4SLinus Torvalds 	map_addr += 2;
45641da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK DATA IN */
45651da177e4SLinus Torvalds 	map_addr += 2;
45661da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04));	/*DISCONNECT MSG? */
45671da177e4SLinus Torvalds 	map_addr += 2;
45681da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN));	/*UKNKNOWN MSG */
45691da177e4SLinus Torvalds 	map_addr += 2;
45701da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*XFER DISCONNECT MSG */
45711da177e4SLinus Torvalds 	map_addr += 2;
45721da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC));	/*STOP AND INTERRUPT */
45731da177e4SLinus Torvalds 	map_addr += 2;
45741da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN));	/*JUMP IF NOT STATUS PHZ. */
45751da177e4SLinus Torvalds 	map_addr += 2;
45761da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0));	/*GET STATUS BYTE */
45771da177e4SLinus Torvalds 	map_addr += 2;
45781da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC));	/*ERROR IF NOT MSG IN PHZ */
45791da177e4SLinus Torvalds 	map_addr += 2;
45801da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00));	/*CHECK FOR CMD COMPLETE MSG. */
45811da177e4SLinus Torvalds 	map_addr += 2;
45821da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC));	/*ERROR IF NOT CMD COMPLETE MSG. */
45831da177e4SLinus Torvalds 	map_addr += 2;
45841da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*GET CMD COMPLETE MSG */
45851da177e4SLinus Torvalds 	map_addr += 2;
45861da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP));	/*END OF COMMAND */
45871da177e4SLinus Torvalds 	map_addr += 2;
45881da177e4SLinus Torvalds 
45891da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN));	/*RECEIVED UNKNOWN MSG BYTE */
45901da177e4SLinus Torvalds 	map_addr += 2;
45911da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
45921da177e4SLinus Torvalds 	map_addr += 2;
45931da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE));	/*BIOS Tickled the Mgr */
45941da177e4SLinus Torvalds 	map_addr += 2;
45951da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL));	/*EXPECTED ID/TAG MESSAGES AND */
45961da177e4SLinus Torvalds 	map_addr += 2;		/* DIDN'T GET ONE */
45971da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG));	/* comp SCSI SEL ID & AR3 */
45981da177e4SLinus Torvalds 	map_addr += 2;
45991da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00));	/*SEL ID OK then Conti. */
46001da177e4SLinus Torvalds 	map_addr += 2;
46011da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
46021da177e4SLinus Torvalds 
46031da177e4SLinus Torvalds 	SGRAM_ACCESS(p_port);
46041da177e4SLinus Torvalds }
46051da177e4SLinus Torvalds 
46061da177e4SLinus Torvalds /*---------------------------------------------------------------------
46071da177e4SLinus Torvalds  *
46081da177e4SLinus Torvalds  * Function: Auto Command Complete
46091da177e4SLinus Torvalds  *
46101da177e4SLinus Torvalds  * Description: Post command back to host and find another command
46111da177e4SLinus Torvalds  *              to execute.
46121da177e4SLinus Torvalds  *
46131da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
46141da177e4SLinus Torvalds 
FPT_autoCmdCmplt(u32 p_port,unsigned char p_card)4615391e2f25SKhalid Aziz static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card)
46161da177e4SLinus Torvalds {
461769eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
4618db038cf8SAlexey Dobriyan 	unsigned char status_byte;
46191da177e4SLinus Torvalds 
462047b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
46211da177e4SLinus Torvalds 
46221da177e4SLinus Torvalds 	status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
46231da177e4SLinus Torvalds 
462447b5d69cSJames Bottomley  	FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
46251da177e4SLinus Torvalds 
4626a87afe28SHannes Reinecke 	if (status_byte != SAM_STAT_GOOD) {
46271da177e4SLinus Torvalds 
4628a87afe28SHannes Reinecke 		if (status_byte == SAM_STAT_TASK_SET_FULL) {
46291da177e4SLinus Torvalds 
463047b5d69cSJames Bottomley  			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
46315c04a7b8SAlexey Dobriyan 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46325c04a7b8SAlexey Dobriyan 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
46335c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46345c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 1;
463547b5d69cSJames Bottomley  				if (FPT_BL_Card[p_card].discQCount != 0)
463647b5d69cSJames Bottomley  					FPT_BL_Card[p_card].discQCount--;
46375c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].
46385c04a7b8SAlexey Dobriyan 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
46395c04a7b8SAlexey Dobriyan 					      [currSCCB->TargID].
46405c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[currSCCB->Lun]] =
46415c04a7b8SAlexey Dobriyan 				    NULL;
46425c04a7b8SAlexey Dobriyan 			} else {
46435c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46445c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 1;
46455c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_tag) {
464647b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
46475c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
46485c04a7b8SAlexey Dobriyan 						    discQCount--;
46495c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
46505c04a7b8SAlexey Dobriyan 								      Sccb_tag]
46515c04a7b8SAlexey Dobriyan 					    = NULL;
46525c04a7b8SAlexey Dobriyan 				} else {
465347b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
46545c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
46555c04a7b8SAlexey Dobriyan 						    discQCount--;
46565c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].
46575c04a7b8SAlexey Dobriyan 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
46585c04a7b8SAlexey Dobriyan 						      [currSCCB->TargID].
46595c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = NULL;
46601da177e4SLinus Torvalds 				}
46611da177e4SLinus Torvalds 			}
46621da177e4SLinus Torvalds 
46631da177e4SLinus Torvalds 			currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
46641da177e4SLinus Torvalds 
466547b5d69cSJames Bottomley  			FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
46661da177e4SLinus Torvalds 
46671da177e4SLinus Torvalds 			return;
46681da177e4SLinus Torvalds 		}
46691da177e4SLinus Torvalds 
46705c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
467147b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4672db038cf8SAlexey Dobriyan 			    (unsigned char)SYNC_SUPPORTED;
46731da177e4SLinus Torvalds 
46745c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
46755c04a7b8SAlexey Dobriyan 			    ~EE_SYNC_MASK;
467647b5d69cSJames Bottomley  			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
46771da177e4SLinus Torvalds 
467847b5d69cSJames Bottomley  			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
46795c04a7b8SAlexey Dobriyan 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46805c04a7b8SAlexey Dobriyan 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
46815c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46825c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 1;
468347b5d69cSJames Bottomley  				if (FPT_BL_Card[p_card].discQCount != 0)
468447b5d69cSJames Bottomley  					FPT_BL_Card[p_card].discQCount--;
46855c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].
46865c04a7b8SAlexey Dobriyan 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
46875c04a7b8SAlexey Dobriyan 					      [currSCCB->TargID].
46885c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[currSCCB->Lun]] =
46895c04a7b8SAlexey Dobriyan 				    NULL;
46905c04a7b8SAlexey Dobriyan 			} else {
46915c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46925c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 1;
46935c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_tag) {
469447b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
46955c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
46965c04a7b8SAlexey Dobriyan 						    discQCount--;
46975c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
46985c04a7b8SAlexey Dobriyan 								      Sccb_tag]
46995c04a7b8SAlexey Dobriyan 					    = NULL;
47005c04a7b8SAlexey Dobriyan 				} else {
470147b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47025c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
47035c04a7b8SAlexey Dobriyan 						    discQCount--;
47045c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].
47055c04a7b8SAlexey Dobriyan 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
47065c04a7b8SAlexey Dobriyan 						      [currSCCB->TargID].
47075c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = NULL;
47081da177e4SLinus Torvalds 				}
47091da177e4SLinus Torvalds 			}
47101da177e4SLinus Torvalds 			return;
47111da177e4SLinus Torvalds 
47121da177e4SLinus Torvalds 		}
47131da177e4SLinus Torvalds 
47145c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
47151da177e4SLinus Torvalds 
471647b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
471747b5d69cSJames Bottomley  			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47181da177e4SLinus Torvalds 			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
47191da177e4SLinus Torvalds 
47205c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
47215c04a7b8SAlexey Dobriyan 			    ~EE_WIDE_SCSI;
472247b5d69cSJames Bottomley  			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
47231da177e4SLinus Torvalds 
472447b5d69cSJames Bottomley  			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
47255c04a7b8SAlexey Dobriyan 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47265c04a7b8SAlexey Dobriyan 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
47275c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47285c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 1;
472947b5d69cSJames Bottomley  				if (FPT_BL_Card[p_card].discQCount != 0)
473047b5d69cSJames Bottomley  					FPT_BL_Card[p_card].discQCount--;
47315c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].
47325c04a7b8SAlexey Dobriyan 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
47335c04a7b8SAlexey Dobriyan 					      [currSCCB->TargID].
47345c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[currSCCB->Lun]] =
47355c04a7b8SAlexey Dobriyan 				    NULL;
47365c04a7b8SAlexey Dobriyan 			} else {
47375c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47385c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 1;
47395c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_tag) {
474047b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47415c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
47425c04a7b8SAlexey Dobriyan 						    discQCount--;
47435c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
47445c04a7b8SAlexey Dobriyan 								      Sccb_tag]
47455c04a7b8SAlexey Dobriyan 					    = NULL;
47465c04a7b8SAlexey Dobriyan 				} else {
474747b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47485c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
47495c04a7b8SAlexey Dobriyan 						    discQCount--;
47505c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].
47515c04a7b8SAlexey Dobriyan 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
47525c04a7b8SAlexey Dobriyan 						      [currSCCB->TargID].
47535c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = NULL;
47541da177e4SLinus Torvalds 				}
47551da177e4SLinus Torvalds 			}
47561da177e4SLinus Torvalds 			return;
47571da177e4SLinus Torvalds 
47581da177e4SLinus Torvalds 		}
47591da177e4SLinus Torvalds 
4760a87afe28SHannes Reinecke 		if (status_byte == SAM_STAT_CHECK_CONDITION) {
47615c04a7b8SAlexey Dobriyan 			if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
47625c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47635c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_SYNC_MASK) {
47645c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
47655c04a7b8SAlexey Dobriyan 							       TargID].
47665c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_SYNC_MASK;
47671da177e4SLinus Torvalds 				}
47685c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47695c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_WIDE_SCSI) {
47705c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
47715c04a7b8SAlexey Dobriyan 							       TargID].
47725c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_WIDE_MASK;
47731da177e4SLinus Torvalds 				}
47741da177e4SLinus Torvalds 			}
47751da177e4SLinus Torvalds 		}
47761da177e4SLinus Torvalds 
47771da177e4SLinus Torvalds 		if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
47781da177e4SLinus Torvalds 
47791da177e4SLinus Torvalds 			currSCCB->SccbStatus = SCCB_ERROR;
47801da177e4SLinus Torvalds 			currSCCB->TargetStatus = status_byte;
47811da177e4SLinus Torvalds 
4782a87afe28SHannes Reinecke 			if (status_byte == SAM_STAT_CHECK_CONDITION) {
47831da177e4SLinus Torvalds 
47845c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47855c04a7b8SAlexey Dobriyan 				    TarLUN_CA = 1;
47861da177e4SLinus Torvalds 
47875c04a7b8SAlexey Dobriyan 				if (currSCCB->RequestSenseLength !=
47885c04a7b8SAlexey Dobriyan 				    NO_AUTO_REQUEST_SENSE) {
47891da177e4SLinus Torvalds 
47901da177e4SLinus Torvalds 					if (currSCCB->RequestSenseLength == 0)
47915c04a7b8SAlexey Dobriyan 						currSCCB->RequestSenseLength =
47925c04a7b8SAlexey Dobriyan 						    14;
47931da177e4SLinus Torvalds 
479447b5d69cSJames Bottomley  					FPT_ssenss(&FPT_BL_Card[p_card]);
47955c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].globalFlags |=
47965c04a7b8SAlexey Dobriyan 					    F_NEW_SCCB_CMD;
47971da177e4SLinus Torvalds 
47985c04a7b8SAlexey Dobriyan 					if (((FPT_BL_Card[p_card].
47995c04a7b8SAlexey Dobriyan 					      globalFlags & F_CONLUN_IO)
48005c04a7b8SAlexey Dobriyan 					     &&
48015c04a7b8SAlexey Dobriyan 					     ((FPT_sccbMgrTbl[p_card]
48025c04a7b8SAlexey Dobriyan 					       [currSCCB->TargID].
48035c04a7b8SAlexey Dobriyan 					       TarStatus & TAR_TAG_Q_MASK) !=
48045c04a7b8SAlexey Dobriyan 					      TAG_Q_TRYING))) {
48055c04a7b8SAlexey Dobriyan 						FPT_sccbMgrTbl[p_card]
48065c04a7b8SAlexey Dobriyan 						    [currSCCB->TargID].
48075c04a7b8SAlexey Dobriyan 						    TarLUNBusy[currSCCB->Lun] =
48085c04a7b8SAlexey Dobriyan 						    1;
48095c04a7b8SAlexey Dobriyan 						if (FPT_BL_Card[p_card].
48105c04a7b8SAlexey Dobriyan 						    discQCount != 0)
48115c04a7b8SAlexey Dobriyan 							FPT_BL_Card[p_card].
48125c04a7b8SAlexey Dobriyan 							    discQCount--;
48135c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
48145c04a7b8SAlexey Dobriyan 						    discQ_Tbl[FPT_sccbMgrTbl
48155c04a7b8SAlexey Dobriyan 							      [p_card]
48165c04a7b8SAlexey Dobriyan 							      [currSCCB->
48175c04a7b8SAlexey Dobriyan 							       TargID].
48185c04a7b8SAlexey Dobriyan 							      LunDiscQ_Idx
48195c04a7b8SAlexey Dobriyan 							      [currSCCB->Lun]] =
48205c04a7b8SAlexey Dobriyan 						    NULL;
48215c04a7b8SAlexey Dobriyan 					} else {
48225c04a7b8SAlexey Dobriyan 						FPT_sccbMgrTbl[p_card]
48235c04a7b8SAlexey Dobriyan 						    [currSCCB->TargID].
48245c04a7b8SAlexey Dobriyan 						    TarLUNBusy[0] = 1;
48255c04a7b8SAlexey Dobriyan 						if (currSCCB->Sccb_tag) {
48265c04a7b8SAlexey Dobriyan 							if (FPT_BL_Card[p_card].
48275c04a7b8SAlexey Dobriyan 							    discQCount != 0)
48285c04a7b8SAlexey Dobriyan 								FPT_BL_Card
48295c04a7b8SAlexey Dobriyan 								    [p_card].
48305c04a7b8SAlexey Dobriyan 								    discQCount--;
48315c04a7b8SAlexey Dobriyan 							FPT_BL_Card[p_card].
48325c04a7b8SAlexey Dobriyan 							    discQ_Tbl[currSCCB->
48335c04a7b8SAlexey Dobriyan 								      Sccb_tag]
48345c04a7b8SAlexey Dobriyan 							    = NULL;
48355c04a7b8SAlexey Dobriyan 						} else {
48365c04a7b8SAlexey Dobriyan 							if (FPT_BL_Card[p_card].
48375c04a7b8SAlexey Dobriyan 							    discQCount != 0)
48385c04a7b8SAlexey Dobriyan 								FPT_BL_Card
48395c04a7b8SAlexey Dobriyan 								    [p_card].
48405c04a7b8SAlexey Dobriyan 								    discQCount--;
48415c04a7b8SAlexey Dobriyan 							FPT_BL_Card[p_card].
48425c04a7b8SAlexey Dobriyan 							    discQ_Tbl
48435c04a7b8SAlexey Dobriyan 							    [FPT_sccbMgrTbl
48445c04a7b8SAlexey Dobriyan 							     [p_card][currSCCB->
48455c04a7b8SAlexey Dobriyan 								      TargID].
48465c04a7b8SAlexey Dobriyan 							     LunDiscQ_Idx[0]] =
48475c04a7b8SAlexey Dobriyan 							    NULL;
48481da177e4SLinus Torvalds 						}
48491da177e4SLinus Torvalds 					}
48501da177e4SLinus Torvalds 					return;
48511da177e4SLinus Torvalds 				}
48521da177e4SLinus Torvalds 			}
485347b5d69cSJames Bottomley  		}
485447b5d69cSJames Bottomley  	}
485547b5d69cSJames Bottomley  
485647b5d69cSJames Bottomley  	if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
48575c04a7b8SAlexey Dobriyan 	    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
48585c04a7b8SAlexey Dobriyan 	      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
48595c04a7b8SAlexey Dobriyan 		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
48605c04a7b8SAlexey Dobriyan 								    Lun] = 0;
48611da177e4SLinus Torvalds 	else
486247b5d69cSJames Bottomley  		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
486347b5d69cSJames Bottomley  
486447b5d69cSJames Bottomley  	FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
48651da177e4SLinus Torvalds }
48661da177e4SLinus Torvalds 
48671da177e4SLinus Torvalds #define SHORT_WAIT   0x0000000F
48681da177e4SLinus Torvalds #define LONG_WAIT    0x0000FFFFL
48691da177e4SLinus Torvalds 
48701da177e4SLinus Torvalds /*---------------------------------------------------------------------
48711da177e4SLinus Torvalds  *
48721da177e4SLinus Torvalds  * Function: Data Transfer Processor
48731da177e4SLinus Torvalds  *
48741da177e4SLinus Torvalds  * Description: This routine performs two tasks.
48751da177e4SLinus Torvalds  *              (1) Start data transfer by calling HOST_DATA_XFER_START
48761da177e4SLinus Torvalds  *              function.  Once data transfer is started, (2) Depends
48771da177e4SLinus Torvalds  *              on the type of data transfer mode Scatter/Gather mode
48781da177e4SLinus Torvalds  *              or NON Scatter/Gather mode.  In NON Scatter/Gather mode,
48791da177e4SLinus Torvalds  *              this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
48801da177e4SLinus Torvalds  *              data transfer done.  In Scatter/Gather mode, this routine
48811da177e4SLinus Torvalds  *              checks bus master command complete and dual rank busy
48821da177e4SLinus Torvalds  *              bit to keep chaining SC transfer command.  Similarly,
48831da177e4SLinus Torvalds  *              in Scatter/Gather mode, it checks Sccb_MGRFlag
48841da177e4SLinus Torvalds  *              (F_HOST_XFER_ACT bit) for data transfer done.
48851da177e4SLinus Torvalds  *
48861da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
48871da177e4SLinus Torvalds 
FPT_dataXferProcessor(u32 port,struct sccb_card * pCurrCard)4888391e2f25SKhalid Aziz static void FPT_dataXferProcessor(u32 port, struct sccb_card *pCurrCard)
48891da177e4SLinus Torvalds {
489069eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
48911da177e4SLinus Torvalds 
48921da177e4SLinus Torvalds 	currSCCB = pCurrCard->currentSCCB;
48931da177e4SLinus Torvalds 
48945c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_XferState & F_SG_XFER) {
48951da177e4SLinus Torvalds 		if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
48961da177e4SLinus Torvalds 		{
4897db038cf8SAlexey Dobriyan 			currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
48981da177e4SLinus Torvalds 			currSCCB->Sccb_SGoffset = 0x00;
48991da177e4SLinus Torvalds 		}
49001da177e4SLinus Torvalds 		pCurrCard->globalFlags |= F_HOST_XFER_ACT;
49011da177e4SLinus Torvalds 
490247b5d69cSJames Bottomley  		FPT_busMstrSGDataXferStart(port, currSCCB);
49031da177e4SLinus Torvalds 	}
49041da177e4SLinus Torvalds 
49055c04a7b8SAlexey Dobriyan 	else {
49065c04a7b8SAlexey Dobriyan 		if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
49071da177e4SLinus Torvalds 			pCurrCard->globalFlags |= F_HOST_XFER_ACT;
49081da177e4SLinus Torvalds 
490947b5d69cSJames Bottomley  			FPT_busMstrDataXferStart(port, currSCCB);
49101da177e4SLinus Torvalds 		}
49111da177e4SLinus Torvalds 	}
49121da177e4SLinus Torvalds }
49131da177e4SLinus Torvalds 
49141da177e4SLinus Torvalds /*---------------------------------------------------------------------
49151da177e4SLinus Torvalds  *
49161da177e4SLinus Torvalds  * Function: BusMaster Scatter Gather Data Transfer Start
49171da177e4SLinus Torvalds  *
49181da177e4SLinus Torvalds  * Description:
49191da177e4SLinus Torvalds  *
49201da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_busMstrSGDataXferStart(u32 p_port,struct sccb * pcurrSCCB)4921391e2f25SKhalid Aziz static void FPT_busMstrSGDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
49221da177e4SLinus Torvalds {
4923391e2f25SKhalid Aziz 	u32 count, addr, tmpSGCnt;
4924ce793215SAlexey Dobriyan 	unsigned int sg_index;
4925db038cf8SAlexey Dobriyan 	unsigned char sg_count, i;
4926391e2f25SKhalid Aziz 	u32 reg_offset;
4927391e2f25SKhalid Aziz 	struct blogic_sg_seg *segp;
49281da177e4SLinus Torvalds 
4929391e2f25SKhalid Aziz 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)
4930391e2f25SKhalid Aziz 		count = ((u32)HOST_RD_CMD) << 24;
4931391e2f25SKhalid Aziz 	else
4932391e2f25SKhalid Aziz 		count = ((u32)HOST_WRT_CMD) << 24;
49331da177e4SLinus Torvalds 
49341da177e4SLinus Torvalds 	sg_count = 0;
49351da177e4SLinus Torvalds 	tmpSGCnt = 0;
49361da177e4SLinus Torvalds 	sg_index = pcurrSCCB->Sccb_sgseg;
49371da177e4SLinus Torvalds 	reg_offset = hp_aramBase;
49381da177e4SLinus Torvalds 
49395c04a7b8SAlexey Dobriyan 	i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
49405c04a7b8SAlexey Dobriyan 			    ~(SGRAM_ARAM | SCATTER_EN));
49411da177e4SLinus Torvalds 
49421da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl, i);
49431da177e4SLinus Torvalds 
4944db038cf8SAlexey Dobriyan 	while ((sg_count < (unsigned char)SG_BUF_CNT) &&
4945391e2f25SKhalid Aziz 			((sg_index * (unsigned int)SG_ELEMENT_SIZE) <
49465c04a7b8SAlexey Dobriyan 			pcurrSCCB->DataLength)) {
49471da177e4SLinus Torvalds 
4948391e2f25SKhalid Aziz 		segp = (struct blogic_sg_seg *)(pcurrSCCB->DataPointer) +
4949391e2f25SKhalid Aziz 				sg_index;
4950391e2f25SKhalid Aziz 		tmpSGCnt += segp->segbytes;
4951391e2f25SKhalid Aziz 		count |= segp->segbytes;
4952391e2f25SKhalid Aziz 		addr = segp->segdata;
49531da177e4SLinus Torvalds 
49541da177e4SLinus Torvalds 		if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
49555c04a7b8SAlexey Dobriyan 			addr +=
49565c04a7b8SAlexey Dobriyan 			    ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
49575c04a7b8SAlexey Dobriyan 			count =
49585c04a7b8SAlexey Dobriyan 			    (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
49591da177e4SLinus Torvalds 			tmpSGCnt = count & 0x00FFFFFFL;
49601da177e4SLinus Torvalds 		}
49611da177e4SLinus Torvalds 
49621da177e4SLinus Torvalds 		WR_HARP32(p_port, reg_offset, addr);
49631da177e4SLinus Torvalds 		reg_offset += 4;
49641da177e4SLinus Torvalds 
49651da177e4SLinus Torvalds 		WR_HARP32(p_port, reg_offset, count);
49661da177e4SLinus Torvalds 		reg_offset += 4;
49671da177e4SLinus Torvalds 
49681da177e4SLinus Torvalds 		count &= 0xFF000000L;
49691da177e4SLinus Torvalds 		sg_index++;
49701da177e4SLinus Torvalds 		sg_count++;
49711da177e4SLinus Torvalds 
49721da177e4SLinus Torvalds 	}			/*End While */
49731da177e4SLinus Torvalds 
49741da177e4SLinus Torvalds 	pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
49751da177e4SLinus Torvalds 
49761da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
49771da177e4SLinus Torvalds 
49781da177e4SLinus Torvalds 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
49791da177e4SLinus Torvalds 
49801da177e4SLinus Torvalds 		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
49811da177e4SLinus Torvalds 
49825c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
49835c04a7b8SAlexey Dobriyan 			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
49841da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
49851da177e4SLinus Torvalds 	}
49861da177e4SLinus Torvalds 
49871da177e4SLinus Torvalds 	else {
49881da177e4SLinus Torvalds 
49891da177e4SLinus Torvalds 		if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
49905c04a7b8SAlexey Dobriyan 		    (tmpSGCnt & 0x000000001)) {
49911da177e4SLinus Torvalds 
49921da177e4SLinus Torvalds 			pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
49931da177e4SLinus Torvalds 			tmpSGCnt--;
49941da177e4SLinus Torvalds 		}
49951da177e4SLinus Torvalds 
49961da177e4SLinus Torvalds 		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
49971da177e4SLinus Torvalds 
49985c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
49995c04a7b8SAlexey Dobriyan 			   (SCSI_PORT | DMA_PORT | DMA_RD));
50001da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
50011da177e4SLinus Torvalds 	}
50021da177e4SLinus Torvalds 
5003db038cf8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
50041da177e4SLinus Torvalds 
50051da177e4SLinus Torvalds }
50061da177e4SLinus Torvalds 
50071da177e4SLinus Torvalds /*---------------------------------------------------------------------
50081da177e4SLinus Torvalds  *
50091da177e4SLinus Torvalds  * Function: BusMaster Data Transfer Start
50101da177e4SLinus Torvalds  *
50111da177e4SLinus Torvalds  * Description:
50121da177e4SLinus Torvalds  *
50131da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_busMstrDataXferStart(u32 p_port,struct sccb * pcurrSCCB)5014391e2f25SKhalid Aziz static void FPT_busMstrDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
50151da177e4SLinus Torvalds {
5016391e2f25SKhalid Aziz 	u32 addr, count;
50171da177e4SLinus Torvalds 
50181da177e4SLinus Torvalds 	if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
50191da177e4SLinus Torvalds 
50201da177e4SLinus Torvalds 		count = pcurrSCCB->Sccb_XferCnt;
50211da177e4SLinus Torvalds 
5022391e2f25SKhalid Aziz 		addr = (u32)(unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
50231da177e4SLinus Torvalds 	}
50241da177e4SLinus Torvalds 
50251da177e4SLinus Torvalds 	else {
50261da177e4SLinus Torvalds 		addr = pcurrSCCB->SensePointer;
50271da177e4SLinus Torvalds 		count = pcurrSCCB->RequestSenseLength;
50281da177e4SLinus Torvalds 
50291da177e4SLinus Torvalds 	}
50301da177e4SLinus Torvalds 
50311da177e4SLinus Torvalds 	HP_SETUP_ADDR_CNT(p_port, addr, count);
50321da177e4SLinus Torvalds 
50331da177e4SLinus Torvalds 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
50341da177e4SLinus Torvalds 
50355c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
50365c04a7b8SAlexey Dobriyan 			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
50371da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
50381da177e4SLinus Torvalds 
50391da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_xfer_cmd,
50401da177e4SLinus Torvalds 			   (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
50411da177e4SLinus Torvalds 	}
50421da177e4SLinus Torvalds 
50431da177e4SLinus Torvalds 	else {
50441da177e4SLinus Torvalds 
50455c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
50465c04a7b8SAlexey Dobriyan 			   (SCSI_PORT | DMA_PORT | DMA_RD));
50471da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
50481da177e4SLinus Torvalds 
50491da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_xfer_cmd,
50501da177e4SLinus Torvalds 			   (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
50511da177e4SLinus Torvalds 
50521da177e4SLinus Torvalds 	}
50531da177e4SLinus Torvalds }
50541da177e4SLinus Torvalds 
50551da177e4SLinus Torvalds /*---------------------------------------------------------------------
50561da177e4SLinus Torvalds  *
50571da177e4SLinus Torvalds  * Function: BusMaster Timeout Handler
50581da177e4SLinus Torvalds  *
50591da177e4SLinus Torvalds  * Description: This function is called after a bus master command busy time
50601da177e4SLinus Torvalds  *               out is detected.  This routines issue halt state machine
50611da177e4SLinus Torvalds  *               with a software time out for command busy.  If command busy
50621da177e4SLinus Torvalds  *               is still asserted at the end of the time out, it issues
50631da177e4SLinus Torvalds  *               hard abort with another software time out.  It hard abort
50641da177e4SLinus Torvalds  *               command busy is also time out, it'll just give up.
50651da177e4SLinus Torvalds  *
50661da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_busMstrTimeOut(u32 p_port)5067391e2f25SKhalid Aziz static unsigned char FPT_busMstrTimeOut(u32 p_port)
50681da177e4SLinus Torvalds {
5069d63a4cccSAlexey Dobriyan 	unsigned long timeout;
50701da177e4SLinus Torvalds 
50711da177e4SLinus Torvalds 	timeout = LONG_WAIT;
50721da177e4SLinus Torvalds 
50731da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
50741da177e4SLinus Torvalds 
50755c04a7b8SAlexey Dobriyan 	while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
50765c04a7b8SAlexey Dobriyan 	       && timeout--) {
50775c04a7b8SAlexey Dobriyan 	}
50781da177e4SLinus Torvalds 
50791da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
50801da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
50811da177e4SLinus Torvalds 
50821da177e4SLinus Torvalds 		timeout = LONG_WAIT;
50835c04a7b8SAlexey Dobriyan 		while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
50845c04a7b8SAlexey Dobriyan 		       && timeout--) {
50855c04a7b8SAlexey Dobriyan 		}
50861da177e4SLinus Torvalds 	}
50871da177e4SLinus Torvalds 
50881da177e4SLinus Torvalds 	RD_HARPOON(p_port + hp_int_status);	/*Clear command complete */
50891da177e4SLinus Torvalds 
50901da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
50915c1b85e2SAlexey Dobriyan 		return 1;
50921da177e4SLinus Torvalds 	}
50931da177e4SLinus Torvalds 
50941da177e4SLinus Torvalds 	else {
50955c1b85e2SAlexey Dobriyan 		return 0;
50961da177e4SLinus Torvalds 	}
50971da177e4SLinus Torvalds }
50981da177e4SLinus Torvalds 
50991da177e4SLinus Torvalds /*---------------------------------------------------------------------
51001da177e4SLinus Torvalds  *
51011da177e4SLinus Torvalds  * Function: Host Data Transfer Abort
51021da177e4SLinus Torvalds  *
51031da177e4SLinus Torvalds  * Description: Abort any in progress transfer.
51041da177e4SLinus Torvalds  *
51051da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_hostDataXferAbort(u32 port,unsigned char p_card,struct sccb * pCurrSCCB)5106391e2f25SKhalid Aziz static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
51075c04a7b8SAlexey Dobriyan 				  struct sccb *pCurrSCCB)
51081da177e4SLinus Torvalds {
51091da177e4SLinus Torvalds 
5110d63a4cccSAlexey Dobriyan 	unsigned long timeout;
5111d63a4cccSAlexey Dobriyan 	unsigned long remain_cnt;
5112391e2f25SKhalid Aziz 	u32 sg_ptr;
5113391e2f25SKhalid Aziz 	struct blogic_sg_seg *segp;
51141da177e4SLinus Torvalds 
511547b5d69cSJames Bottomley  	FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
51161da177e4SLinus Torvalds 
51171da177e4SLinus Torvalds 	if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
51181da177e4SLinus Torvalds 
51191da177e4SLinus Torvalds 		if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
51201da177e4SLinus Torvalds 
51215c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_bm_ctrl,
51225c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_bm_ctrl) |
51235c04a7b8SAlexey Dobriyan 				    FLUSH_XFER_CNTR));
51241da177e4SLinus Torvalds 			timeout = LONG_WAIT;
51251da177e4SLinus Torvalds 
51265c04a7b8SAlexey Dobriyan 			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
51275c04a7b8SAlexey Dobriyan 			       && timeout--) {
51285c04a7b8SAlexey Dobriyan 			}
51291da177e4SLinus Torvalds 
51305c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_bm_ctrl,
51315c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_bm_ctrl) &
51325c04a7b8SAlexey Dobriyan 				    ~FLUSH_XFER_CNTR));
51331da177e4SLinus Torvalds 
51341da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
51351da177e4SLinus Torvalds 
513647b5d69cSJames Bottomley  				if (FPT_busMstrTimeOut(port)) {
51371da177e4SLinus Torvalds 
51381da177e4SLinus Torvalds 					if (pCurrSCCB->HostStatus == 0x00)
51391da177e4SLinus Torvalds 
51405c04a7b8SAlexey Dobriyan 						pCurrSCCB->HostStatus =
51415c04a7b8SAlexey Dobriyan 						    SCCB_BM_ERR;
51421da177e4SLinus Torvalds 
51431da177e4SLinus Torvalds 				}
51441da177e4SLinus Torvalds 
51455c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_int_status) &
51465c04a7b8SAlexey Dobriyan 				    INT_EXT_STATUS)
51471da177e4SLinus Torvalds 
51485c04a7b8SAlexey Dobriyan 					if (RD_HARPOON(port + hp_ext_status) &
51495c04a7b8SAlexey Dobriyan 					    BAD_EXT_STATUS)
51501da177e4SLinus Torvalds 
51515c04a7b8SAlexey Dobriyan 						if (pCurrSCCB->HostStatus ==
51525c04a7b8SAlexey Dobriyan 						    0x00)
51531da177e4SLinus Torvalds 						{
51545c04a7b8SAlexey Dobriyan 							pCurrSCCB->HostStatus =
51555c04a7b8SAlexey Dobriyan 							    SCCB_BM_ERR;
51561da177e4SLinus Torvalds 						}
51571da177e4SLinus Torvalds 			}
51581da177e4SLinus Torvalds 		}
51591da177e4SLinus Torvalds 	}
51601da177e4SLinus Torvalds 
51611da177e4SLinus Torvalds 	else if (pCurrSCCB->Sccb_XferCnt) {
51621da177e4SLinus Torvalds 
51631da177e4SLinus Torvalds 		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
51641da177e4SLinus Torvalds 
51655c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_page_ctrl,
51665c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_page_ctrl) &
51671da177e4SLinus Torvalds 				    ~SCATTER_EN));
51681da177e4SLinus Torvalds 
51691da177e4SLinus Torvalds 			WR_HARPOON(port + hp_sg_addr, 0x00);
51701da177e4SLinus Torvalds 
51711da177e4SLinus Torvalds 			sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
51721da177e4SLinus Torvalds 
51735c04a7b8SAlexey Dobriyan 			if (sg_ptr >
51745c04a7b8SAlexey Dobriyan 			    (unsigned int)(pCurrSCCB->DataLength /
51755c04a7b8SAlexey Dobriyan 					   SG_ELEMENT_SIZE)) {
51761da177e4SLinus Torvalds 
5177391e2f25SKhalid Aziz 				sg_ptr = (u32)(pCurrSCCB->DataLength /
51785c04a7b8SAlexey Dobriyan 							SG_ELEMENT_SIZE);
51791da177e4SLinus Torvalds 			}
51801da177e4SLinus Torvalds 
51811da177e4SLinus Torvalds 			remain_cnt = pCurrSCCB->Sccb_XferCnt;
51821da177e4SLinus Torvalds 
51831da177e4SLinus Torvalds 			while (remain_cnt < 0x01000000L) {
51841da177e4SLinus Torvalds 
51851da177e4SLinus Torvalds 				sg_ptr--;
5186391e2f25SKhalid Aziz 				segp = (struct blogic_sg_seg *)(pCurrSCCB->
5187391e2f25SKhalid Aziz 						DataPointer) + (sg_ptr * 2);
5188391e2f25SKhalid Aziz 				if (remain_cnt > (unsigned long)segp->segbytes)
51895c04a7b8SAlexey Dobriyan 					remain_cnt -=
5190391e2f25SKhalid Aziz 						(unsigned long)segp->segbytes;
5191391e2f25SKhalid Aziz 				else
51921da177e4SLinus Torvalds 					break;
51931da177e4SLinus Torvalds 			}
51941da177e4SLinus Torvalds 
51951da177e4SLinus Torvalds 			if (remain_cnt < 0x01000000L) {
51961da177e4SLinus Torvalds 
51971da177e4SLinus Torvalds 				pCurrSCCB->Sccb_SGoffset = remain_cnt;
51981da177e4SLinus Torvalds 
5199c823feebSAlexey Dobriyan 				pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
52001da177e4SLinus Torvalds 
52015c04a7b8SAlexey Dobriyan 				if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
52025c04a7b8SAlexey Dobriyan 				    pCurrSCCB->DataLength && (remain_cnt == 0))
52031da177e4SLinus Torvalds 
52045c04a7b8SAlexey Dobriyan 					pCurrSCCB->Sccb_XferState |=
52055c04a7b8SAlexey Dobriyan 					    F_ALL_XFERRED;
52061da177e4SLinus Torvalds 			}
52071da177e4SLinus Torvalds 
52081da177e4SLinus Torvalds 			else {
52091da177e4SLinus Torvalds 
52101da177e4SLinus Torvalds 				if (pCurrSCCB->HostStatus == 0x00) {
52111da177e4SLinus Torvalds 
52125c04a7b8SAlexey Dobriyan 					pCurrSCCB->HostStatus =
52135c04a7b8SAlexey Dobriyan 					    SCCB_GROSS_FW_ERR;
52141da177e4SLinus Torvalds 				}
52151da177e4SLinus Torvalds 			}
52161da177e4SLinus Torvalds 		}
52171da177e4SLinus Torvalds 
52181da177e4SLinus Torvalds 		if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
52191da177e4SLinus Torvalds 
52201da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
52211da177e4SLinus Torvalds 
522247b5d69cSJames Bottomley  				FPT_busMstrTimeOut(port);
52231da177e4SLinus Torvalds 			}
52241da177e4SLinus Torvalds 
52251da177e4SLinus Torvalds 			else {
52261da177e4SLinus Torvalds 
52275c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_int_status) &
52285c04a7b8SAlexey Dobriyan 				    INT_EXT_STATUS) {
52291da177e4SLinus Torvalds 
52305c04a7b8SAlexey Dobriyan 					if (RD_HARPOON(port + hp_ext_status) &
52315c04a7b8SAlexey Dobriyan 					    BAD_EXT_STATUS) {
52321da177e4SLinus Torvalds 
52335c04a7b8SAlexey Dobriyan 						if (pCurrSCCB->HostStatus ==
52345c04a7b8SAlexey Dobriyan 						    0x00) {
52351da177e4SLinus Torvalds 
52365c04a7b8SAlexey Dobriyan 							pCurrSCCB->HostStatus =
52375c04a7b8SAlexey Dobriyan 							    SCCB_BM_ERR;
52381da177e4SLinus Torvalds 						}
52391da177e4SLinus Torvalds 					}
52401da177e4SLinus Torvalds 				}
52411da177e4SLinus Torvalds 
52421da177e4SLinus Torvalds 			}
52431da177e4SLinus Torvalds 		}
52441da177e4SLinus Torvalds 
52451da177e4SLinus Torvalds 		else {
52461da177e4SLinus Torvalds 
52471da177e4SLinus Torvalds 			if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
52481da177e4SLinus Torvalds 
52491da177e4SLinus Torvalds 				timeout = SHORT_WAIT;
52501da177e4SLinus Torvalds 
52515c04a7b8SAlexey Dobriyan 				while ((RD_HARPOON(port + hp_ext_status) &
52525c04a7b8SAlexey Dobriyan 					BM_CMD_BUSY)
52535c04a7b8SAlexey Dobriyan 				       && ((RD_HARPOON(port + hp_fifo_cnt)) >=
52545c04a7b8SAlexey Dobriyan 					   BM_THRESHOLD) && timeout--) {
52555c04a7b8SAlexey Dobriyan 				}
52561da177e4SLinus Torvalds 			}
52571da177e4SLinus Torvalds 
52581da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
52591da177e4SLinus Torvalds 
52605c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_bm_ctrl,
52615c04a7b8SAlexey Dobriyan 					   (RD_HARPOON(port + hp_bm_ctrl) |
52621da177e4SLinus Torvalds 					    FLUSH_XFER_CNTR));
52631da177e4SLinus Torvalds 
52641da177e4SLinus Torvalds 				timeout = LONG_WAIT;
52651da177e4SLinus Torvalds 
52665c04a7b8SAlexey Dobriyan 				while ((RD_HARPOON(port + hp_ext_status) &
52675c04a7b8SAlexey Dobriyan 					BM_CMD_BUSY) && timeout--) {
52685c04a7b8SAlexey Dobriyan 				}
52691da177e4SLinus Torvalds 
52705c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_bm_ctrl,
52715c04a7b8SAlexey Dobriyan 					   (RD_HARPOON(port + hp_bm_ctrl) &
52721da177e4SLinus Torvalds 					    ~FLUSH_XFER_CNTR));
52731da177e4SLinus Torvalds 
52745c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_ext_status) &
52755c04a7b8SAlexey Dobriyan 				    BM_CMD_BUSY) {
52761da177e4SLinus Torvalds 
52771da177e4SLinus Torvalds 					if (pCurrSCCB->HostStatus == 0x00) {
52781da177e4SLinus Torvalds 
52795c04a7b8SAlexey Dobriyan 						pCurrSCCB->HostStatus =
52805c04a7b8SAlexey Dobriyan 						    SCCB_BM_ERR;
52811da177e4SLinus Torvalds 					}
52821da177e4SLinus Torvalds 
528347b5d69cSJames Bottomley  					FPT_busMstrTimeOut(port);
52841da177e4SLinus Torvalds 				}
52851da177e4SLinus Torvalds 			}
52861da177e4SLinus Torvalds 
52871da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
52881da177e4SLinus Torvalds 
52895c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_ext_status) &
52905c04a7b8SAlexey Dobriyan 				    BAD_EXT_STATUS) {
52911da177e4SLinus Torvalds 
52921da177e4SLinus Torvalds 					if (pCurrSCCB->HostStatus == 0x00) {
52931da177e4SLinus Torvalds 
52945c04a7b8SAlexey Dobriyan 						pCurrSCCB->HostStatus =
52955c04a7b8SAlexey Dobriyan 						    SCCB_BM_ERR;
52961da177e4SLinus Torvalds 					}
52971da177e4SLinus Torvalds 				}
52981da177e4SLinus Torvalds 			}
52991da177e4SLinus Torvalds 		}
53001da177e4SLinus Torvalds 
53011da177e4SLinus Torvalds 	}
53021da177e4SLinus Torvalds 
53031da177e4SLinus Torvalds 	else {
53041da177e4SLinus Torvalds 
53051da177e4SLinus Torvalds 		if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
53061da177e4SLinus Torvalds 
53071da177e4SLinus Torvalds 			timeout = LONG_WAIT;
53081da177e4SLinus Torvalds 
53095c04a7b8SAlexey Dobriyan 			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
53105c04a7b8SAlexey Dobriyan 			       && timeout--) {
53115c04a7b8SAlexey Dobriyan 			}
53121da177e4SLinus Torvalds 
53131da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
53141da177e4SLinus Torvalds 
53151da177e4SLinus Torvalds 				if (pCurrSCCB->HostStatus == 0x00) {
53161da177e4SLinus Torvalds 
53171da177e4SLinus Torvalds 					pCurrSCCB->HostStatus = SCCB_BM_ERR;
53181da177e4SLinus Torvalds 				}
53191da177e4SLinus Torvalds 
532047b5d69cSJames Bottomley  				FPT_busMstrTimeOut(port);
53211da177e4SLinus Torvalds 			}
53221da177e4SLinus Torvalds 		}
53231da177e4SLinus Torvalds 
53241da177e4SLinus Torvalds 		if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
53251da177e4SLinus Torvalds 
53261da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
53271da177e4SLinus Torvalds 
53281da177e4SLinus Torvalds 				if (pCurrSCCB->HostStatus == 0x00) {
53291da177e4SLinus Torvalds 
53301da177e4SLinus Torvalds 					pCurrSCCB->HostStatus = SCCB_BM_ERR;
53311da177e4SLinus Torvalds 				}
53321da177e4SLinus Torvalds 			}
53331da177e4SLinus Torvalds 
53341da177e4SLinus Torvalds 		}
53351da177e4SLinus Torvalds 
53361da177e4SLinus Torvalds 		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
53371da177e4SLinus Torvalds 
53385c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_page_ctrl,
53395c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_page_ctrl) &
53401da177e4SLinus Torvalds 				    ~SCATTER_EN));
53411da177e4SLinus Torvalds 
53421da177e4SLinus Torvalds 			WR_HARPOON(port + hp_sg_addr, 0x00);
53431da177e4SLinus Torvalds 
53441da177e4SLinus Torvalds 			pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
53451da177e4SLinus Torvalds 
53461da177e4SLinus Torvalds 			pCurrSCCB->Sccb_SGoffset = 0x00;
53471da177e4SLinus Torvalds 
5348391e2f25SKhalid Aziz 			if ((u32)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >=
53491da177e4SLinus Torvalds 					pCurrSCCB->DataLength) {
53501da177e4SLinus Torvalds 
53511da177e4SLinus Torvalds 				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
53525c04a7b8SAlexey Dobriyan 				pCurrSCCB->Sccb_sgseg =
53535c04a7b8SAlexey Dobriyan 				    (unsigned short)(pCurrSCCB->DataLength /
53545c04a7b8SAlexey Dobriyan 						     SG_ELEMENT_SIZE);
53551da177e4SLinus Torvalds 			}
53561da177e4SLinus Torvalds 		}
53571da177e4SLinus Torvalds 
53581da177e4SLinus Torvalds 		else {
53591da177e4SLinus Torvalds 			if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
53601da177e4SLinus Torvalds 				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
53611da177e4SLinus Torvalds 		}
53621da177e4SLinus Torvalds 	}
53631da177e4SLinus Torvalds 
53641da177e4SLinus Torvalds 	WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
53651da177e4SLinus Torvalds }
53661da177e4SLinus Torvalds 
53671da177e4SLinus Torvalds /*---------------------------------------------------------------------
53681da177e4SLinus Torvalds  *
53691da177e4SLinus Torvalds  * Function: Host Data Transfer Restart
53701da177e4SLinus Torvalds  *
53711da177e4SLinus Torvalds  * Description: Reset the available count due to a restore data
53721da177e4SLinus Torvalds  *              pointers message.
53731da177e4SLinus Torvalds  *
53741da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_hostDataXferRestart(struct sccb * currSCCB)537569eb2ea4SAlexey Dobriyan static void FPT_hostDataXferRestart(struct sccb *currSCCB)
53761da177e4SLinus Torvalds {
5377d63a4cccSAlexey Dobriyan 	unsigned long data_count;
5378ce793215SAlexey Dobriyan 	unsigned int sg_index;
5379391e2f25SKhalid Aziz 	struct blogic_sg_seg *segp;
53801da177e4SLinus Torvalds 
53811da177e4SLinus Torvalds 	if (currSCCB->Sccb_XferState & F_SG_XFER) {
53821da177e4SLinus Torvalds 
53831da177e4SLinus Torvalds 		currSCCB->Sccb_XferCnt = 0;
53841da177e4SLinus Torvalds 
53851da177e4SLinus Torvalds 		sg_index = 0xffff;	/*Index by long words into sg list. */
53861da177e4SLinus Torvalds 		data_count = 0;		/*Running count of SG xfer counts. */
53871da177e4SLinus Torvalds 
53881da177e4SLinus Torvalds 
53891da177e4SLinus Torvalds 		while (data_count < currSCCB->Sccb_ATC) {
53901da177e4SLinus Torvalds 
53911da177e4SLinus Torvalds 			sg_index++;
5392391e2f25SKhalid Aziz 			segp = (struct blogic_sg_seg *)(currSCCB->DataPointer) +
5393391e2f25SKhalid Aziz 						(sg_index * 2);
5394391e2f25SKhalid Aziz 			data_count += segp->segbytes;
53951da177e4SLinus Torvalds 		}
53961da177e4SLinus Torvalds 
53971da177e4SLinus Torvalds 		if (data_count == currSCCB->Sccb_ATC) {
53981da177e4SLinus Torvalds 
53991da177e4SLinus Torvalds 			currSCCB->Sccb_SGoffset = 0;
54001da177e4SLinus Torvalds 			sg_index++;
54011da177e4SLinus Torvalds 		}
54021da177e4SLinus Torvalds 
54031da177e4SLinus Torvalds 		else {
54045c04a7b8SAlexey Dobriyan 			currSCCB->Sccb_SGoffset =
54055c04a7b8SAlexey Dobriyan 			    data_count - currSCCB->Sccb_ATC;
54061da177e4SLinus Torvalds 		}
54071da177e4SLinus Torvalds 
5408c823feebSAlexey Dobriyan 		currSCCB->Sccb_sgseg = (unsigned short)sg_index;
54091da177e4SLinus Torvalds 	}
54101da177e4SLinus Torvalds 
54111da177e4SLinus Torvalds 	else {
54125c04a7b8SAlexey Dobriyan 		currSCCB->Sccb_XferCnt =
54135c04a7b8SAlexey Dobriyan 		    currSCCB->DataLength - currSCCB->Sccb_ATC;
54141da177e4SLinus Torvalds 	}
54151da177e4SLinus Torvalds }
54161da177e4SLinus Torvalds 
54171da177e4SLinus Torvalds /*---------------------------------------------------------------------
54181da177e4SLinus Torvalds  *
541947b5d69cSJames Bottomley   * Function: FPT_scini
54201da177e4SLinus Torvalds  *
54211da177e4SLinus Torvalds  * Description: Setup all data structures necessary for SCAM selection.
54221da177e4SLinus Torvalds  *
54231da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
54241da177e4SLinus Torvalds 
FPT_scini(unsigned char p_card,unsigned char p_our_id,unsigned char p_power_up)54255c04a7b8SAlexey Dobriyan static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
54265c04a7b8SAlexey Dobriyan 		      unsigned char p_power_up)
54271da177e4SLinus Torvalds {
54281da177e4SLinus Torvalds 
5429db038cf8SAlexey Dobriyan 	unsigned char loser, assigned_id;
5430391e2f25SKhalid Aziz 	u32 p_port;
54311da177e4SLinus Torvalds 
5432db038cf8SAlexey Dobriyan 	unsigned char i, k, ScamFlg;
543313e6851aSAlexey Dobriyan 	struct sccb_card *currCard;
543468d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
54351da177e4SLinus Torvalds 
543647b5d69cSJames Bottomley  	currCard = &FPT_BL_Card[p_card];
54371da177e4SLinus Torvalds 	p_port = currCard->ioPort;
54381da177e4SLinus Torvalds 	pCurrNvRam = currCard->pNvRamInfo;
54391da177e4SLinus Torvalds 
54401da177e4SLinus Torvalds 	if (pCurrNvRam) {
54411da177e4SLinus Torvalds 		ScamFlg = pCurrNvRam->niScamConf;
54421da177e4SLinus Torvalds 		i = pCurrNvRam->niSysConf;
54435c04a7b8SAlexey Dobriyan 	} else {
54445c04a7b8SAlexey Dobriyan 		ScamFlg =
54455c04a7b8SAlexey Dobriyan 		    (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
54465c04a7b8SAlexey Dobriyan 		i = (unsigned
54475c04a7b8SAlexey Dobriyan 		     char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
54481da177e4SLinus Torvalds 	}
54491da177e4SLinus Torvalds 	if (!(i & 0x02))	/* check if reset bus in AutoSCSI parameter set */
54501da177e4SLinus Torvalds 		return;
54511da177e4SLinus Torvalds 
545247b5d69cSJames Bottomley  	FPT_inisci(p_card, p_port, p_our_id);
54531da177e4SLinus Torvalds 
54541da177e4SLinus Torvalds 	/* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
54551da177e4SLinus Torvalds 	   too slow to return to SCAM selection */
54561da177e4SLinus Torvalds 
54571da177e4SLinus Torvalds 	/* if (p_power_up)
545847b5d69cSJames Bottomley  	   FPT_Wait1Second(p_port);
54591da177e4SLinus Torvalds 	   else
546047b5d69cSJames Bottomley  	   FPT_Wait(p_port, TO_250ms); */
54611da177e4SLinus Torvalds 
546247b5d69cSJames Bottomley  	FPT_Wait1Second(p_port);
54631da177e4SLinus Torvalds 
54645c04a7b8SAlexey Dobriyan 	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
54655c04a7b8SAlexey Dobriyan 		while (!(FPT_scarb(p_port, INIT_SELTD))) {
54665c04a7b8SAlexey Dobriyan 		}
54671da177e4SLinus Torvalds 
546847b5d69cSJames Bottomley  		FPT_scsel(p_port);
54691da177e4SLinus Torvalds 
54701da177e4SLinus Torvalds 		do {
547147b5d69cSJames Bottomley  			FPT_scxferc(p_port, SYNC_PTRN);
547247b5d69cSJames Bottomley  			FPT_scxferc(p_port, DOM_MSTR);
54735c04a7b8SAlexey Dobriyan 			loser =
54745c04a7b8SAlexey Dobriyan 			    FPT_scsendi(p_port,
54755c04a7b8SAlexey Dobriyan 					&FPT_scamInfo[p_our_id].id_string[0]);
54761da177e4SLinus Torvalds 		} while (loser == 0xFF);
54771da177e4SLinus Torvalds 
547847b5d69cSJames Bottomley  		FPT_scbusf(p_port);
54791da177e4SLinus Torvalds 
54805c04a7b8SAlexey Dobriyan 		if ((p_power_up) && (!loser)) {
548147b5d69cSJames Bottomley  			FPT_sresb(p_port, p_card);
548247b5d69cSJames Bottomley  			FPT_Wait(p_port, TO_250ms);
54831da177e4SLinus Torvalds 
54845c04a7b8SAlexey Dobriyan 			while (!(FPT_scarb(p_port, INIT_SELTD))) {
54855c04a7b8SAlexey Dobriyan 			}
54861da177e4SLinus Torvalds 
548747b5d69cSJames Bottomley  			FPT_scsel(p_port);
54881da177e4SLinus Torvalds 
54891da177e4SLinus Torvalds 			do {
549047b5d69cSJames Bottomley  				FPT_scxferc(p_port, SYNC_PTRN);
549147b5d69cSJames Bottomley  				FPT_scxferc(p_port, DOM_MSTR);
54925c04a7b8SAlexey Dobriyan 				loser =
54935c04a7b8SAlexey Dobriyan 				    FPT_scsendi(p_port,
54945c04a7b8SAlexey Dobriyan 						&FPT_scamInfo[p_our_id].
54951da177e4SLinus Torvalds 						id_string[0]);
54961da177e4SLinus Torvalds 			} while (loser == 0xFF);
54971da177e4SLinus Torvalds 
549847b5d69cSJames Bottomley  			FPT_scbusf(p_port);
54991da177e4SLinus Torvalds 		}
55001da177e4SLinus Torvalds 	}
55011da177e4SLinus Torvalds 
55025c04a7b8SAlexey Dobriyan 	else {
550347b5d69cSJames Bottomley  		loser = 0;
55041da177e4SLinus Torvalds 	}
55051da177e4SLinus Torvalds 
55065c04a7b8SAlexey Dobriyan 	if (!loser) {
55071da177e4SLinus Torvalds 
550847b5d69cSJames Bottomley  		FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
55091da177e4SLinus Torvalds 
55105c04a7b8SAlexey Dobriyan 		if (ScamFlg & SCAM_ENABLED) {
55111da177e4SLinus Torvalds 
55125c04a7b8SAlexey Dobriyan 			for (i = 0; i < MAX_SCSI_TAR; i++) {
551347b5d69cSJames Bottomley  				if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
55145c04a7b8SAlexey Dobriyan 				    (FPT_scamInfo[i].state == ID_UNUSED)) {
55155c04a7b8SAlexey Dobriyan 					if (FPT_scsell(p_port, i)) {
551647b5d69cSJames Bottomley  						FPT_scamInfo[i].state = LEGACY;
55175c04a7b8SAlexey Dobriyan 						if ((FPT_scamInfo[i].
55185c04a7b8SAlexey Dobriyan 						     id_string[0] != 0xFF)
55195c04a7b8SAlexey Dobriyan 						    || (FPT_scamInfo[i].
55205c04a7b8SAlexey Dobriyan 							id_string[1] != 0xFA)) {
55211da177e4SLinus Torvalds 
55225c04a7b8SAlexey Dobriyan 							FPT_scamInfo[i].
55235c04a7b8SAlexey Dobriyan 							    id_string[0] = 0xFF;
55245c04a7b8SAlexey Dobriyan 							FPT_scamInfo[i].
55255c04a7b8SAlexey Dobriyan 							    id_string[1] = 0xFA;
55261da177e4SLinus Torvalds 							if (pCurrNvRam == NULL)
55275c04a7b8SAlexey Dobriyan 								currCard->
55285c04a7b8SAlexey Dobriyan 								    globalFlags
55295c04a7b8SAlexey Dobriyan 								    |=
55305c04a7b8SAlexey Dobriyan 								    F_UPDATE_EEPROM;
55311da177e4SLinus Torvalds 						}
55321da177e4SLinus Torvalds 					}
55331da177e4SLinus Torvalds 				}
55341da177e4SLinus Torvalds 			}
55351da177e4SLinus Torvalds 
553647b5d69cSJames Bottomley  			FPT_sresb(p_port, p_card);
553747b5d69cSJames Bottomley  			FPT_Wait1Second(p_port);
55385c04a7b8SAlexey Dobriyan 			while (!(FPT_scarb(p_port, INIT_SELTD))) {
55395c04a7b8SAlexey Dobriyan 			}
554047b5d69cSJames Bottomley  			FPT_scsel(p_port);
554147b5d69cSJames Bottomley  			FPT_scasid(p_card, p_port);
55421da177e4SLinus Torvalds 		}
55431da177e4SLinus Torvalds 
55441da177e4SLinus Torvalds 	}
55451da177e4SLinus Torvalds 
55465c04a7b8SAlexey Dobriyan 	else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
554747b5d69cSJames Bottomley  		FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
554847b5d69cSJames Bottomley  		assigned_id = 0;
554947b5d69cSJames Bottomley  		FPT_scwtsel(p_port);
55501da177e4SLinus Torvalds 
55511da177e4SLinus Torvalds 		do {
55525c04a7b8SAlexey Dobriyan 			while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
55535c04a7b8SAlexey Dobriyan 			}
55541da177e4SLinus Torvalds 
555547b5d69cSJames Bottomley  			i = FPT_scxferc(p_port, 0x00);
55565c04a7b8SAlexey Dobriyan 			if (i == ASSIGN_ID) {
55575c04a7b8SAlexey Dobriyan 				if (!
55585c04a7b8SAlexey Dobriyan 				    (FPT_scsendi
55595c04a7b8SAlexey Dobriyan 				     (p_port,
55605c04a7b8SAlexey Dobriyan 				      &FPT_scamInfo[p_our_id].id_string[0]))) {
556147b5d69cSJames Bottomley  					i = FPT_scxferc(p_port, 0x00);
55625c04a7b8SAlexey Dobriyan 					if (FPT_scvalq(i)) {
556347b5d69cSJames Bottomley  						k = FPT_scxferc(p_port, 0x00);
55641da177e4SLinus Torvalds 
55655c04a7b8SAlexey Dobriyan 						if (FPT_scvalq(k)) {
55661da177e4SLinus Torvalds 							currCard->ourId =
55675c04a7b8SAlexey Dobriyan 							    ((unsigned char)(i
55685c04a7b8SAlexey Dobriyan 									     <<
55695c04a7b8SAlexey Dobriyan 									     3)
55705c04a7b8SAlexey Dobriyan 							     +
55715c04a7b8SAlexey Dobriyan 							     (k &
55725c04a7b8SAlexey Dobriyan 							      (unsigned char)7))
55735c04a7b8SAlexey Dobriyan 							    & (unsigned char)
55745c04a7b8SAlexey Dobriyan 							    0x3F;
55755c04a7b8SAlexey Dobriyan 							FPT_inisci(p_card,
55765c04a7b8SAlexey Dobriyan 								   p_port,
55775c04a7b8SAlexey Dobriyan 								   p_our_id);
55785c04a7b8SAlexey Dobriyan 							FPT_scamInfo[currCard->
55795c04a7b8SAlexey Dobriyan 								     ourId].
55805c04a7b8SAlexey Dobriyan 							    state = ID_ASSIGNED;
55815c04a7b8SAlexey Dobriyan 							FPT_scamInfo[currCard->
55825c04a7b8SAlexey Dobriyan 								     ourId].
55835c04a7b8SAlexey Dobriyan 							    id_string[0]
55841da177e4SLinus Torvalds 							    = SLV_TYPE_CODE0;
558547b5d69cSJames Bottomley  							assigned_id = 1;
55861da177e4SLinus Torvalds 						}
55871da177e4SLinus Torvalds 					}
55881da177e4SLinus Torvalds 				}
55891da177e4SLinus Torvalds 			}
55901da177e4SLinus Torvalds 
55915c04a7b8SAlexey Dobriyan 			else if (i == SET_P_FLAG) {
559247b5d69cSJames Bottomley  				if (!(FPT_scsendi(p_port,
55935c04a7b8SAlexey Dobriyan 						  &FPT_scamInfo[p_our_id].
55945c04a7b8SAlexey Dobriyan 						  id_string[0])))
55955c04a7b8SAlexey Dobriyan 					FPT_scamInfo[p_our_id].id_string[0] |=
55965c04a7b8SAlexey Dobriyan 					    0x80;
55971da177e4SLinus Torvalds 			}
55981da177e4SLinus Torvalds 		} while (!assigned_id);
55991da177e4SLinus Torvalds 
56005c04a7b8SAlexey Dobriyan 		while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
56015c04a7b8SAlexey Dobriyan 		}
56021da177e4SLinus Torvalds 	}
56031da177e4SLinus Torvalds 
56045c04a7b8SAlexey Dobriyan 	if (ScamFlg & SCAM_ENABLED) {
560547b5d69cSJames Bottomley  		FPT_scbusf(p_port);
56065c04a7b8SAlexey Dobriyan 		if (currCard->globalFlags & F_UPDATE_EEPROM) {
560747b5d69cSJames Bottomley  			FPT_scsavdi(p_card, p_port);
56081da177e4SLinus Torvalds 			currCard->globalFlags &= ~F_UPDATE_EEPROM;
56091da177e4SLinus Torvalds 		}
56101da177e4SLinus Torvalds 	}
56111da177e4SLinus Torvalds 
56121da177e4SLinus Torvalds /*
56131da177e4SLinus Torvalds    for (i=0,k=0; i < MAX_SCSI_TAR; i++)
56141da177e4SLinus Torvalds       {
561547b5d69cSJames Bottomley        if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
561647b5d69cSJames Bottomley           (FPT_scamInfo[i].state == LEGACY))
56171da177e4SLinus Torvalds          k++;
56181da177e4SLinus Torvalds       }
56191da177e4SLinus Torvalds 
56201da177e4SLinus Torvalds    if (k==2)
56211da177e4SLinus Torvalds       currCard->globalFlags |= F_SINGLE_DEVICE;
56221da177e4SLinus Torvalds    else
56231da177e4SLinus Torvalds       currCard->globalFlags &= ~F_SINGLE_DEVICE;
56241da177e4SLinus Torvalds */
56251da177e4SLinus Torvalds }
56261da177e4SLinus Torvalds 
56271da177e4SLinus Torvalds /*---------------------------------------------------------------------
56281da177e4SLinus Torvalds  *
562947b5d69cSJames Bottomley   * Function: FPT_scarb
56301da177e4SLinus Torvalds  *
56311da177e4SLinus Torvalds  * Description: Gain control of the bus and wait SCAM select time (250ms)
56321da177e4SLinus Torvalds  *
56331da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
56341da177e4SLinus Torvalds 
FPT_scarb(u32 p_port,unsigned char p_sel_type)5635391e2f25SKhalid Aziz static int FPT_scarb(u32 p_port, unsigned char p_sel_type)
56361da177e4SLinus Torvalds {
56375c04a7b8SAlexey Dobriyan 	if (p_sel_type == INIT_SELTD) {
56381da177e4SLinus Torvalds 
56395c04a7b8SAlexey Dobriyan 		while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
56405c04a7b8SAlexey Dobriyan 		}
56411da177e4SLinus Torvalds 
56421da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
56435c1b85e2SAlexey Dobriyan 			return 0;
56441da177e4SLinus Torvalds 
56451da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
56465c1b85e2SAlexey Dobriyan 			return 0;
56471da177e4SLinus Torvalds 
56485c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_scsisig,
56495c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
56501da177e4SLinus Torvalds 
56511da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
56521da177e4SLinus Torvalds 
56535c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_scsisig,
56545c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(p_port + hp_scsisig) &
56551da177e4SLinus Torvalds 				    ~SCSI_BSY));
56565c1b85e2SAlexey Dobriyan 			return 0;
56571da177e4SLinus Torvalds 		}
56581da177e4SLinus Torvalds 
56595c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_scsisig,
56605c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
56611da177e4SLinus Torvalds 
56621da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
56631da177e4SLinus Torvalds 
56645c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_scsisig,
56655c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(p_port + hp_scsisig) &
56661da177e4SLinus Torvalds 				    ~(SCSI_BSY | SCSI_SEL)));
56675c1b85e2SAlexey Dobriyan 			return 0;
56681da177e4SLinus Torvalds 		}
56691da177e4SLinus Torvalds 	}
56701da177e4SLinus Torvalds 
56711da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
56721da177e4SLinus Torvalds 					   & ~ACTdeassert));
56731da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
56741da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
56751da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_1, 0x00);
56761da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
56771da177e4SLinus Torvalds 
56785c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsisig,
56795c04a7b8SAlexey Dobriyan 		   (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
56801da177e4SLinus Torvalds 
56811da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
56821da177e4SLinus Torvalds 					 & ~SCSI_BSY));
56831da177e4SLinus Torvalds 
568447b5d69cSJames Bottomley  	FPT_Wait(p_port, TO_250ms);
56851da177e4SLinus Torvalds 
56865c1b85e2SAlexey Dobriyan 	return 1;
56871da177e4SLinus Torvalds }
56881da177e4SLinus Torvalds 
56891da177e4SLinus Torvalds /*---------------------------------------------------------------------
56901da177e4SLinus Torvalds  *
569147b5d69cSJames Bottomley   * Function: FPT_scbusf
56921da177e4SLinus Torvalds  *
56931da177e4SLinus Torvalds  * Description: Release the SCSI bus and disable SCAM selection.
56941da177e4SLinus Torvalds  *
56951da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
56961da177e4SLinus Torvalds 
FPT_scbusf(u32 p_port)5697391e2f25SKhalid Aziz static void FPT_scbusf(u32 p_port)
56981da177e4SLinus Torvalds {
56991da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl,
57001da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
57011da177e4SLinus Torvalds 
57021da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
57031da177e4SLinus Torvalds 
57041da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
57051da177e4SLinus Torvalds 					    & ~SCSI_BUS_EN));
57061da177e4SLinus Torvalds 
57071da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, 0x00);
57081da177e4SLinus Torvalds 
57091da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
57101da177e4SLinus Torvalds 					   & ~SCAM_EN));
57111da177e4SLinus Torvalds 
57121da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
57131da177e4SLinus Torvalds 					   | ACTdeassert));
57141da177e4SLinus Torvalds 
57151da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
57161da177e4SLinus Torvalds 
57171da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl,
57181da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
57191da177e4SLinus Torvalds }
57201da177e4SLinus Torvalds 
57211da177e4SLinus Torvalds /*---------------------------------------------------------------------
57221da177e4SLinus Torvalds  *
572347b5d69cSJames Bottomley   * Function: FPT_scasid
57241da177e4SLinus Torvalds  *
57251da177e4SLinus Torvalds  * Description: Assign an ID to all the SCAM devices.
57261da177e4SLinus Torvalds  *
57271da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
57281da177e4SLinus Torvalds 
FPT_scasid(unsigned char p_card,u32 p_port)5729391e2f25SKhalid Aziz static void FPT_scasid(unsigned char p_card, u32 p_port)
57301da177e4SLinus Torvalds {
5731db038cf8SAlexey Dobriyan 	unsigned char temp_id_string[ID_STRING_LENGTH];
57321da177e4SLinus Torvalds 
5733db038cf8SAlexey Dobriyan 	unsigned char i, k, scam_id;
5734db038cf8SAlexey Dobriyan 	unsigned char crcBytes[3];
573568d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
5736fd1e29edSAlexey Dobriyan 	unsigned short *pCrcBytes;
57371da177e4SLinus Torvalds 
573847b5d69cSJames Bottomley  	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
57391da177e4SLinus Torvalds 
574047b5d69cSJames Bottomley  	i = 0;
57411da177e4SLinus Torvalds 
57425c04a7b8SAlexey Dobriyan 	while (!i) {
57431da177e4SLinus Torvalds 
57445c04a7b8SAlexey Dobriyan 		for (k = 0; k < ID_STRING_LENGTH; k++) {
5745db038cf8SAlexey Dobriyan 			temp_id_string[k] = (unsigned char)0x00;
57461da177e4SLinus Torvalds 		}
57471da177e4SLinus Torvalds 
574847b5d69cSJames Bottomley  		FPT_scxferc(p_port, SYNC_PTRN);
574947b5d69cSJames Bottomley  		FPT_scxferc(p_port, ASSIGN_ID);
57501da177e4SLinus Torvalds 
57515c04a7b8SAlexey Dobriyan 		if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
57521da177e4SLinus Torvalds 			if (pCurrNvRam) {
5753fd1e29edSAlexey Dobriyan 				pCrcBytes = (unsigned short *)&crcBytes[0];
575447b5d69cSJames Bottomley  				*pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
575547b5d69cSJames Bottomley  				crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
57561da177e4SLinus Torvalds 				temp_id_string[1] = crcBytes[2];
57571da177e4SLinus Torvalds 				temp_id_string[2] = crcBytes[0];
57581da177e4SLinus Torvalds 				temp_id_string[3] = crcBytes[1];
57591da177e4SLinus Torvalds 				for (k = 4; k < ID_STRING_LENGTH; k++)
5760db038cf8SAlexey Dobriyan 					temp_id_string[k] = (unsigned char)0x00;
57611da177e4SLinus Torvalds 			}
576247b5d69cSJames Bottomley  			i = FPT_scmachid(p_card, temp_id_string);
57631da177e4SLinus Torvalds 
57645c04a7b8SAlexey Dobriyan 			if (i == CLR_PRIORITY) {
576547b5d69cSJames Bottomley  				FPT_scxferc(p_port, MISC_CODE);
576647b5d69cSJames Bottomley  				FPT_scxferc(p_port, CLR_P_FLAG);
576747b5d69cSJames Bottomley  				i = 0;	/*Not the last ID yet. */
57681da177e4SLinus Torvalds 			}
57691da177e4SLinus Torvalds 
57705c04a7b8SAlexey Dobriyan 			else if (i != NO_ID_AVAIL) {
57711da177e4SLinus Torvalds 				if (i < 8)
577247b5d69cSJames Bottomley  					FPT_scxferc(p_port, ID_0_7);
57731da177e4SLinus Torvalds 				else
577447b5d69cSJames Bottomley  					FPT_scxferc(p_port, ID_8_F);
57751da177e4SLinus Torvalds 
5776db038cf8SAlexey Dobriyan 				scam_id = (i & (unsigned char)0x07);
57771da177e4SLinus Torvalds 
57781da177e4SLinus Torvalds 				for (k = 1; k < 0x08; k <<= 1)
57791da177e4SLinus Torvalds 					if (!(k & i))
57801da177e4SLinus Torvalds 						scam_id += 0x08;	/*Count number of zeros in DB0-3. */
57811da177e4SLinus Torvalds 
578247b5d69cSJames Bottomley  				FPT_scxferc(p_port, scam_id);
57831da177e4SLinus Torvalds 
578447b5d69cSJames Bottomley  				i = 0;	/*Not the last ID yet. */
57851da177e4SLinus Torvalds 			}
57861da177e4SLinus Torvalds 		}
57871da177e4SLinus Torvalds 
57885c04a7b8SAlexey Dobriyan 		else {
578947b5d69cSJames Bottomley  			i = 1;
57901da177e4SLinus Torvalds 		}
57911da177e4SLinus Torvalds 
57921da177e4SLinus Torvalds 	}			/*End while */
57931da177e4SLinus Torvalds 
579447b5d69cSJames Bottomley  	FPT_scxferc(p_port, SYNC_PTRN);
579547b5d69cSJames Bottomley  	FPT_scxferc(p_port, CFG_CMPLT);
57961da177e4SLinus Torvalds }
57971da177e4SLinus Torvalds 
57981da177e4SLinus Torvalds /*---------------------------------------------------------------------
57991da177e4SLinus Torvalds  *
580047b5d69cSJames Bottomley   * Function: FPT_scsel
58011da177e4SLinus Torvalds  *
58021da177e4SLinus Torvalds  * Description: Select all the SCAM devices.
58031da177e4SLinus Torvalds  *
58041da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
58051da177e4SLinus Torvalds 
FPT_scsel(u32 p_port)5806391e2f25SKhalid Aziz static void FPT_scsel(u32 p_port)
58071da177e4SLinus Torvalds {
58081da177e4SLinus Torvalds 
58091da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
581047b5d69cSJames Bottomley  	FPT_scwiros(p_port, SCSI_MSG);
58111da177e4SLinus Torvalds 
58121da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
58131da177e4SLinus Torvalds 
58145c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsisig,
58155c04a7b8SAlexey Dobriyan 		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
58165c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsidata_0,
58175c04a7b8SAlexey Dobriyan 		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5818db038cf8SAlexey Dobriyan 				   (unsigned char)(BIT(7) + BIT(6))));
58191da177e4SLinus Torvalds 
58201da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
582147b5d69cSJames Bottomley  	FPT_scwiros(p_port, SCSI_SEL);
58221da177e4SLinus Torvalds 
58235c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsidata_0,
58245c04a7b8SAlexey Dobriyan 		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5825db038cf8SAlexey Dobriyan 				   ~(unsigned char)BIT(6)));
582647b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(6));
58271da177e4SLinus Torvalds 
58285c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsisig,
58295c04a7b8SAlexey Dobriyan 		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
58301da177e4SLinus Torvalds }
58311da177e4SLinus Torvalds 
58321da177e4SLinus Torvalds /*---------------------------------------------------------------------
58331da177e4SLinus Torvalds  *
583447b5d69cSJames Bottomley   * Function: FPT_scxferc
58351da177e4SLinus Torvalds  *
58361da177e4SLinus Torvalds  * Description: Handshake the p_data (DB4-0) across the bus.
58371da177e4SLinus Torvalds  *
58381da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
58391da177e4SLinus Torvalds 
FPT_scxferc(u32 p_port,unsigned char p_data)5840391e2f25SKhalid Aziz static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data)
58411da177e4SLinus Torvalds {
5842db038cf8SAlexey Dobriyan 	unsigned char curr_data, ret_data;
58431da177e4SLinus Torvalds 
58441da177e4SLinus Torvalds 	curr_data = p_data | BIT(7) | BIT(5);	/*Start with DB7 & DB5 asserted. */
58451da177e4SLinus Torvalds 
58461da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
58471da177e4SLinus Torvalds 
58481da177e4SLinus Torvalds 	curr_data &= ~BIT(7);
58491da177e4SLinus Torvalds 
58501da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
58511da177e4SLinus Torvalds 
585247b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(7));	/*Wait for DB7 to be released. */
58531da177e4SLinus Torvalds 	while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
58541da177e4SLinus Torvalds 
5855db038cf8SAlexey Dobriyan 	ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
58561da177e4SLinus Torvalds 
58571da177e4SLinus Torvalds 	curr_data |= BIT(6);
58581da177e4SLinus Torvalds 
58591da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
58601da177e4SLinus Torvalds 
58611da177e4SLinus Torvalds 	curr_data &= ~BIT(5);
58621da177e4SLinus Torvalds 
58631da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
58641da177e4SLinus Torvalds 
586547b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(5));	/*Wait for DB5 to be released. */
58661da177e4SLinus Torvalds 
58671da177e4SLinus Torvalds 	curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));	/*Release data bits */
58681da177e4SLinus Torvalds 	curr_data |= BIT(7);
58691da177e4SLinus Torvalds 
58701da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
58711da177e4SLinus Torvalds 
58721da177e4SLinus Torvalds 	curr_data &= ~BIT(6);
58731da177e4SLinus Torvalds 
58741da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
58751da177e4SLinus Torvalds 
587647b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(6));	/*Wait for DB6 to be released. */
58771da177e4SLinus Torvalds 
58785c1b85e2SAlexey Dobriyan 	return ret_data;
58791da177e4SLinus Torvalds }
58801da177e4SLinus Torvalds 
58811da177e4SLinus Torvalds /*---------------------------------------------------------------------
58821da177e4SLinus Torvalds  *
588347b5d69cSJames Bottomley   * Function: FPT_scsendi
58841da177e4SLinus Torvalds  *
58851da177e4SLinus Torvalds  * Description: Transfer our Identification string to determine if we
58861da177e4SLinus Torvalds  *              will be the dominant master.
58871da177e4SLinus Torvalds  *
58881da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
58891da177e4SLinus Torvalds 
FPT_scsendi(u32 p_port,unsigned char p_id_string[])5890391e2f25SKhalid Aziz static unsigned char FPT_scsendi(u32 p_port, unsigned char p_id_string[])
58911da177e4SLinus Torvalds {
5892db038cf8SAlexey Dobriyan 	unsigned char ret_data, byte_cnt, bit_cnt, defer;
58931da177e4SLinus Torvalds 
589447b5d69cSJames Bottomley  	defer = 0;
58951da177e4SLinus Torvalds 
58961da177e4SLinus Torvalds 	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
58971da177e4SLinus Torvalds 
58981da177e4SLinus Torvalds 		for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
58991da177e4SLinus Torvalds 
59001da177e4SLinus Torvalds 			if (defer)
590147b5d69cSJames Bottomley  				ret_data = FPT_scxferc(p_port, 00);
59021da177e4SLinus Torvalds 
59031da177e4SLinus Torvalds 			else if (p_id_string[byte_cnt] & bit_cnt)
59041da177e4SLinus Torvalds 
590547b5d69cSJames Bottomley  				ret_data = FPT_scxferc(p_port, 02);
59061da177e4SLinus Torvalds 
59071da177e4SLinus Torvalds 			else {
59081da177e4SLinus Torvalds 
590947b5d69cSJames Bottomley  				ret_data = FPT_scxferc(p_port, 01);
59101da177e4SLinus Torvalds 				if (ret_data & 02)
591147b5d69cSJames Bottomley  					defer = 1;
59121da177e4SLinus Torvalds 			}
59131da177e4SLinus Torvalds 
59141da177e4SLinus Torvalds 			if ((ret_data & 0x1C) == 0x10)
59155c1b85e2SAlexey Dobriyan 				return 0x00;	/*End of isolation stage, we won! */
59161da177e4SLinus Torvalds 
59171da177e4SLinus Torvalds 			if (ret_data & 0x1C)
59185c1b85e2SAlexey Dobriyan 				return 0xFF;
59191da177e4SLinus Torvalds 
59201da177e4SLinus Torvalds 			if ((defer) && (!(ret_data & 0x1F)))
59215c1b85e2SAlexey Dobriyan 				return 0x01;	/*End of isolation stage, we lost. */
59221da177e4SLinus Torvalds 
59231da177e4SLinus Torvalds 		}		/*bit loop */
59241da177e4SLinus Torvalds 
59251da177e4SLinus Torvalds 	}			/*byte loop */
59261da177e4SLinus Torvalds 
59271da177e4SLinus Torvalds 	if (defer)
59285c1b85e2SAlexey Dobriyan 		return 0x01;	/*We lost */
59291da177e4SLinus Torvalds 	else
59305c1b85e2SAlexey Dobriyan 		return 0;	/*We WON! Yeeessss! */
59311da177e4SLinus Torvalds }
59321da177e4SLinus Torvalds 
59331da177e4SLinus Torvalds /*---------------------------------------------------------------------
59341da177e4SLinus Torvalds  *
593547b5d69cSJames Bottomley   * Function: FPT_sciso
59361da177e4SLinus Torvalds  *
59371da177e4SLinus Torvalds  * Description: Transfer the Identification string.
59381da177e4SLinus Torvalds  *
59391da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
59401da177e4SLinus Torvalds 
FPT_sciso(u32 p_port,unsigned char p_id_string[])5941391e2f25SKhalid Aziz static unsigned char FPT_sciso(u32 p_port, unsigned char p_id_string[])
59421da177e4SLinus Torvalds {
5943db038cf8SAlexey Dobriyan 	unsigned char ret_data, the_data, byte_cnt, bit_cnt;
59441da177e4SLinus Torvalds 
59451da177e4SLinus Torvalds 	the_data = 0;
59461da177e4SLinus Torvalds 
59471da177e4SLinus Torvalds 	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
59481da177e4SLinus Torvalds 
59491da177e4SLinus Torvalds 		for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
59501da177e4SLinus Torvalds 
595147b5d69cSJames Bottomley  			ret_data = FPT_scxferc(p_port, 0);
59521da177e4SLinus Torvalds 
59531da177e4SLinus Torvalds 			if (ret_data & 0xFC)
59545c1b85e2SAlexey Dobriyan 				return 0xFF;
59551da177e4SLinus Torvalds 
59561da177e4SLinus Torvalds 			else {
59571da177e4SLinus Torvalds 
59581da177e4SLinus Torvalds 				the_data <<= 1;
59591da177e4SLinus Torvalds 				if (ret_data & BIT(1)) {
59601da177e4SLinus Torvalds 					the_data |= 1;
59611da177e4SLinus Torvalds 				}
59621da177e4SLinus Torvalds 			}
59631da177e4SLinus Torvalds 
59645c04a7b8SAlexey Dobriyan 			if ((ret_data & 0x1F) == 0) {
59651da177e4SLinus Torvalds /*
59661da177e4SLinus Torvalds 				if(bit_cnt != 0 || bit_cnt != 8)
59671da177e4SLinus Torvalds 				{
59681da177e4SLinus Torvalds 					byte_cnt = 0;
59691da177e4SLinus Torvalds 					bit_cnt = 0;
597047b5d69cSJames Bottomley  					FPT_scxferc(p_port, SYNC_PTRN);
597147b5d69cSJames Bottomley  					FPT_scxferc(p_port, ASSIGN_ID);
59721da177e4SLinus Torvalds 					continue;
59731da177e4SLinus Torvalds 				}
59741da177e4SLinus Torvalds */
59751da177e4SLinus Torvalds 				if (byte_cnt)
59765c1b85e2SAlexey Dobriyan 					return 0x00;
59771da177e4SLinus Torvalds 				else
59785c1b85e2SAlexey Dobriyan 					return 0xFF;
59791da177e4SLinus Torvalds 			}
59801da177e4SLinus Torvalds 
59811da177e4SLinus Torvalds 		}		/*bit loop */
59821da177e4SLinus Torvalds 
59831da177e4SLinus Torvalds 		p_id_string[byte_cnt] = the_data;
59841da177e4SLinus Torvalds 
59851da177e4SLinus Torvalds 	}			/*byte loop */
59861da177e4SLinus Torvalds 
59875c1b85e2SAlexey Dobriyan 	return 0;
59881da177e4SLinus Torvalds }
59891da177e4SLinus Torvalds 
59901da177e4SLinus Torvalds /*---------------------------------------------------------------------
59911da177e4SLinus Torvalds  *
599247b5d69cSJames Bottomley   * Function: FPT_scwirod
59931da177e4SLinus Torvalds  *
59941da177e4SLinus Torvalds  * Description: Sample the SCSI data bus making sure the signal has been
59951da177e4SLinus Torvalds  *              deasserted for the correct number of consecutive samples.
59961da177e4SLinus Torvalds  *
59971da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
59981da177e4SLinus Torvalds 
FPT_scwirod(u32 p_port,unsigned char p_data_bit)5999391e2f25SKhalid Aziz static void FPT_scwirod(u32 p_port, unsigned char p_data_bit)
60001da177e4SLinus Torvalds {
6001db038cf8SAlexey Dobriyan 	unsigned char i;
60021da177e4SLinus Torvalds 
60031da177e4SLinus Torvalds 	i = 0;
60041da177e4SLinus Torvalds 	while (i < MAX_SCSI_TAR) {
60051da177e4SLinus Torvalds 
60061da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
60071da177e4SLinus Torvalds 
60081da177e4SLinus Torvalds 			i = 0;
60091da177e4SLinus Torvalds 
60101da177e4SLinus Torvalds 		else
60111da177e4SLinus Torvalds 
60121da177e4SLinus Torvalds 			i++;
60131da177e4SLinus Torvalds 
60141da177e4SLinus Torvalds 	}
60151da177e4SLinus Torvalds }
60161da177e4SLinus Torvalds 
60171da177e4SLinus Torvalds /*---------------------------------------------------------------------
60181da177e4SLinus Torvalds  *
601947b5d69cSJames Bottomley   * Function: FPT_scwiros
60201da177e4SLinus Torvalds  *
60211da177e4SLinus Torvalds  * Description: Sample the SCSI Signal lines making sure the signal has been
60221da177e4SLinus Torvalds  *              deasserted for the correct number of consecutive samples.
60231da177e4SLinus Torvalds  *
60241da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
60251da177e4SLinus Torvalds 
FPT_scwiros(u32 p_port,unsigned char p_data_bit)6026391e2f25SKhalid Aziz static void FPT_scwiros(u32 p_port, unsigned char p_data_bit)
60271da177e4SLinus Torvalds {
6028db038cf8SAlexey Dobriyan 	unsigned char i;
60291da177e4SLinus Torvalds 
60301da177e4SLinus Torvalds 	i = 0;
60311da177e4SLinus Torvalds 	while (i < MAX_SCSI_TAR) {
60321da177e4SLinus Torvalds 
60331da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
60341da177e4SLinus Torvalds 
60351da177e4SLinus Torvalds 			i = 0;
60361da177e4SLinus Torvalds 
60371da177e4SLinus Torvalds 		else
60381da177e4SLinus Torvalds 
60391da177e4SLinus Torvalds 			i++;
60401da177e4SLinus Torvalds 
60411da177e4SLinus Torvalds 	}
60421da177e4SLinus Torvalds }
60431da177e4SLinus Torvalds 
60441da177e4SLinus Torvalds /*---------------------------------------------------------------------
60451da177e4SLinus Torvalds  *
604647b5d69cSJames Bottomley   * Function: FPT_scvalq
60471da177e4SLinus Torvalds  *
60481da177e4SLinus Torvalds  * Description: Make sure we received a valid data byte.
60491da177e4SLinus Torvalds  *
60501da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
60511da177e4SLinus Torvalds 
FPT_scvalq(unsigned char p_quintet)6052db038cf8SAlexey Dobriyan static unsigned char FPT_scvalq(unsigned char p_quintet)
60531da177e4SLinus Torvalds {
6054db038cf8SAlexey Dobriyan 	unsigned char count;
60551da177e4SLinus Torvalds 
60561da177e4SLinus Torvalds 	for (count = 1; count < 0x08; count <<= 1) {
60571da177e4SLinus Torvalds 		if (!(p_quintet & count))
60581da177e4SLinus Torvalds 			p_quintet -= 0x80;
60591da177e4SLinus Torvalds 	}
60601da177e4SLinus Torvalds 
60611da177e4SLinus Torvalds 	if (p_quintet & 0x18)
60625c1b85e2SAlexey Dobriyan 		return 0;
60631da177e4SLinus Torvalds 
60641da177e4SLinus Torvalds 	else
60655c1b85e2SAlexey Dobriyan 		return 1;
60661da177e4SLinus Torvalds }
60671da177e4SLinus Torvalds 
60681da177e4SLinus Torvalds /*---------------------------------------------------------------------
60691da177e4SLinus Torvalds  *
607047b5d69cSJames Bottomley   * Function: FPT_scsell
60711da177e4SLinus Torvalds  *
60721da177e4SLinus Torvalds  * Description: Select the specified device ID using a selection timeout
60731da177e4SLinus Torvalds  *              less than 4ms.  If somebody responds then it is a legacy
60741da177e4SLinus Torvalds  *              drive and this ID must be marked as such.
60751da177e4SLinus Torvalds  *
60761da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
60771da177e4SLinus Torvalds 
FPT_scsell(u32 p_port,unsigned char targ_id)6078391e2f25SKhalid Aziz static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id)
60791da177e4SLinus Torvalds {
6080d63a4cccSAlexey Dobriyan 	unsigned long i;
60811da177e4SLinus Torvalds 
60821da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl,
60831da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
60841da177e4SLinus Torvalds 
60851da177e4SLinus Torvalds 	ARAM_ACCESS(p_port);
60861da177e4SLinus Torvalds 
60875c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_addstat,
60885c04a7b8SAlexey Dobriyan 		   (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
60891da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
60901da177e4SLinus Torvalds 
60911da177e4SLinus Torvalds 	for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
60921da177e4SLinus Torvalds 		WRW_HARPOON(i, (MPM_OP + ACOMMAND));
60931da177e4SLinus Torvalds 	}
60941da177e4SLinus Torvalds 	WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
60951da177e4SLinus Torvalds 
60961da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat),
60971da177e4SLinus Torvalds 		    (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
60981da177e4SLinus Torvalds 
60991da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_select_id, targ_id);
61001da177e4SLinus Torvalds 
61011da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
61021da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
61031da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
61041da177e4SLinus Torvalds 
61051da177e4SLinus Torvalds 	while (!(RDW_HARPOON((p_port + hp_intstat)) &
61065c04a7b8SAlexey Dobriyan 		 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
61075c04a7b8SAlexey Dobriyan 	}
61081da177e4SLinus Torvalds 
61091da177e4SLinus Torvalds 	if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
611047b5d69cSJames Bottomley  		FPT_Wait(p_port, TO_250ms);
61111da177e4SLinus Torvalds 
61121da177e4SLinus Torvalds 	DISABLE_AUTO(p_port);
61131da177e4SLinus Torvalds 
61145c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_addstat,
61155c04a7b8SAlexey Dobriyan 		   (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
61161da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
61171da177e4SLinus Torvalds 
61181da177e4SLinus Torvalds 	SGRAM_ACCESS(p_port);
61191da177e4SLinus Torvalds 
61201da177e4SLinus Torvalds 	if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
61211da177e4SLinus Torvalds 
61221da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat),
61231da177e4SLinus Torvalds 			    (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
61241da177e4SLinus Torvalds 
61251da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_page_ctrl,
61265c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_page_ctrl) &
61275c04a7b8SAlexey Dobriyan 			    ~G_INT_DISABLE));
61281da177e4SLinus Torvalds 
61295c1b85e2SAlexey Dobriyan 		return 0;	/*No legacy device */
61301da177e4SLinus Torvalds 	}
61311da177e4SLinus Torvalds 
61321da177e4SLinus Torvalds 	else {
61331da177e4SLinus Torvalds 
61341da177e4SLinus Torvalds 		while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
61355c04a7b8SAlexey Dobriyan 			if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
61365c04a7b8SAlexey Dobriyan 				WR_HARPOON(p_port + hp_scsisig,
61375c04a7b8SAlexey Dobriyan 					   (SCSI_ACK + S_ILL_PH));
61381da177e4SLinus Torvalds 				ACCEPT_MSG(p_port);
61391da177e4SLinus Torvalds 			}
61401da177e4SLinus Torvalds 		}
61411da177e4SLinus Torvalds 
61421da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
61431da177e4SLinus Torvalds 
61441da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_page_ctrl,
61455c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_page_ctrl) &
61465c04a7b8SAlexey Dobriyan 			    ~G_INT_DISABLE));
61471da177e4SLinus Torvalds 
61485c1b85e2SAlexey Dobriyan 		return 1;	/*Found one of them oldies! */
61491da177e4SLinus Torvalds 	}
61501da177e4SLinus Torvalds }
61511da177e4SLinus Torvalds 
61521da177e4SLinus Torvalds /*---------------------------------------------------------------------
61531da177e4SLinus Torvalds  *
615447b5d69cSJames Bottomley   * Function: FPT_scwtsel
61551da177e4SLinus Torvalds  *
61561da177e4SLinus Torvalds  * Description: Wait to be selected by another SCAM initiator.
61571da177e4SLinus Torvalds  *
61581da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
61591da177e4SLinus Torvalds 
FPT_scwtsel(u32 p_port)6160391e2f25SKhalid Aziz static void FPT_scwtsel(u32 p_port)
61611da177e4SLinus Torvalds {
61625c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
61631da177e4SLinus Torvalds 	}
61645c04a7b8SAlexey Dobriyan }
61651da177e4SLinus Torvalds 
61661da177e4SLinus Torvalds /*---------------------------------------------------------------------
61671da177e4SLinus Torvalds  *
616847b5d69cSJames Bottomley   * Function: FPT_inisci
61691da177e4SLinus Torvalds  *
61701da177e4SLinus Torvalds  * Description: Setup the data Structure with the info from the EEPROM.
61711da177e4SLinus Torvalds  *
61721da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
61731da177e4SLinus Torvalds 
FPT_inisci(unsigned char p_card,u32 p_port,unsigned char p_our_id)6174391e2f25SKhalid Aziz static void FPT_inisci(unsigned char p_card, u32 p_port, unsigned char p_our_id)
61751da177e4SLinus Torvalds {
6176db038cf8SAlexey Dobriyan 	unsigned char i, k, max_id;
6177c823feebSAlexey Dobriyan 	unsigned short ee_data;
617868d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
61791da177e4SLinus Torvalds 
618047b5d69cSJames Bottomley  	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
61811da177e4SLinus Torvalds 
61821da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
61831da177e4SLinus Torvalds 		max_id = 0x08;
61841da177e4SLinus Torvalds 
61851da177e4SLinus Torvalds 	else
61861da177e4SLinus Torvalds 		max_id = 0x10;
61871da177e4SLinus Torvalds 
61881da177e4SLinus Torvalds 	if (pCurrNvRam) {
61891da177e4SLinus Torvalds 		for (i = 0; i < max_id; i++) {
61901da177e4SLinus Torvalds 
61911da177e4SLinus Torvalds 			for (k = 0; k < 4; k++)
61925c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k] =
61935c04a7b8SAlexey Dobriyan 				    pCurrNvRam->niScamTbl[i][k];
61941da177e4SLinus Torvalds 			for (k = 4; k < ID_STRING_LENGTH; k++)
61955c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k] =
61965c04a7b8SAlexey Dobriyan 				    (unsigned char)0x00;
61971da177e4SLinus Torvalds 
619847b5d69cSJames Bottomley  			if (FPT_scamInfo[i].id_string[0] == 0x00)
619947b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
62001da177e4SLinus Torvalds 			else
620147b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
62021da177e4SLinus Torvalds 
62031da177e4SLinus Torvalds 		}
62041da177e4SLinus Torvalds 	} else {
62055c04a7b8SAlexey Dobriyan 		for (i = 0; i < max_id; i++) {
62065c04a7b8SAlexey Dobriyan 			for (k = 0; k < ID_STRING_LENGTH; k += 2) {
62075c04a7b8SAlexey Dobriyan 				ee_data =
62085c04a7b8SAlexey Dobriyan 				    FPT_utilEERead(p_port,
62095c04a7b8SAlexey Dobriyan 						   (unsigned
62105c04a7b8SAlexey Dobriyan 						    short)((EE_SCAMBASE / 2) +
62115c04a7b8SAlexey Dobriyan 							   (unsigned short)(i *
62125c04a7b8SAlexey Dobriyan 									    ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
62135c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k] =
62145c04a7b8SAlexey Dobriyan 				    (unsigned char)ee_data;
62151da177e4SLinus Torvalds 				ee_data >>= 8;
62165c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k + 1] =
62175c04a7b8SAlexey Dobriyan 				    (unsigned char)ee_data;
62181da177e4SLinus Torvalds 			}
62191da177e4SLinus Torvalds 
622047b5d69cSJames Bottomley  			if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
622147b5d69cSJames Bottomley  			    (FPT_scamInfo[i].id_string[0] == 0xFF))
62221da177e4SLinus Torvalds 
622347b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
62241da177e4SLinus Torvalds 
62251da177e4SLinus Torvalds 			else
622647b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
62271da177e4SLinus Torvalds 
62281da177e4SLinus Torvalds 		}
62291da177e4SLinus Torvalds 	}
62301da177e4SLinus Torvalds 	for (k = 0; k < ID_STRING_LENGTH; k++)
623147b5d69cSJames Bottomley  		FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
62321da177e4SLinus Torvalds 
62331da177e4SLinus Torvalds }
62341da177e4SLinus Torvalds 
62351da177e4SLinus Torvalds /*---------------------------------------------------------------------
62361da177e4SLinus Torvalds  *
623747b5d69cSJames Bottomley   * Function: FPT_scmachid
62381da177e4SLinus Torvalds  *
62391da177e4SLinus Torvalds  * Description: Match the Device ID string with our values stored in
62401da177e4SLinus Torvalds  *              the EEPROM.
62411da177e4SLinus Torvalds  *
62421da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
62431da177e4SLinus Torvalds 
FPT_scmachid(unsigned char p_card,unsigned char p_id_string[])62445c04a7b8SAlexey Dobriyan static unsigned char FPT_scmachid(unsigned char p_card,
62455c04a7b8SAlexey Dobriyan 				  unsigned char p_id_string[])
62461da177e4SLinus Torvalds {
62471da177e4SLinus Torvalds 
6248db038cf8SAlexey Dobriyan 	unsigned char i, k, match;
62491da177e4SLinus Torvalds 
62501da177e4SLinus Torvalds 	for (i = 0; i < MAX_SCSI_TAR; i++) {
62511da177e4SLinus Torvalds 
625247b5d69cSJames Bottomley  		match = 1;
62531da177e4SLinus Torvalds 
62545c04a7b8SAlexey Dobriyan 		for (k = 0; k < ID_STRING_LENGTH; k++) {
625547b5d69cSJames Bottomley  			if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
625647b5d69cSJames Bottomley  				match = 0;
62571da177e4SLinus Torvalds 		}
62581da177e4SLinus Torvalds 
62595c04a7b8SAlexey Dobriyan 		if (match) {
626047b5d69cSJames Bottomley  			FPT_scamInfo[i].state = ID_ASSIGNED;
62615c1b85e2SAlexey Dobriyan 			return i;
62621da177e4SLinus Torvalds 		}
62631da177e4SLinus Torvalds 
62641da177e4SLinus Torvalds 	}
62651da177e4SLinus Torvalds 
62661da177e4SLinus Torvalds 	if (p_id_string[0] & BIT(5))
62671da177e4SLinus Torvalds 		i = 8;
62681da177e4SLinus Torvalds 	else
62691da177e4SLinus Torvalds 		i = MAX_SCSI_TAR;
62701da177e4SLinus Torvalds 
62715c04a7b8SAlexey Dobriyan 	if (((p_id_string[0] & 0x06) == 0x02)
62725c04a7b8SAlexey Dobriyan 	    || ((p_id_string[0] & 0x06) == 0x04))
6273db038cf8SAlexey Dobriyan 		match = p_id_string[1] & (unsigned char)0x1F;
62741da177e4SLinus Torvalds 	else
62751da177e4SLinus Torvalds 		match = 7;
62761da177e4SLinus Torvalds 
62775c04a7b8SAlexey Dobriyan 	while (i > 0) {
62781da177e4SLinus Torvalds 		i--;
62791da177e4SLinus Torvalds 
62805c04a7b8SAlexey Dobriyan 		if (FPT_scamInfo[match].state == ID_UNUSED) {
62815c04a7b8SAlexey Dobriyan 			for (k = 0; k < ID_STRING_LENGTH; k++) {
62825c04a7b8SAlexey Dobriyan 				FPT_scamInfo[match].id_string[k] =
62835c04a7b8SAlexey Dobriyan 				    p_id_string[k];
62841da177e4SLinus Torvalds 			}
62851da177e4SLinus Torvalds 
628647b5d69cSJames Bottomley  			FPT_scamInfo[match].state = ID_ASSIGNED;
62871da177e4SLinus Torvalds 
628847b5d69cSJames Bottomley  			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
62895c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].globalFlags |=
62905c04a7b8SAlexey Dobriyan 				    F_UPDATE_EEPROM;
62915c1b85e2SAlexey Dobriyan 			return match;
62921da177e4SLinus Torvalds 
62931da177e4SLinus Torvalds 		}
62941da177e4SLinus Torvalds 
62951da177e4SLinus Torvalds 		match--;
62961da177e4SLinus Torvalds 
62975c04a7b8SAlexey Dobriyan 		if (match == 0xFF) {
62981da177e4SLinus Torvalds 			if (p_id_string[0] & BIT(5))
62991da177e4SLinus Torvalds 				match = 7;
63001da177e4SLinus Torvalds 			else
63011da177e4SLinus Torvalds 				match = MAX_SCSI_TAR - 1;
63021da177e4SLinus Torvalds 		}
63031da177e4SLinus Torvalds 	}
63041da177e4SLinus Torvalds 
63055c04a7b8SAlexey Dobriyan 	if (p_id_string[0] & BIT(7)) {
63065c1b85e2SAlexey Dobriyan 		return CLR_PRIORITY;
63071da177e4SLinus Torvalds 	}
63081da177e4SLinus Torvalds 
63091da177e4SLinus Torvalds 	if (p_id_string[0] & BIT(5))
63101da177e4SLinus Torvalds 		i = 8;
63111da177e4SLinus Torvalds 	else
63121da177e4SLinus Torvalds 		i = MAX_SCSI_TAR;
63131da177e4SLinus Torvalds 
63145c04a7b8SAlexey Dobriyan 	if (((p_id_string[0] & 0x06) == 0x02)
63155c04a7b8SAlexey Dobriyan 	    || ((p_id_string[0] & 0x06) == 0x04))
6316db038cf8SAlexey Dobriyan 		match = p_id_string[1] & (unsigned char)0x1F;
63171da177e4SLinus Torvalds 	else
63181da177e4SLinus Torvalds 		match = 7;
63191da177e4SLinus Torvalds 
63205c04a7b8SAlexey Dobriyan 	while (i > 0) {
63211da177e4SLinus Torvalds 
63221da177e4SLinus Torvalds 		i--;
63231da177e4SLinus Torvalds 
63245c04a7b8SAlexey Dobriyan 		if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
63255c04a7b8SAlexey Dobriyan 			for (k = 0; k < ID_STRING_LENGTH; k++) {
63265c04a7b8SAlexey Dobriyan 				FPT_scamInfo[match].id_string[k] =
63275c04a7b8SAlexey Dobriyan 				    p_id_string[k];
63281da177e4SLinus Torvalds 			}
63291da177e4SLinus Torvalds 
633047b5d69cSJames Bottomley  			FPT_scamInfo[match].id_string[0] |= BIT(7);
633147b5d69cSJames Bottomley  			FPT_scamInfo[match].state = ID_ASSIGNED;
633247b5d69cSJames Bottomley  			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
63335c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].globalFlags |=
63345c04a7b8SAlexey Dobriyan 				    F_UPDATE_EEPROM;
63355c1b85e2SAlexey Dobriyan 			return match;
63361da177e4SLinus Torvalds 
63371da177e4SLinus Torvalds 		}
63381da177e4SLinus Torvalds 
63391da177e4SLinus Torvalds 		match--;
63401da177e4SLinus Torvalds 
63415c04a7b8SAlexey Dobriyan 		if (match == 0xFF) {
63421da177e4SLinus Torvalds 			if (p_id_string[0] & BIT(5))
63431da177e4SLinus Torvalds 				match = 7;
63441da177e4SLinus Torvalds 			else
63451da177e4SLinus Torvalds 				match = MAX_SCSI_TAR - 1;
63461da177e4SLinus Torvalds 		}
63471da177e4SLinus Torvalds 	}
63481da177e4SLinus Torvalds 
63495c1b85e2SAlexey Dobriyan 	return NO_ID_AVAIL;
63501da177e4SLinus Torvalds }
63511da177e4SLinus Torvalds 
63521da177e4SLinus Torvalds /*---------------------------------------------------------------------
63531da177e4SLinus Torvalds  *
635447b5d69cSJames Bottomley   * Function: FPT_scsavdi
63551da177e4SLinus Torvalds  *
63561da177e4SLinus Torvalds  * Description: Save off the device SCAM ID strings.
63571da177e4SLinus Torvalds  *
63581da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
63591da177e4SLinus Torvalds 
FPT_scsavdi(unsigned char p_card,u32 p_port)6360391e2f25SKhalid Aziz static void FPT_scsavdi(unsigned char p_card, u32 p_port)
63611da177e4SLinus Torvalds {
6362db038cf8SAlexey Dobriyan 	unsigned char i, k, max_id;
6363c823feebSAlexey Dobriyan 	unsigned short ee_data, sum_data;
63641da177e4SLinus Torvalds 
63651da177e4SLinus Torvalds 	sum_data = 0x0000;
63661da177e4SLinus Torvalds 
63675c04a7b8SAlexey Dobriyan 	for (i = 1; i < EE_SCAMBASE / 2; i++) {
636847b5d69cSJames Bottomley  		sum_data += FPT_utilEERead(p_port, i);
63691da177e4SLinus Torvalds 	}
63701da177e4SLinus Torvalds 
637147b5d69cSJames Bottomley  	FPT_utilEEWriteOnOff(p_port, 1);	/* Enable write access to the EEPROM */
63721da177e4SLinus Torvalds 
63731da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
63741da177e4SLinus Torvalds 		max_id = 0x08;
63751da177e4SLinus Torvalds 
63761da177e4SLinus Torvalds 	else
63771da177e4SLinus Torvalds 		max_id = 0x10;
63781da177e4SLinus Torvalds 
63795c04a7b8SAlexey Dobriyan 	for (i = 0; i < max_id; i++) {
63801da177e4SLinus Torvalds 
63815c04a7b8SAlexey Dobriyan 		for (k = 0; k < ID_STRING_LENGTH; k += 2) {
638247b5d69cSJames Bottomley  			ee_data = FPT_scamInfo[i].id_string[k + 1];
63831da177e4SLinus Torvalds 			ee_data <<= 8;
638447b5d69cSJames Bottomley  			ee_data |= FPT_scamInfo[i].id_string[k];
63851da177e4SLinus Torvalds 			sum_data += ee_data;
63865c04a7b8SAlexey Dobriyan 			FPT_utilEEWrite(p_port, ee_data,
63875c04a7b8SAlexey Dobriyan 					(unsigned short)((EE_SCAMBASE / 2) +
63885c04a7b8SAlexey Dobriyan 							 (unsigned short)(i *
63895c04a7b8SAlexey Dobriyan 									  ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
63901da177e4SLinus Torvalds 		}
63911da177e4SLinus Torvalds 	}
63921da177e4SLinus Torvalds 
639347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
639447b5d69cSJames Bottomley  	FPT_utilEEWriteOnOff(p_port, 0);	/* Turn off write access */
63951da177e4SLinus Torvalds }
63961da177e4SLinus Torvalds 
63971da177e4SLinus Torvalds /*---------------------------------------------------------------------
63981da177e4SLinus Torvalds  *
639947b5d69cSJames Bottomley   * Function: FPT_XbowInit
64001da177e4SLinus Torvalds  *
64011da177e4SLinus Torvalds  * Description: Setup the Xbow for normal operation.
64021da177e4SLinus Torvalds  *
64031da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
64041da177e4SLinus Torvalds 
FPT_XbowInit(u32 port,unsigned char ScamFlg)6405391e2f25SKhalid Aziz static void FPT_XbowInit(u32 port, unsigned char ScamFlg)
64061da177e4SLinus Torvalds {
6407db038cf8SAlexey Dobriyan 	unsigned char i;
64081da177e4SLinus Torvalds 
64091da177e4SLinus Torvalds 	i = RD_HARPOON(port + hp_page_ctrl);
6410db038cf8SAlexey Dobriyan 	WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
64111da177e4SLinus Torvalds 
64121da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsireset, 0x00);
64131da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
64141da177e4SLinus Torvalds 
64155c04a7b8SAlexey Dobriyan 	WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
64161da177e4SLinus Torvalds 					 FIFO_CLR));
64171da177e4SLinus Torvalds 
64181da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsireset, SCSI_INI);
64191da177e4SLinus Torvalds 
64201da177e4SLinus Torvalds 	WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
64211da177e4SLinus Torvalds 
64221da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, 0x00);	/*  Clear any signals we might */
64231da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
64241da177e4SLinus Torvalds 
64251da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
64261da177e4SLinus Torvalds 
642747b5d69cSJames Bottomley  	FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
64281da177e4SLinus Torvalds 	    BUS_FREE | XFER_CNT_0 | AUTO_INT;
64291da177e4SLinus Torvalds 
64301da177e4SLinus Torvalds 	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
643147b5d69cSJames Bottomley  		FPT_default_intena |= SCAM_SEL;
64321da177e4SLinus Torvalds 
643347b5d69cSJames Bottomley  	WRW_HARPOON((port + hp_intena), FPT_default_intena);
64341da177e4SLinus Torvalds 
64351da177e4SLinus Torvalds 	WR_HARPOON(port + hp_seltimeout, TO_290ms);
64361da177e4SLinus Torvalds 
64371da177e4SLinus Torvalds 	/* Turn on SCSI_MODE8 for narrow cards to fix the
64381da177e4SLinus Torvalds 	   strapping issue with the DUAL CHANNEL card */
64391da177e4SLinus Torvalds 	if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
64401da177e4SLinus Torvalds 		WR_HARPOON(port + hp_addstat, SCSI_MODE8);
64411da177e4SLinus Torvalds 
64421da177e4SLinus Torvalds 	WR_HARPOON(port + hp_page_ctrl, i);
64431da177e4SLinus Torvalds 
64441da177e4SLinus Torvalds }
64451da177e4SLinus Torvalds 
64461da177e4SLinus Torvalds /*---------------------------------------------------------------------
64471da177e4SLinus Torvalds  *
644847b5d69cSJames Bottomley   * Function: FPT_BusMasterInit
64491da177e4SLinus Torvalds  *
64501da177e4SLinus Torvalds  * Description: Initialize the BusMaster for normal operations.
64511da177e4SLinus Torvalds  *
64521da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
64531da177e4SLinus Torvalds 
FPT_BusMasterInit(u32 p_port)6454391e2f25SKhalid Aziz static void FPT_BusMasterInit(u32 p_port)
64551da177e4SLinus Torvalds {
64561da177e4SLinus Torvalds 
64571da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
64581da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
64591da177e4SLinus Torvalds 
64601da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
64611da177e4SLinus Torvalds 
64621da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
64631da177e4SLinus Torvalds 
64641da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
64651da177e4SLinus Torvalds 
64661da177e4SLinus Torvalds 	RD_HARPOON(p_port + hp_int_status);	/*Clear interrupts. */
64671da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
64681da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
64691da177e4SLinus Torvalds 					   ~SCATTER_EN));
64701da177e4SLinus Torvalds }
64711da177e4SLinus Torvalds 
64721da177e4SLinus Torvalds /*---------------------------------------------------------------------
64731da177e4SLinus Torvalds  *
647447b5d69cSJames Bottomley   * Function: FPT_DiagEEPROM
64751da177e4SLinus Torvalds  *
64761da177e4SLinus Torvalds  * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
64771da177e4SLinus Torvalds  *              necessary.
64781da177e4SLinus Torvalds  *
64791da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
64801da177e4SLinus Torvalds 
FPT_DiagEEPROM(u32 p_port)6481391e2f25SKhalid Aziz static void FPT_DiagEEPROM(u32 p_port)
64821da177e4SLinus Torvalds {
6483c823feebSAlexey Dobriyan 	unsigned short index, temp, max_wd_cnt;
64841da177e4SLinus Torvalds 
64851da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
64861da177e4SLinus Torvalds 		max_wd_cnt = EEPROM_WD_CNT;
64871da177e4SLinus Torvalds 	else
64881da177e4SLinus Torvalds 		max_wd_cnt = EEPROM_WD_CNT * 2;
64891da177e4SLinus Torvalds 
649047b5d69cSJames Bottomley  	temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
64911da177e4SLinus Torvalds 
64921da177e4SLinus Torvalds 	if (temp == 0x4641) {
64931da177e4SLinus Torvalds 
64941da177e4SLinus Torvalds 		for (index = 2; index < max_wd_cnt; index++) {
64951da177e4SLinus Torvalds 
649647b5d69cSJames Bottomley  			temp += FPT_utilEERead(p_port, index);
64971da177e4SLinus Torvalds 
64981da177e4SLinus Torvalds 		}
64991da177e4SLinus Torvalds 
650047b5d69cSJames Bottomley  		if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
65011da177e4SLinus Torvalds 
65021da177e4SLinus Torvalds 			return;	/*EEPROM is Okay so return now! */
65031da177e4SLinus Torvalds 		}
65041da177e4SLinus Torvalds 	}
65051da177e4SLinus Torvalds 
6506db038cf8SAlexey Dobriyan 	FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
65071da177e4SLinus Torvalds 
65081da177e4SLinus Torvalds 	for (index = 0; index < max_wd_cnt; index++) {
65091da177e4SLinus Torvalds 
651047b5d69cSJames Bottomley  		FPT_utilEEWrite(p_port, 0x0000, index);
65111da177e4SLinus Torvalds 	}
65121da177e4SLinus Torvalds 
65131da177e4SLinus Torvalds 	temp = 0;
65141da177e4SLinus Torvalds 
651547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
65161da177e4SLinus Torvalds 	temp += 0x4641;
651747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
65181da177e4SLinus Torvalds 	temp += 0x3920;
651947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
65201da177e4SLinus Torvalds 	temp += 0x3033;
652147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
65221da177e4SLinus Torvalds 	temp += 0x2020;
652347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
65241da177e4SLinus Torvalds 	temp += 0x70D3;
652547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
65261da177e4SLinus Torvalds 	temp += 0x0010;
652747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
65281da177e4SLinus Torvalds 	temp += 0x0003;
652947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
65301da177e4SLinus Torvalds 	temp += 0x0007;
65311da177e4SLinus Torvalds 
653247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
65331da177e4SLinus Torvalds 	temp += 0x0000;
653447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
65351da177e4SLinus Torvalds 	temp += 0x0000;
653647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
65371da177e4SLinus Torvalds 	temp += 0x0000;
65381da177e4SLinus Torvalds 
653947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
65401da177e4SLinus Torvalds 	temp += 0x4242;
654147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
65421da177e4SLinus Torvalds 	temp += 0x4242;
654347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
65441da177e4SLinus Torvalds 	temp += 0x4242;
654547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
65461da177e4SLinus Torvalds 	temp += 0x4242;
654747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
65481da177e4SLinus Torvalds 	temp += 0x4242;
654947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
65501da177e4SLinus Torvalds 	temp += 0x4242;
655147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
65521da177e4SLinus Torvalds 	temp += 0x4242;
655347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
65541da177e4SLinus Torvalds 	temp += 0x4242;
65551da177e4SLinus Torvalds 
655647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x6C46, 64 / 2);	/*PRODUCT ID */
65571da177e4SLinus Torvalds 	temp += 0x6C46;
655847b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x7361, 66 / 2);	/* FlashPoint LT   */
65591da177e4SLinus Torvalds 	temp += 0x7361;
656047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
65611da177e4SLinus Torvalds 	temp += 0x5068;
656247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
65631da177e4SLinus Torvalds 	temp += 0x696F;
656447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
65651da177e4SLinus Torvalds 	temp += 0x746E;
656647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
65671da177e4SLinus Torvalds 	temp += 0x4C20;
656847b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
65691da177e4SLinus Torvalds 	temp += 0x2054;
657047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
65711da177e4SLinus Torvalds 	temp += 0x2020;
65721da177e4SLinus Torvalds 
65731da177e4SLinus Torvalds 	index = ((EE_SCAMBASE / 2) + (7 * 16));
657447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
65751da177e4SLinus Torvalds 	temp += (0x0700 + TYPE_CODE0);
65761da177e4SLinus Torvalds 	index++;
657747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5542, index);	/*Vendor ID code */
65781da177e4SLinus Torvalds 	temp += 0x5542;		/* BUSLOGIC      */
65791da177e4SLinus Torvalds 	index++;
658047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4C53, index);
65811da177e4SLinus Torvalds 	temp += 0x4C53;
65821da177e4SLinus Torvalds 	index++;
658347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x474F, index);
65841da177e4SLinus Torvalds 	temp += 0x474F;
65851da177e4SLinus Torvalds 	index++;
658647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4349, index);
65871da177e4SLinus Torvalds 	temp += 0x4349;
65881da177e4SLinus Torvalds 	index++;
658947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5442, index);	/*Vendor unique code */
65901da177e4SLinus Torvalds 	temp += 0x5442;		/* BT- 930           */
65911da177e4SLinus Torvalds 	index++;
659247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x202D, index);
65931da177e4SLinus Torvalds 	temp += 0x202D;
65941da177e4SLinus Torvalds 	index++;
659547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3339, index);
65961da177e4SLinus Torvalds 	temp += 0x3339;
65971da177e4SLinus Torvalds 	index++;		/*Serial #          */
659847b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2030, index);	/* 01234567         */
65991da177e4SLinus Torvalds 	temp += 0x2030;
66001da177e4SLinus Torvalds 	index++;
660147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5453, index);
66021da177e4SLinus Torvalds 	temp += 0x5453;
66031da177e4SLinus Torvalds 	index++;
660447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5645, index);
66051da177e4SLinus Torvalds 	temp += 0x5645;
66061da177e4SLinus Torvalds 	index++;
660747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2045, index);
66081da177e4SLinus Torvalds 	temp += 0x2045;
66091da177e4SLinus Torvalds 	index++;
661047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x202F, index);
66111da177e4SLinus Torvalds 	temp += 0x202F;
66121da177e4SLinus Torvalds 	index++;
661347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4F4A, index);
66141da177e4SLinus Torvalds 	temp += 0x4F4A;
66151da177e4SLinus Torvalds 	index++;
661647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x204E, index);
66171da177e4SLinus Torvalds 	temp += 0x204E;
66181da177e4SLinus Torvalds 	index++;
661947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3539, index);
66201da177e4SLinus Torvalds 	temp += 0x3539;
66211da177e4SLinus Torvalds 
662247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
66231da177e4SLinus Torvalds 
6624db038cf8SAlexey Dobriyan 	FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
66251da177e4SLinus Torvalds 
66261da177e4SLinus Torvalds }
66271da177e4SLinus Torvalds 
66281da177e4SLinus Torvalds /*---------------------------------------------------------------------
66291da177e4SLinus Torvalds  *
66301da177e4SLinus Torvalds  * Function: Queue Search Select
66311da177e4SLinus Torvalds  *
66321da177e4SLinus Torvalds  * Description: Try to find a new command to execute.
66331da177e4SLinus Torvalds  *
66341da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
66351da177e4SLinus Torvalds 
FPT_queueSearchSelect(struct sccb_card * pCurrCard,unsigned char p_card)66365c04a7b8SAlexey Dobriyan static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
66375c04a7b8SAlexey Dobriyan 				  unsigned char p_card)
66381da177e4SLinus Torvalds {
6639db038cf8SAlexey Dobriyan 	unsigned char scan_ptr, lun;
6640f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
664169eb2ea4SAlexey Dobriyan 	struct sccb *pOldSccb;
66421da177e4SLinus Torvalds 
66431da177e4SLinus Torvalds 	scan_ptr = pCurrCard->scanIndex;
66445c04a7b8SAlexey Dobriyan 	do {
664547b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
66461da177e4SLinus Torvalds 		if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
66475c04a7b8SAlexey Dobriyan 		    ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
66485c04a7b8SAlexey Dobriyan 		     TAG_Q_TRYING)) {
66495c04a7b8SAlexey Dobriyan 			if (currTar_Info->TarSelQ_Cnt != 0) {
66501da177e4SLinus Torvalds 
66511da177e4SLinus Torvalds 				scan_ptr++;
66521da177e4SLinus Torvalds 				if (scan_ptr == MAX_SCSI_TAR)
66531da177e4SLinus Torvalds 					scan_ptr = 0;
66541da177e4SLinus Torvalds 
66555c04a7b8SAlexey Dobriyan 				for (lun = 0; lun < MAX_LUN; lun++) {
66565c04a7b8SAlexey Dobriyan 					if (currTar_Info->TarLUNBusy[lun] == 0) {
66571da177e4SLinus Torvalds 
66585c04a7b8SAlexey Dobriyan 						pCurrCard->currentSCCB =
66595c04a7b8SAlexey Dobriyan 						    currTar_Info->TarSelQ_Head;
66601da177e4SLinus Torvalds 						pOldSccb = NULL;
66611da177e4SLinus Torvalds 
66625c04a7b8SAlexey Dobriyan 						while ((pCurrCard->
66635c04a7b8SAlexey Dobriyan 							currentSCCB != NULL)
66645c04a7b8SAlexey Dobriyan 						       && (lun !=
66655c04a7b8SAlexey Dobriyan 							   pCurrCard->
66665c04a7b8SAlexey Dobriyan 							   currentSCCB->Lun)) {
66675c04a7b8SAlexey Dobriyan 							pOldSccb =
66685c04a7b8SAlexey Dobriyan 							    pCurrCard->
66695c04a7b8SAlexey Dobriyan 							    currentSCCB;
66705c04a7b8SAlexey Dobriyan 							pCurrCard->currentSCCB =
66715c04a7b8SAlexey Dobriyan 							    (struct sccb
66725c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
66735c04a7b8SAlexey Dobriyan 								currentSCCB)->
66741da177e4SLinus Torvalds 							    Sccb_forwardlink;
66751da177e4SLinus Torvalds 						}
66765c04a7b8SAlexey Dobriyan 						if (pCurrCard->currentSCCB ==
66775c04a7b8SAlexey Dobriyan 						    NULL)
66781da177e4SLinus Torvalds 							continue;
66795c04a7b8SAlexey Dobriyan 						if (pOldSccb != NULL) {
66805c04a7b8SAlexey Dobriyan 							pOldSccb->
66815c04a7b8SAlexey Dobriyan 							    Sccb_forwardlink =
66825c04a7b8SAlexey Dobriyan 							    (struct sccb
66835c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
66845c04a7b8SAlexey Dobriyan 								currentSCCB)->
66851da177e4SLinus Torvalds 							    Sccb_forwardlink;
66865c04a7b8SAlexey Dobriyan 							pOldSccb->
66875c04a7b8SAlexey Dobriyan 							    Sccb_backlink =
66885c04a7b8SAlexey Dobriyan 							    (struct sccb
66895c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
66905c04a7b8SAlexey Dobriyan 								currentSCCB)->
66911da177e4SLinus Torvalds 							    Sccb_backlink;
66925c04a7b8SAlexey Dobriyan 							currTar_Info->
66935c04a7b8SAlexey Dobriyan 							    TarSelQ_Cnt--;
66945c04a7b8SAlexey Dobriyan 						} else {
66955c04a7b8SAlexey Dobriyan 							currTar_Info->
66965c04a7b8SAlexey Dobriyan 							    TarSelQ_Head =
66975c04a7b8SAlexey Dobriyan 							    (struct sccb
66985c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
66995c04a7b8SAlexey Dobriyan 								currentSCCB)->
67005c04a7b8SAlexey Dobriyan 							    Sccb_forwardlink;
67011da177e4SLinus Torvalds 
67025c04a7b8SAlexey Dobriyan 							if (currTar_Info->
67035c04a7b8SAlexey Dobriyan 							    TarSelQ_Head ==
67045c04a7b8SAlexey Dobriyan 							    NULL) {
67055c04a7b8SAlexey Dobriyan 								currTar_Info->
67065c04a7b8SAlexey Dobriyan 								    TarSelQ_Tail
67075c04a7b8SAlexey Dobriyan 								    = NULL;
67085c04a7b8SAlexey Dobriyan 								currTar_Info->
67095c04a7b8SAlexey Dobriyan 								    TarSelQ_Cnt
67105c04a7b8SAlexey Dobriyan 								    = 0;
67115c04a7b8SAlexey Dobriyan 							} else {
67125c04a7b8SAlexey Dobriyan 								currTar_Info->
67135c04a7b8SAlexey Dobriyan 								    TarSelQ_Cnt--;
67145c04a7b8SAlexey Dobriyan 								currTar_Info->
67155c04a7b8SAlexey Dobriyan 								    TarSelQ_Head->
67165c04a7b8SAlexey Dobriyan 								    Sccb_backlink
67175c04a7b8SAlexey Dobriyan 								    =
67185c04a7b8SAlexey Dobriyan 								    (struct sccb
67195c04a7b8SAlexey Dobriyan 								     *)NULL;
67201da177e4SLinus Torvalds 							}
67211da177e4SLinus Torvalds 						}
67221da177e4SLinus Torvalds 						pCurrCard->scanIndex = scan_ptr;
67231da177e4SLinus Torvalds 
67245c04a7b8SAlexey Dobriyan 						pCurrCard->globalFlags |=
67255c04a7b8SAlexey Dobriyan 						    F_NEW_SCCB_CMD;
67261da177e4SLinus Torvalds 
67271da177e4SLinus Torvalds 						break;
67281da177e4SLinus Torvalds 					}
67291da177e4SLinus Torvalds 				}
67301da177e4SLinus Torvalds 			}
67311da177e4SLinus Torvalds 
67325c04a7b8SAlexey Dobriyan 			else {
67331da177e4SLinus Torvalds 				scan_ptr++;
67341da177e4SLinus Torvalds 				if (scan_ptr == MAX_SCSI_TAR) {
67351da177e4SLinus Torvalds 					scan_ptr = 0;
67361da177e4SLinus Torvalds 				}
67371da177e4SLinus Torvalds 			}
67381da177e4SLinus Torvalds 
67395c04a7b8SAlexey Dobriyan 		} else {
67401da177e4SLinus Torvalds 			if ((currTar_Info->TarSelQ_Cnt != 0) &&
67415c04a7b8SAlexey Dobriyan 			    (currTar_Info->TarLUNBusy[0] == 0)) {
67421da177e4SLinus Torvalds 
67435c04a7b8SAlexey Dobriyan 				pCurrCard->currentSCCB =
67445c04a7b8SAlexey Dobriyan 				    currTar_Info->TarSelQ_Head;
67451da177e4SLinus Torvalds 
67465c04a7b8SAlexey Dobriyan 				currTar_Info->TarSelQ_Head =
67475c04a7b8SAlexey Dobriyan 				    (struct sccb *)(pCurrCard->currentSCCB)->
67485c04a7b8SAlexey Dobriyan 				    Sccb_forwardlink;
67491da177e4SLinus Torvalds 
67505c04a7b8SAlexey Dobriyan 				if (currTar_Info->TarSelQ_Head == NULL) {
67511da177e4SLinus Torvalds 					currTar_Info->TarSelQ_Tail = NULL;
67521da177e4SLinus Torvalds 					currTar_Info->TarSelQ_Cnt = 0;
67535c04a7b8SAlexey Dobriyan 				} else {
67541da177e4SLinus Torvalds 					currTar_Info->TarSelQ_Cnt--;
67555c04a7b8SAlexey Dobriyan 					currTar_Info->TarSelQ_Head->
67565c04a7b8SAlexey Dobriyan 					    Sccb_backlink = (struct sccb *)NULL;
67571da177e4SLinus Torvalds 				}
67581da177e4SLinus Torvalds 
67591da177e4SLinus Torvalds 				scan_ptr++;
67601da177e4SLinus Torvalds 				if (scan_ptr == MAX_SCSI_TAR)
67611da177e4SLinus Torvalds 					scan_ptr = 0;
67621da177e4SLinus Torvalds 
67631da177e4SLinus Torvalds 				pCurrCard->scanIndex = scan_ptr;
67641da177e4SLinus Torvalds 
67651da177e4SLinus Torvalds 				pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
67661da177e4SLinus Torvalds 
67671da177e4SLinus Torvalds 				break;
67681da177e4SLinus Torvalds 			}
67691da177e4SLinus Torvalds 
67705c04a7b8SAlexey Dobriyan 			else {
67711da177e4SLinus Torvalds 				scan_ptr++;
67725c04a7b8SAlexey Dobriyan 				if (scan_ptr == MAX_SCSI_TAR) {
67731da177e4SLinus Torvalds 					scan_ptr = 0;
67741da177e4SLinus Torvalds 				}
67751da177e4SLinus Torvalds 			}
67761da177e4SLinus Torvalds 		}
67771da177e4SLinus Torvalds 	} while (scan_ptr != pCurrCard->scanIndex);
67781da177e4SLinus Torvalds }
67791da177e4SLinus Torvalds 
67801da177e4SLinus Torvalds /*---------------------------------------------------------------------
67811da177e4SLinus Torvalds  *
67821da177e4SLinus Torvalds  * Function: Queue Select Fail
67831da177e4SLinus Torvalds  *
67841da177e4SLinus Torvalds  * Description: Add the current SCCB to the head of the Queue.
67851da177e4SLinus Torvalds  *
67861da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
67871da177e4SLinus Torvalds 
FPT_queueSelectFail(struct sccb_card * pCurrCard,unsigned char p_card)67885c04a7b8SAlexey Dobriyan static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
67895c04a7b8SAlexey Dobriyan 				unsigned char p_card)
67901da177e4SLinus Torvalds {
6791db038cf8SAlexey Dobriyan 	unsigned char thisTarg;
6792f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
67931da177e4SLinus Torvalds 
67945c04a7b8SAlexey Dobriyan 	if (pCurrCard->currentSCCB != NULL) {
67955c04a7b8SAlexey Dobriyan 		thisTarg =
67965c04a7b8SAlexey Dobriyan 		    (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
67975c04a7b8SAlexey Dobriyan 				    TargID);
679847b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
67991da177e4SLinus Torvalds 
680069eb2ea4SAlexey Dobriyan 		pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
68011da177e4SLinus Torvalds 
68025c04a7b8SAlexey Dobriyan 		pCurrCard->currentSCCB->Sccb_forwardlink =
68035c04a7b8SAlexey Dobriyan 		    currTar_Info->TarSelQ_Head;
68041da177e4SLinus Torvalds 
68055c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarSelQ_Cnt == 0) {
68061da177e4SLinus Torvalds 			currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
68071da177e4SLinus Torvalds 		}
68081da177e4SLinus Torvalds 
68095c04a7b8SAlexey Dobriyan 		else {
68105c04a7b8SAlexey Dobriyan 			currTar_Info->TarSelQ_Head->Sccb_backlink =
68115c04a7b8SAlexey Dobriyan 			    pCurrCard->currentSCCB;
68121da177e4SLinus Torvalds 		}
68131da177e4SLinus Torvalds 
68141da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
68151da177e4SLinus Torvalds 
68161da177e4SLinus Torvalds 		pCurrCard->currentSCCB = NULL;
68171da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Cnt++;
68181da177e4SLinus Torvalds 	}
68191da177e4SLinus Torvalds }
68205c04a7b8SAlexey Dobriyan 
68211da177e4SLinus Torvalds /*---------------------------------------------------------------------
68221da177e4SLinus Torvalds  *
68231da177e4SLinus Torvalds  * Function: Queue Command Complete
68241da177e4SLinus Torvalds  *
68251da177e4SLinus Torvalds  * Description: Call the callback function with the current SCCB.
68261da177e4SLinus Torvalds  *
68271da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
68281da177e4SLinus Torvalds 
FPT_queueCmdComplete(struct sccb_card * pCurrCard,struct sccb * p_sccb,unsigned char p_card)68295c04a7b8SAlexey Dobriyan static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
68305c04a7b8SAlexey Dobriyan 				 struct sccb *p_sccb, unsigned char p_card)
68311da177e4SLinus Torvalds {
68321da177e4SLinus Torvalds 
6833db038cf8SAlexey Dobriyan 	unsigned char i, SCSIcmd;
68341da177e4SLinus Torvalds 	CALL_BK_FN callback;
6835f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
68361da177e4SLinus Torvalds 
68371da177e4SLinus Torvalds 	SCSIcmd = p_sccb->Cdb[0];
68381da177e4SLinus Torvalds 
68391da177e4SLinus Torvalds 	if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
68401da177e4SLinus Torvalds 
68415c04a7b8SAlexey Dobriyan 		if ((p_sccb->
68425c04a7b8SAlexey Dobriyan 		     ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
68435c04a7b8SAlexey Dobriyan 		    && (p_sccb->HostStatus == SCCB_COMPLETE)
6844a87afe28SHannes Reinecke 		    && (p_sccb->TargetStatus != SAM_STAT_CHECK_CONDITION))
68451da177e4SLinus Torvalds 
6846a87afe28SHannes Reinecke 			if ((SCSIcmd == READ_6) ||
6847a87afe28SHannes Reinecke 			    (SCSIcmd == WRITE_6) ||
6848a87afe28SHannes Reinecke 			    (SCSIcmd == READ_10) ||
6849a87afe28SHannes Reinecke 			    (SCSIcmd == WRITE_10) ||
6850a87afe28SHannes Reinecke 			    (SCSIcmd == WRITE_VERIFY) ||
6851a87afe28SHannes Reinecke 			    (SCSIcmd == START_STOP) ||
68521da177e4SLinus Torvalds 			    (pCurrCard->globalFlags & F_NO_FILTER)
68531da177e4SLinus Torvalds 			    )
68541da177e4SLinus Torvalds 				p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
68551da177e4SLinus Torvalds 	}
68561da177e4SLinus Torvalds 
68575c04a7b8SAlexey Dobriyan 	if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
68581da177e4SLinus Torvalds 		if (p_sccb->HostStatus || p_sccb->TargetStatus)
68591da177e4SLinus Torvalds 			p_sccb->SccbStatus = SCCB_ERROR;
68601da177e4SLinus Torvalds 		else
68611da177e4SLinus Torvalds 			p_sccb->SccbStatus = SCCB_SUCCESS;
68621da177e4SLinus Torvalds 	}
68631da177e4SLinus Torvalds 
68641da177e4SLinus Torvalds 	if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
68651da177e4SLinus Torvalds 
68661da177e4SLinus Torvalds 		p_sccb->CdbLength = p_sccb->Save_CdbLen;
68671da177e4SLinus Torvalds 		for (i = 0; i < 6; i++) {
68681da177e4SLinus Torvalds 			p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
68691da177e4SLinus Torvalds 		}
68701da177e4SLinus Torvalds 	}
68711da177e4SLinus Torvalds 
68721da177e4SLinus Torvalds 	if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
68731da177e4SLinus Torvalds 	    (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
68741da177e4SLinus Torvalds 
687547b5d69cSJames Bottomley  		FPT_utilUpdateResidual(p_sccb);
68761da177e4SLinus Torvalds 	}
68771da177e4SLinus Torvalds 
68781da177e4SLinus Torvalds 	pCurrCard->cmdCounter--;
68791da177e4SLinus Torvalds 	if (!pCurrCard->cmdCounter) {
68801da177e4SLinus Torvalds 
68811da177e4SLinus Torvalds 		if (pCurrCard->globalFlags & F_GREEN_PC) {
68825c04a7b8SAlexey Dobriyan 			WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
68835c04a7b8SAlexey Dobriyan 				   (PWR_DWN | CLKCTRL_DEFAULT));
68841da177e4SLinus Torvalds 			WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
68851da177e4SLinus Torvalds 		}
68861da177e4SLinus Torvalds 
68871da177e4SLinus Torvalds 		WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
68885c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
68895c04a7b8SAlexey Dobriyan 			    ~SCCB_MGR_ACTIVE));
68901da177e4SLinus Torvalds 
68911da177e4SLinus Torvalds 	}
68921da177e4SLinus Torvalds 
68935c04a7b8SAlexey Dobriyan 	if (pCurrCard->discQCount != 0) {
689447b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
68951da177e4SLinus Torvalds 		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
68965c04a7b8SAlexey Dobriyan 		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
68975c04a7b8SAlexey Dobriyan 		      TAG_Q_TRYING))) {
68981da177e4SLinus Torvalds 			pCurrCard->discQCount--;
68995c04a7b8SAlexey Dobriyan 			pCurrCard->discQ_Tbl[currTar_Info->
69005c04a7b8SAlexey Dobriyan 					     LunDiscQ_Idx[p_sccb->Lun]] = NULL;
69015c04a7b8SAlexey Dobriyan 		} else {
69025c04a7b8SAlexey Dobriyan 			if (p_sccb->Sccb_tag) {
69031da177e4SLinus Torvalds 				pCurrCard->discQCount--;
69041da177e4SLinus Torvalds 				pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
69055c04a7b8SAlexey Dobriyan 			} else {
69061da177e4SLinus Torvalds 				pCurrCard->discQCount--;
69075c04a7b8SAlexey Dobriyan 				pCurrCard->discQ_Tbl[currTar_Info->
69085c04a7b8SAlexey Dobriyan 						     LunDiscQ_Idx[0]] = NULL;
69091da177e4SLinus Torvalds 			}
69101da177e4SLinus Torvalds 		}
69111da177e4SLinus Torvalds 
69121da177e4SLinus Torvalds 	}
69131da177e4SLinus Torvalds 
69141da177e4SLinus Torvalds 	callback = (CALL_BK_FN) p_sccb->SccbCallback;
69151da177e4SLinus Torvalds 	callback(p_sccb);
69161da177e4SLinus Torvalds 	pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
69171da177e4SLinus Torvalds 	pCurrCard->currentSCCB = NULL;
69181da177e4SLinus Torvalds }
69191da177e4SLinus Torvalds 
69201da177e4SLinus Torvalds /*---------------------------------------------------------------------
69211da177e4SLinus Torvalds  *
69221da177e4SLinus Torvalds  * Function: Queue Disconnect
69231da177e4SLinus Torvalds  *
69241da177e4SLinus Torvalds  * Description: Add SCCB to our disconnect array.
69251da177e4SLinus Torvalds  *
69261da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
FPT_queueDisconnect(struct sccb * p_sccb,unsigned char p_card)692769eb2ea4SAlexey Dobriyan static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
69281da177e4SLinus Torvalds {
6929f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
69301da177e4SLinus Torvalds 
693147b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
69321da177e4SLinus Torvalds 
693347b5d69cSJames Bottomley  	if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
69345c04a7b8SAlexey Dobriyan 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
69355c04a7b8SAlexey Dobriyan 		FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
69365c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[p_sccb->Lun]] =
69375c04a7b8SAlexey Dobriyan 		    p_sccb;
69385c04a7b8SAlexey Dobriyan 	} else {
69395c04a7b8SAlexey Dobriyan 		if (p_sccb->Sccb_tag) {
69405c04a7b8SAlexey Dobriyan 			FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
69415c04a7b8SAlexey Dobriyan 			    p_sccb;
69425c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
69435c04a7b8SAlexey Dobriyan 			    0;
694447b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
69455c04a7b8SAlexey Dobriyan 		} else {
69465c04a7b8SAlexey Dobriyan 			FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
69475c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = p_sccb;
69481da177e4SLinus Torvalds 		}
69491da177e4SLinus Torvalds 	}
695047b5d69cSJames Bottomley  	FPT_BL_Card[p_card].currentSCCB = NULL;
69511da177e4SLinus Torvalds }
69521da177e4SLinus Torvalds 
69531da177e4SLinus Torvalds /*---------------------------------------------------------------------
69541da177e4SLinus Torvalds  *
69551da177e4SLinus Torvalds  * Function: Queue Flush SCCB
69561da177e4SLinus Torvalds  *
69571da177e4SLinus Torvalds  * Description: Flush all SCCB's back to the host driver for this target.
69581da177e4SLinus Torvalds  *
69591da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
69601da177e4SLinus Torvalds 
FPT_queueFlushSccb(unsigned char p_card,unsigned char error_code)6961db038cf8SAlexey Dobriyan static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
69621da177e4SLinus Torvalds {
6963db038cf8SAlexey Dobriyan 	unsigned char qtag, thisTarg;
696469eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
6965f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
69661da177e4SLinus Torvalds 
696747b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
69685c04a7b8SAlexey Dobriyan 	if (currSCCB != NULL) {
6969db038cf8SAlexey Dobriyan 		thisTarg = (unsigned char)currSCCB->TargID;
697047b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
69711da177e4SLinus Torvalds 
69721da177e4SLinus Torvalds 		for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
69731da177e4SLinus Torvalds 
697447b5d69cSJames Bottomley  			if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
69755c04a7b8SAlexey Dobriyan 			    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
69765c04a7b8SAlexey Dobriyan 			     thisTarg)) {
69771da177e4SLinus Torvalds 
69785c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].discQ_Tbl[qtag]->
69795c04a7b8SAlexey Dobriyan 				    HostStatus = (unsigned char)error_code;
69801da177e4SLinus Torvalds 
69815c04a7b8SAlexey Dobriyan 				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
69825c04a7b8SAlexey Dobriyan 						     FPT_BL_Card[p_card].
69835c04a7b8SAlexey Dobriyan 						     discQ_Tbl[qtag], p_card);
69841da177e4SLinus Torvalds 
698547b5d69cSJames Bottomley  				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
69861da177e4SLinus Torvalds 				currTar_Info->TarTagQ_Cnt--;
69871da177e4SLinus Torvalds 
69881da177e4SLinus Torvalds 			}
69891da177e4SLinus Torvalds 		}
69901da177e4SLinus Torvalds 	}
69911da177e4SLinus Torvalds 
69921da177e4SLinus Torvalds }
69931da177e4SLinus Torvalds 
69941da177e4SLinus Torvalds /*---------------------------------------------------------------------
69951da177e4SLinus Torvalds  *
69961da177e4SLinus Torvalds  * Function: Queue Flush Target SCCB
69971da177e4SLinus Torvalds  *
69981da177e4SLinus Torvalds  * Description: Flush all SCCB's back to the host driver for this target.
69991da177e4SLinus Torvalds  *
70001da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
70011da177e4SLinus Torvalds 
FPT_queueFlushTargSccb(unsigned char p_card,unsigned char thisTarg,unsigned char error_code)7002db038cf8SAlexey Dobriyan static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7003db038cf8SAlexey Dobriyan 				   unsigned char error_code)
70041da177e4SLinus Torvalds {
7005db038cf8SAlexey Dobriyan 	unsigned char qtag;
7006f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
70071da177e4SLinus Torvalds 
700847b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
70091da177e4SLinus Torvalds 
70101da177e4SLinus Torvalds 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
70111da177e4SLinus Torvalds 
701247b5d69cSJames Bottomley  		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
70135c04a7b8SAlexey Dobriyan 		    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
70141da177e4SLinus Torvalds 
70155c04a7b8SAlexey Dobriyan 			FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
70165c04a7b8SAlexey Dobriyan 			    (unsigned char)error_code;
70171da177e4SLinus Torvalds 
70185c04a7b8SAlexey Dobriyan 			FPT_queueCmdComplete(&FPT_BL_Card[p_card],
70195c04a7b8SAlexey Dobriyan 					     FPT_BL_Card[p_card].
70205c04a7b8SAlexey Dobriyan 					     discQ_Tbl[qtag], p_card);
70211da177e4SLinus Torvalds 
702247b5d69cSJames Bottomley  			FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
70231da177e4SLinus Torvalds 			currTar_Info->TarTagQ_Cnt--;
70241da177e4SLinus Torvalds 
70251da177e4SLinus Torvalds 		}
70261da177e4SLinus Torvalds 	}
70271da177e4SLinus Torvalds 
70281da177e4SLinus Torvalds }
70291da177e4SLinus Torvalds 
FPT_queueAddSccb(struct sccb * p_SCCB,unsigned char p_card)703069eb2ea4SAlexey Dobriyan static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
70311da177e4SLinus Torvalds {
7032f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
703347b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
70341da177e4SLinus Torvalds 
70351da177e4SLinus Torvalds 	p_SCCB->Sccb_forwardlink = NULL;
70361da177e4SLinus Torvalds 
70371da177e4SLinus Torvalds 	p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
70381da177e4SLinus Torvalds 
70391da177e4SLinus Torvalds 	if (currTar_Info->TarSelQ_Cnt == 0) {
70401da177e4SLinus Torvalds 
70411da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Head = p_SCCB;
70421da177e4SLinus Torvalds 	}
70431da177e4SLinus Torvalds 
70441da177e4SLinus Torvalds 	else {
70451da177e4SLinus Torvalds 
70461da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
70471da177e4SLinus Torvalds 	}
70481da177e4SLinus Torvalds 
70491da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Tail = p_SCCB;
70501da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Cnt++;
70511da177e4SLinus Torvalds }
70521da177e4SLinus Torvalds 
70531da177e4SLinus Torvalds /*---------------------------------------------------------------------
70541da177e4SLinus Torvalds  *
70551da177e4SLinus Torvalds  * Function: Queue Find SCCB
70561da177e4SLinus Torvalds  *
70571da177e4SLinus Torvalds  * Description: Search the target select Queue for this SCCB, and
70581da177e4SLinus Torvalds  *              remove it if found.
70591da177e4SLinus Torvalds  *
70601da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
70611da177e4SLinus Torvalds 
FPT_queueFindSccb(struct sccb * p_SCCB,unsigned char p_card)70625c04a7b8SAlexey Dobriyan static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
70635c04a7b8SAlexey Dobriyan 				       unsigned char p_card)
70641da177e4SLinus Torvalds {
706569eb2ea4SAlexey Dobriyan 	struct sccb *q_ptr;
7066f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
70671da177e4SLinus Torvalds 
706847b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
70691da177e4SLinus Torvalds 
70701da177e4SLinus Torvalds 	q_ptr = currTar_Info->TarSelQ_Head;
70711da177e4SLinus Torvalds 
70721da177e4SLinus Torvalds 	while (q_ptr != NULL) {
70731da177e4SLinus Torvalds 
70741da177e4SLinus Torvalds 		if (q_ptr == p_SCCB) {
70751da177e4SLinus Torvalds 
70761da177e4SLinus Torvalds 			if (currTar_Info->TarSelQ_Head == q_ptr) {
70771da177e4SLinus Torvalds 
70785c04a7b8SAlexey Dobriyan 				currTar_Info->TarSelQ_Head =
70795c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_forwardlink;
70801da177e4SLinus Torvalds 			}
70811da177e4SLinus Torvalds 
70821da177e4SLinus Torvalds 			if (currTar_Info->TarSelQ_Tail == q_ptr) {
70831da177e4SLinus Torvalds 
70845c04a7b8SAlexey Dobriyan 				currTar_Info->TarSelQ_Tail =
70855c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_backlink;
70861da177e4SLinus Torvalds 			}
70871da177e4SLinus Torvalds 
70881da177e4SLinus Torvalds 			if (q_ptr->Sccb_forwardlink != NULL) {
70895c04a7b8SAlexey Dobriyan 				q_ptr->Sccb_forwardlink->Sccb_backlink =
70905c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_backlink;
70911da177e4SLinus Torvalds 			}
70921da177e4SLinus Torvalds 
70931da177e4SLinus Torvalds 			if (q_ptr->Sccb_backlink != NULL) {
70945c04a7b8SAlexey Dobriyan 				q_ptr->Sccb_backlink->Sccb_forwardlink =
70955c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_forwardlink;
70961da177e4SLinus Torvalds 			}
70971da177e4SLinus Torvalds 
70981da177e4SLinus Torvalds 			currTar_Info->TarSelQ_Cnt--;
70991da177e4SLinus Torvalds 
71005c1b85e2SAlexey Dobriyan 			return 1;
71011da177e4SLinus Torvalds 		}
71021da177e4SLinus Torvalds 
71031da177e4SLinus Torvalds 		else {
71041da177e4SLinus Torvalds 			q_ptr = q_ptr->Sccb_forwardlink;
71051da177e4SLinus Torvalds 		}
71061da177e4SLinus Torvalds 	}
71071da177e4SLinus Torvalds 
71085c1b85e2SAlexey Dobriyan 	return 0;
71091da177e4SLinus Torvalds 
71101da177e4SLinus Torvalds }
71111da177e4SLinus Torvalds 
71121da177e4SLinus Torvalds /*---------------------------------------------------------------------
71131da177e4SLinus Torvalds  *
71141da177e4SLinus Torvalds  * Function: Utility Update Residual Count
71151da177e4SLinus Torvalds  *
71161da177e4SLinus Torvalds  * Description: Update the XferCnt to the remaining byte count.
71171da177e4SLinus Torvalds  *              If we transferred all the data then just write zero.
71181da177e4SLinus Torvalds  *              If Non-SG transfer then report Total Cnt - Actual Transfer
71191da177e4SLinus Torvalds  *              Cnt.  For SG transfers add the count fields of all
71201da177e4SLinus Torvalds  *              remaining SG elements, as well as any partial remaining
71211da177e4SLinus Torvalds  *              element.
71221da177e4SLinus Torvalds  *
71231da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
71241da177e4SLinus Torvalds 
FPT_utilUpdateResidual(struct sccb * p_SCCB)712569eb2ea4SAlexey Dobriyan static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
71261da177e4SLinus Torvalds {
7127d63a4cccSAlexey Dobriyan 	unsigned long partial_cnt;
7128ce793215SAlexey Dobriyan 	unsigned int sg_index;
7129391e2f25SKhalid Aziz 	struct blogic_sg_seg *segp;
71301da177e4SLinus Torvalds 
71311da177e4SLinus Torvalds 	if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
71321da177e4SLinus Torvalds 
71331da177e4SLinus Torvalds 		p_SCCB->DataLength = 0x0000;
71341da177e4SLinus Torvalds 	}
71351da177e4SLinus Torvalds 
71361da177e4SLinus Torvalds 	else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
71371da177e4SLinus Torvalds 
71381da177e4SLinus Torvalds 		partial_cnt = 0x0000;
71391da177e4SLinus Torvalds 
71401da177e4SLinus Torvalds 		sg_index = p_SCCB->Sccb_sgseg;
71411da177e4SLinus Torvalds 
71421da177e4SLinus Torvalds 
71431da177e4SLinus Torvalds 		if (p_SCCB->Sccb_SGoffset) {
71441da177e4SLinus Torvalds 
71451da177e4SLinus Torvalds 			partial_cnt = p_SCCB->Sccb_SGoffset;
71461da177e4SLinus Torvalds 			sg_index++;
71471da177e4SLinus Torvalds 		}
71481da177e4SLinus Torvalds 
71495c04a7b8SAlexey Dobriyan 		while (((unsigned long)sg_index *
71505c04a7b8SAlexey Dobriyan 			(unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
7151391e2f25SKhalid Aziz 			segp = (struct blogic_sg_seg *)(p_SCCB->DataPointer) +
7152391e2f25SKhalid Aziz 					(sg_index * 2);
7153391e2f25SKhalid Aziz 			partial_cnt += segp->segbytes;
71541da177e4SLinus Torvalds 			sg_index++;
71551da177e4SLinus Torvalds 		}
71561da177e4SLinus Torvalds 
71571da177e4SLinus Torvalds 		p_SCCB->DataLength = partial_cnt;
71581da177e4SLinus Torvalds 	}
71591da177e4SLinus Torvalds 
71601da177e4SLinus Torvalds 	else {
71611da177e4SLinus Torvalds 
71621da177e4SLinus Torvalds 		p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
71631da177e4SLinus Torvalds 	}
71641da177e4SLinus Torvalds }
71651da177e4SLinus Torvalds 
71661da177e4SLinus Torvalds /*---------------------------------------------------------------------
71671da177e4SLinus Torvalds  *
71681da177e4SLinus Torvalds  * Function: Wait 1 Second
71691da177e4SLinus Torvalds  *
71701da177e4SLinus Torvalds  * Description: Wait for 1 second.
71711da177e4SLinus Torvalds  *
71721da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
71731da177e4SLinus Torvalds 
FPT_Wait1Second(u32 p_port)7174391e2f25SKhalid Aziz static void FPT_Wait1Second(u32 p_port)
71751da177e4SLinus Torvalds {
7176db038cf8SAlexey Dobriyan 	unsigned char i;
71771da177e4SLinus Torvalds 
71781da177e4SLinus Torvalds 	for (i = 0; i < 4; i++) {
71791da177e4SLinus Torvalds 
718047b5d69cSJames Bottomley  		FPT_Wait(p_port, TO_250ms);
71811da177e4SLinus Torvalds 
71821da177e4SLinus Torvalds 		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
71831da177e4SLinus Torvalds 			break;
71841da177e4SLinus Torvalds 
71851da177e4SLinus Torvalds 		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
71861da177e4SLinus Torvalds 			break;
71871da177e4SLinus Torvalds 	}
71881da177e4SLinus Torvalds }
71891da177e4SLinus Torvalds 
71901da177e4SLinus Torvalds /*---------------------------------------------------------------------
71911da177e4SLinus Torvalds  *
719247b5d69cSJames Bottomley   * Function: FPT_Wait
71931da177e4SLinus Torvalds  *
71941da177e4SLinus Torvalds  * Description: Wait the desired delay.
71951da177e4SLinus Torvalds  *
71961da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
71971da177e4SLinus Torvalds 
FPT_Wait(u32 p_port,unsigned char p_delay)7198391e2f25SKhalid Aziz static void FPT_Wait(u32 p_port, unsigned char p_delay)
71991da177e4SLinus Torvalds {
7200db038cf8SAlexey Dobriyan 	unsigned char old_timer;
7201db038cf8SAlexey Dobriyan 	unsigned char green_flag;
72021da177e4SLinus Torvalds 
72031da177e4SLinus Torvalds 	old_timer = RD_HARPOON(p_port + hp_seltimeout);
72041da177e4SLinus Torvalds 
72051da177e4SLinus Torvalds 	green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
72061da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
72071da177e4SLinus Torvalds 
72081da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, p_delay);
72091da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
721047b5d69cSJames Bottomley  	WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
72111da177e4SLinus Torvalds 
72121da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0,
72131da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
72141da177e4SLinus Torvalds 
72151da177e4SLinus Torvalds 	while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
72161da177e4SLinus Torvalds 
72171da177e4SLinus Torvalds 		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
72181da177e4SLinus Torvalds 			break;
72191da177e4SLinus Torvalds 
72201da177e4SLinus Torvalds 		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
72211da177e4SLinus Torvalds 			break;
72221da177e4SLinus Torvalds 	}
72231da177e4SLinus Torvalds 
72241da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0,
72251da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
72261da177e4SLinus Torvalds 
72271da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
722847b5d69cSJames Bottomley  	WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
72291da177e4SLinus Torvalds 
72301da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
72311da177e4SLinus Torvalds 
72321da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, old_timer);
72331da177e4SLinus Torvalds }
72341da177e4SLinus Torvalds 
72351da177e4SLinus Torvalds /*---------------------------------------------------------------------
72361da177e4SLinus Torvalds  *
72371da177e4SLinus Torvalds  * Function: Enable/Disable Write to EEPROM
72381da177e4SLinus Torvalds  *
72391da177e4SLinus Torvalds  * Description: The EEPROM must first be enabled for writes
72401da177e4SLinus Torvalds  *              A total of 9 clocks are needed.
72411da177e4SLinus Torvalds  *
72421da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
72431da177e4SLinus Torvalds 
FPT_utilEEWriteOnOff(u32 p_port,unsigned char p_mode)7244391e2f25SKhalid Aziz static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode)
72451da177e4SLinus Torvalds {
7246db038cf8SAlexey Dobriyan 	unsigned char ee_value;
72471da177e4SLinus Torvalds 
72485c04a7b8SAlexey Dobriyan 	ee_value =
72495c04a7b8SAlexey Dobriyan 	    (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
72505c04a7b8SAlexey Dobriyan 			    (EXT_ARB_ACK | SCSI_TERM_ENA_H));
72511da177e4SLinus Torvalds 
72521da177e4SLinus Torvalds 	if (p_mode)
72531da177e4SLinus Torvalds 
725447b5d69cSJames Bottomley  		FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
72551da177e4SLinus Torvalds 
72561da177e4SLinus Torvalds 	else
72571da177e4SLinus Torvalds 
725847b5d69cSJames Bottomley  		FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
72591da177e4SLinus Torvalds 
72601da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
72611da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
72621da177e4SLinus Torvalds }
72631da177e4SLinus Torvalds 
72641da177e4SLinus Torvalds /*---------------------------------------------------------------------
72651da177e4SLinus Torvalds  *
72661da177e4SLinus Torvalds  * Function: Write EEPROM
72671da177e4SLinus Torvalds  *
72681da177e4SLinus Torvalds  * Description: Write a word to the EEPROM at the specified
72691da177e4SLinus Torvalds  *              address.
72701da177e4SLinus Torvalds  *
72711da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
72721da177e4SLinus Torvalds 
FPT_utilEEWrite(u32 p_port,unsigned short ee_data,unsigned short ee_addr)7273391e2f25SKhalid Aziz static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
72745c04a7b8SAlexey Dobriyan 			    unsigned short ee_addr)
72751da177e4SLinus Torvalds {
72761da177e4SLinus Torvalds 
7277db038cf8SAlexey Dobriyan 	unsigned char ee_value;
7278c823feebSAlexey Dobriyan 	unsigned short i;
72791da177e4SLinus Torvalds 
72805c04a7b8SAlexey Dobriyan 	ee_value =
72815c04a7b8SAlexey Dobriyan 	    (unsigned
72825c04a7b8SAlexey Dobriyan 	     char)((RD_HARPOON(p_port + hp_ee_ctrl) &
72835c04a7b8SAlexey Dobriyan 		    (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
72841da177e4SLinus Torvalds 
728547b5d69cSJames Bottomley  	FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
72861da177e4SLinus Torvalds 
72871da177e4SLinus Torvalds 	ee_value |= (SEE_MS + SEE_CS);
72881da177e4SLinus Torvalds 
72891da177e4SLinus Torvalds 	for (i = 0x8000; i != 0; i >>= 1) {
72901da177e4SLinus Torvalds 
72911da177e4SLinus Torvalds 		if (i & ee_data)
72921da177e4SLinus Torvalds 			ee_value |= SEE_DO;
72931da177e4SLinus Torvalds 		else
72941da177e4SLinus Torvalds 			ee_value &= ~SEE_DO;
72951da177e4SLinus Torvalds 
72961da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
72971da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
72981da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
72991da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73001da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73011da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
73021da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73031da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73041da177e4SLinus Torvalds 	}
73051da177e4SLinus Torvalds 	ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
73061da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
73071da177e4SLinus Torvalds 
730847b5d69cSJames Bottomley  	FPT_Wait(p_port, TO_10ms);
73091da177e4SLinus Torvalds 
73101da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS));	/* Set CS to EEPROM */
73111da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/* Turn off CS */
73121da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/* Turn off Master Select */
73131da177e4SLinus Torvalds }
73141da177e4SLinus Torvalds 
73151da177e4SLinus Torvalds /*---------------------------------------------------------------------
73161da177e4SLinus Torvalds  *
73171da177e4SLinus Torvalds  * Function: Read EEPROM
73181da177e4SLinus Torvalds  *
73191da177e4SLinus Torvalds  * Description: Read a word from the EEPROM at the desired
73201da177e4SLinus Torvalds  *              address.
73211da177e4SLinus Torvalds  *
73221da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
73231da177e4SLinus Torvalds 
FPT_utilEERead(u32 p_port,unsigned short ee_addr)7324391e2f25SKhalid Aziz static unsigned short FPT_utilEERead(u32 p_port,
73255c04a7b8SAlexey Dobriyan 				     unsigned short ee_addr)
73261da177e4SLinus Torvalds {
7327c823feebSAlexey Dobriyan 	unsigned short i, ee_data1, ee_data2;
73281da177e4SLinus Torvalds 
73291da177e4SLinus Torvalds 	i = 0;
733047b5d69cSJames Bottomley  	ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
73315c04a7b8SAlexey Dobriyan 	do {
733247b5d69cSJames Bottomley  		ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
73331da177e4SLinus Torvalds 
73341da177e4SLinus Torvalds 		if (ee_data1 == ee_data2)
73355c1b85e2SAlexey Dobriyan 			return ee_data1;
73361da177e4SLinus Torvalds 
73371da177e4SLinus Torvalds 		ee_data1 = ee_data2;
73381da177e4SLinus Torvalds 		i++;
73391da177e4SLinus Torvalds 
73401da177e4SLinus Torvalds 	} while (i < 4);
73411da177e4SLinus Torvalds 
73425c1b85e2SAlexey Dobriyan 	return ee_data1;
73431da177e4SLinus Torvalds }
73441da177e4SLinus Torvalds 
73451da177e4SLinus Torvalds /*---------------------------------------------------------------------
73461da177e4SLinus Torvalds  *
73471da177e4SLinus Torvalds  * Function: Read EEPROM Original
73481da177e4SLinus Torvalds  *
73491da177e4SLinus Torvalds  * Description: Read a word from the EEPROM at the desired
73501da177e4SLinus Torvalds  *              address.
73511da177e4SLinus Torvalds  *
73521da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
73531da177e4SLinus Torvalds 
FPT_utilEEReadOrg(u32 p_port,unsigned short ee_addr)7354391e2f25SKhalid Aziz static unsigned short FPT_utilEEReadOrg(u32 p_port, unsigned short ee_addr)
73551da177e4SLinus Torvalds {
73561da177e4SLinus Torvalds 
7357db038cf8SAlexey Dobriyan 	unsigned char ee_value;
7358c823feebSAlexey Dobriyan 	unsigned short i, ee_data;
73591da177e4SLinus Torvalds 
73605c04a7b8SAlexey Dobriyan 	ee_value =
73615c04a7b8SAlexey Dobriyan 	    (unsigned
73625c04a7b8SAlexey Dobriyan 	     char)((RD_HARPOON(p_port + hp_ee_ctrl) &
73635c04a7b8SAlexey Dobriyan 		    (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
73641da177e4SLinus Torvalds 
736547b5d69cSJames Bottomley  	FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
73661da177e4SLinus Torvalds 
73671da177e4SLinus Torvalds 	ee_value |= (SEE_MS + SEE_CS);
73681da177e4SLinus Torvalds 	ee_data = 0;
73691da177e4SLinus Torvalds 
73701da177e4SLinus Torvalds 	for (i = 1; i <= 16; i++) {
73711da177e4SLinus Torvalds 
73721da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
73731da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73741da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73751da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
73761da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73771da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73781da177e4SLinus Torvalds 
73791da177e4SLinus Torvalds 		ee_data <<= 1;
73801da177e4SLinus Torvalds 
73811da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
73821da177e4SLinus Torvalds 			ee_data |= 1;
73831da177e4SLinus Torvalds 	}
73841da177e4SLinus Torvalds 
73851da177e4SLinus Torvalds 	ee_value &= ~(SEE_MS + SEE_CS);
73861da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
73871da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
73881da177e4SLinus Torvalds 
73895c1b85e2SAlexey Dobriyan 	return ee_data;
73901da177e4SLinus Torvalds }
73911da177e4SLinus Torvalds 
73921da177e4SLinus Torvalds /*---------------------------------------------------------------------
73931da177e4SLinus Torvalds  *
73941da177e4SLinus Torvalds  * Function: Send EE command and Address to the EEPROM
73951da177e4SLinus Torvalds  *
73961da177e4SLinus Torvalds  * Description: Transfers the correct command and sends the address
73971da177e4SLinus Torvalds  *              to the eeprom.
73981da177e4SLinus Torvalds  *
73991da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
74001da177e4SLinus Torvalds 
FPT_utilEESendCmdAddr(u32 p_port,unsigned char ee_cmd,unsigned short ee_addr)7401391e2f25SKhalid Aziz static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
74025c04a7b8SAlexey Dobriyan 				  unsigned short ee_addr)
74031da177e4SLinus Torvalds {
7404db038cf8SAlexey Dobriyan 	unsigned char ee_value;
7405db038cf8SAlexey Dobriyan 	unsigned char narrow_flg;
74061da177e4SLinus Torvalds 
7407c823feebSAlexey Dobriyan 	unsigned short i;
74081da177e4SLinus Torvalds 
74095c04a7b8SAlexey Dobriyan 	narrow_flg =
74105c04a7b8SAlexey Dobriyan 	    (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
74115c04a7b8SAlexey Dobriyan 			    NARROW_SCSI_CARD);
74121da177e4SLinus Torvalds 
74131da177e4SLinus Torvalds 	ee_value = SEE_MS;
74141da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74151da177e4SLinus Torvalds 
74161da177e4SLinus Torvalds 	ee_value |= SEE_CS;	/* Set CS to EEPROM */
74171da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74181da177e4SLinus Torvalds 
74191da177e4SLinus Torvalds 	for (i = 0x04; i != 0; i >>= 1) {
74201da177e4SLinus Torvalds 
74211da177e4SLinus Torvalds 		if (i & ee_cmd)
74221da177e4SLinus Torvalds 			ee_value |= SEE_DO;
74231da177e4SLinus Torvalds 		else
74241da177e4SLinus Torvalds 			ee_value &= ~SEE_DO;
74251da177e4SLinus Torvalds 
74261da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74271da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74281da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
74291da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74301da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74311da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
74321da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74331da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74341da177e4SLinus Torvalds 	}
74351da177e4SLinus Torvalds 
74361da177e4SLinus Torvalds 	if (narrow_flg)
74371da177e4SLinus Torvalds 		i = 0x0080;
74381da177e4SLinus Torvalds 
74391da177e4SLinus Torvalds 	else
74401da177e4SLinus Torvalds 		i = 0x0200;
74411da177e4SLinus Torvalds 
74421da177e4SLinus Torvalds 	while (i != 0) {
74431da177e4SLinus Torvalds 
74441da177e4SLinus Torvalds 		if (i & ee_addr)
74451da177e4SLinus Torvalds 			ee_value |= SEE_DO;
74461da177e4SLinus Torvalds 		else
74471da177e4SLinus Torvalds 			ee_value &= ~SEE_DO;
74481da177e4SLinus Torvalds 
74491da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74501da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74511da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
74521da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74531da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74541da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
74551da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74561da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74571da177e4SLinus Torvalds 
74581da177e4SLinus Torvalds 		i >>= 1;
74591da177e4SLinus Torvalds 	}
74601da177e4SLinus Torvalds }
74611da177e4SLinus Torvalds 
FPT_CalcCrc16(unsigned char buffer[])7462c823feebSAlexey Dobriyan static unsigned short FPT_CalcCrc16(unsigned char buffer[])
74631da177e4SLinus Torvalds {
7464c823feebSAlexey Dobriyan 	unsigned short crc = 0;
74651da177e4SLinus Torvalds 	int i, j;
7466c823feebSAlexey Dobriyan 	unsigned short ch;
74675c04a7b8SAlexey Dobriyan 	for (i = 0; i < ID_STRING_LENGTH; i++) {
7468c823feebSAlexey Dobriyan 		ch = (unsigned short)buffer[i];
74695c04a7b8SAlexey Dobriyan 		for (j = 0; j < 8; j++) {
74701da177e4SLinus Torvalds 			if ((crc ^ ch) & 1)
74711da177e4SLinus Torvalds 				crc = (crc >> 1) ^ CRCMASK;
74721da177e4SLinus Torvalds 			else
74731da177e4SLinus Torvalds 				crc >>= 1;
74741da177e4SLinus Torvalds 			ch >>= 1;
74751da177e4SLinus Torvalds 		}
74761da177e4SLinus Torvalds 	}
74775c1b85e2SAlexey Dobriyan 	return crc;
74781da177e4SLinus Torvalds }
74791da177e4SLinus Torvalds 
FPT_CalcLrc(unsigned char buffer[])7480db038cf8SAlexey Dobriyan static unsigned char FPT_CalcLrc(unsigned char buffer[])
74811da177e4SLinus Torvalds {
74821da177e4SLinus Torvalds 	int i;
7483db038cf8SAlexey Dobriyan 	unsigned char lrc;
74841da177e4SLinus Torvalds 	lrc = 0;
74851da177e4SLinus Torvalds 	for (i = 0; i < ID_STRING_LENGTH; i++)
74861da177e4SLinus Torvalds 		lrc ^= buffer[i];
74875c1b85e2SAlexey Dobriyan 	return lrc;
74881da177e4SLinus Torvalds }
74891da177e4SLinus Torvalds 
74901da177e4SLinus Torvalds /*
74911da177e4SLinus Torvalds   The following inline definitions avoid type conflicts.
74921da177e4SLinus Torvalds */
74931da177e4SLinus Torvalds 
74941da177e4SLinus Torvalds static inline unsigned char
FlashPoint__ProbeHostAdapter(struct fpoint_info * FlashPointInfo)7495839cb99eSKhalid Aziz FlashPoint__ProbeHostAdapter(struct fpoint_info *FlashPointInfo)
74961da177e4SLinus Torvalds {
74975c04a7b8SAlexey Dobriyan 	return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
74985c04a7b8SAlexey Dobriyan 					   FlashPointInfo);
74991da177e4SLinus Torvalds }
75001da177e4SLinus Torvalds 
7501391e2f25SKhalid Aziz static inline void *
FlashPoint__HardwareResetHostAdapter(struct fpoint_info * FlashPointInfo)7502839cb99eSKhalid Aziz FlashPoint__HardwareResetHostAdapter(struct fpoint_info *FlashPointInfo)
75031da177e4SLinus Torvalds {
75045c04a7b8SAlexey Dobriyan 	return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
75055c04a7b8SAlexey Dobriyan 						   FlashPointInfo);
75061da177e4SLinus Torvalds }
75071da177e4SLinus Torvalds 
75081da177e4SLinus Torvalds static inline void
FlashPoint__ReleaseHostAdapter(void * CardHandle)7509391e2f25SKhalid Aziz FlashPoint__ReleaseHostAdapter(void *CardHandle)
75101da177e4SLinus Torvalds {
75111da177e4SLinus Torvalds 	FlashPoint_ReleaseHostAdapter(CardHandle);
75121da177e4SLinus Torvalds }
75131da177e4SLinus Torvalds 
75141da177e4SLinus Torvalds static inline void
FlashPoint__StartCCB(void * CardHandle,struct blogic_ccb * CCB)7515391e2f25SKhalid Aziz FlashPoint__StartCCB(void *CardHandle, struct blogic_ccb *CCB)
75161da177e4SLinus Torvalds {
751769eb2ea4SAlexey Dobriyan 	FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
75181da177e4SLinus Torvalds }
75191da177e4SLinus Torvalds 
75201da177e4SLinus Torvalds static inline void
FlashPoint__AbortCCB(void * CardHandle,struct blogic_ccb * CCB)7521391e2f25SKhalid Aziz FlashPoint__AbortCCB(void *CardHandle, struct blogic_ccb *CCB)
75221da177e4SLinus Torvalds {
752369eb2ea4SAlexey Dobriyan 	FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
75241da177e4SLinus Torvalds }
75251da177e4SLinus Torvalds 
75262065e310SRichard Knutsson static inline bool
FlashPoint__InterruptPending(void * CardHandle)7527391e2f25SKhalid Aziz FlashPoint__InterruptPending(void *CardHandle)
75281da177e4SLinus Torvalds {
75291da177e4SLinus Torvalds 	return FlashPoint_InterruptPending(CardHandle);
75301da177e4SLinus Torvalds }
75311da177e4SLinus Torvalds 
75321da177e4SLinus Torvalds static inline int
FlashPoint__HandleInterrupt(void * CardHandle)7533391e2f25SKhalid Aziz FlashPoint__HandleInterrupt(void *CardHandle)
75341da177e4SLinus Torvalds {
75351da177e4SLinus Torvalds 	return FlashPoint_HandleInterrupt(CardHandle);
75361da177e4SLinus Torvalds }
75371da177e4SLinus Torvalds 
75381da177e4SLinus Torvalds #define FlashPoint_ProbeHostAdapter	    FlashPoint__ProbeHostAdapter
75391da177e4SLinus Torvalds #define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
75401da177e4SLinus Torvalds #define FlashPoint_ReleaseHostAdapter	    FlashPoint__ReleaseHostAdapter
75411da177e4SLinus Torvalds #define FlashPoint_StartCCB		    FlashPoint__StartCCB
75421da177e4SLinus Torvalds #define FlashPoint_AbortCCB		    FlashPoint__AbortCCB
75431da177e4SLinus Torvalds #define FlashPoint_InterruptPending	    FlashPoint__InterruptPending
75441da177e4SLinus Torvalds #define FlashPoint_HandleInterrupt	    FlashPoint__HandleInterrupt
75451da177e4SLinus Torvalds 
754678b4b05dSMatthew Wilcox #else				/* !CONFIG_SCSI_FLASHPOINT */
75471da177e4SLinus Torvalds 
75481da177e4SLinus Torvalds /*
75491da177e4SLinus Torvalds   Define prototypes for the FlashPoint SCCB Manager Functions.
75501da177e4SLinus Torvalds */
75511da177e4SLinus Torvalds 
7552839cb99eSKhalid Aziz extern unsigned char FlashPoint_ProbeHostAdapter(struct fpoint_info *);
7553391e2f25SKhalid Aziz extern void *FlashPoint_HardwareResetHostAdapter(struct fpoint_info *);
7554391e2f25SKhalid Aziz extern void FlashPoint_StartCCB(void *, struct blogic_ccb *);
7555391e2f25SKhalid Aziz extern int FlashPoint_AbortCCB(void *, struct blogic_ccb *);
7556391e2f25SKhalid Aziz extern bool FlashPoint_InterruptPending(void *);
7557391e2f25SKhalid Aziz extern int FlashPoint_HandleInterrupt(void *);
7558391e2f25SKhalid Aziz extern void FlashPoint_ReleaseHostAdapter(void *);
75591da177e4SLinus Torvalds 
756078b4b05dSMatthew Wilcox #endif				/* CONFIG_SCSI_FLASHPOINT */
7561